// compact image comparison vactor generator // mainly to be used via IPC in read-from-stdin mode // requires CImg.h, adjust the include as needed // cvs -d:pserver:anonymous@cimg.cvs.sourceforge.net:/cvsroot/cimg co CImg // compile: g++ -o hashimg hashimg.cpp // function ph_dct_matrix and the PHASH section of do_hash (ph_dct_imagehash) // liberated from pHash.ccp which had the following blurb: /* pHash, the open source perceptual hash library Copyright (C) 2009 Aetilius, Inc. All rights reserved. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Evan Klinger - eklinger@phash.org D Grant Starkweather - dstarkweather@phash.org */ // based on ph_dct_imagehash from http://www.phash.org/ #define PHASH 1 // based on average hash from http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html #define AHASH 1 // based on rgb4x4 from http://www.stonehenge.com/merlyn/LinuxMag/col50.html #define RHASH 1 // enables for various debugprints all over the place. noisy. #define DEBUG_PHASH 0 #define DEBUG_AHASH 0 #define DEBUG 0 #define cimg_debug 0 #define cimg_display 0 #include "CImg/CImg.h" using namespace cimg_library; #include #include #include #include #include #include #include #include #include #include #include #include #define __STDC_CONSTANT_MACROS #include CImg* ph_dct_matrix(const int N){ CImg *ptr_matrix = new CImg(N,N,1,1,1/sqrt((float)N)); const float c1 = sqrt(2.0/N); for (int x=0;xdata(x,y) = c1*cos((cimg::PI/2/N)*y*(2*x+1)); } } return ptr_matrix; } void hexprint(char *a, int count, int spacer){ int i; char h[] = "0123456789abcdef"; for (i=0;i>4)&0x0f],h[a[i]&0x0f]); } } int hashgen(CImg *data, char *hash, int bitcount, float limit, int doprint=0) { int bc = 0; for (int i=0;i< bitcount;i++){ float current = (*data)(i); if (current >= limit) { hash[int(i/8)] |= (0x80 >> (i%8)); bc++; if (doprint) { printf("1"); } } else { if (doprint) { printf("0"); } } } return bc; } int do_hash(char *file) { if (!file){ return -1; } printf("FILE: %s", file); CImg osrc; try { osrc.load(file); } catch (CImgIOException ex){ return -1; } // working copy CImg src = osrc; float median, mean; unsigned long long hash; int bc; CImg img; CImg subsec; #if PHASH // // PHASH SECTION // //int ph_dct_imagehash(const char* file,ulong64 &hash){ // img = src.get_convolve(meanfilter); // img.save("test2.png"); CImg meanfilter(7,7,1,1,1); CImg *C = ph_dct_matrix(32); CImg Ctransp = C->get_transpose(); if (src.spectrum() == 3){ #if DEBUG_PHASH printf(" b1"); #endif img = src.RGBtoYCbCr().channel(0).get_convolve(meanfilter); } else if (src.spectrum() == 4){ #if DEBUG_PHASH printf(" b2"); #endif int width = src.width(); int height = src.height(); int depth = src.depth(); img = src.crop(0,0,0,0,width-1,height-1,depth-1,2).RGBtoYCbCr().channel(0).get_convolve(meanfilter); } else { #if DEBUG_PHASH printf(" b3"); #endif img = src.channel(0).get_convolve(meanfilter); } // img.save("step3a.png"); img.resize(32,32); #if DEBUG_PHASH printf("\nimg:\n"); for (int i=0;i< 3;i++){ for (int j=0;j< 10;j++){ float v = img(j,i); printf(" %f", v); } printf("\n"); } // img.save("step3b.png"); printf("\nC:\n"); for (int i=0;i< 3;i++){ for (int j=0;j< 10;j++){ float v = (*C)(j,i); printf(" %f", v); } printf("\n"); } printf("\nCtransp:\n"); for (int i=0;i< 3;i++){ for (int j=0;j< 10;j++){ float v = Ctransp(j,i); printf(" %f", v); } printf("\n"); } #endif CImg dctImage = (*C)*img*Ctransp; // dctImage.save("step4b.png"); #if DEBUG_PHASH printf("\ndctImage:\n"); for (int i=0;i< 3;i++){ for (int j=0;j< 10;j++){ float v = dctImage(j,i); printf(" %f", v); } printf("\n"); } #endif dctImage.crop(1,1,8,8); #if DEBUG_PHASH printf("\nsec:\n"); for (int i=0;i< 8;i++){ for (int j=0;j< 8;j++){ float v = dctImage(j,i); printf(" %15f", v); } printf("\n"); } #endif subsec = dctImage.unroll('x');; median = subsec.median(); mean = subsec.mean(); #if DEBUG_PHASH printf("median: %.10f\n", median); printf("mean: %.10f\n", mean); #endif hash = 0; printf("\nPHASH(median,%s): ", file); bc = hashgen(&subsec, (char*)&hash, 64, median, 1); printf(" %i %llu ", bc, hash); hexprint((char*)&hash, 8, 8); printf("\n"); hash = 0; printf("\nPHASH(mean,%s): ", file); bc = hashgen(&subsec, (char*)&hash, 64, mean, 1); printf(" %i %llu ", bc, hash); hexprint((char*)&hash, 8, 8); printf("\n"); delete C; #endif // PHASH #if AHASH // // AHASH SECTION // src = osrc; src.resize(8,8,-100,-100,2); // src.save("test3ff.png"); // this seems to be an attempt to get rid of alpha channel by applying it if (src.spectrum() == 4){ #if DEBUG_AHASH printf(" c2"); #endif int width = src.width(); int height = src.height(); int depth = src.depth(); src = src.crop(0,0,0,0,width-1,height-1,depth-1,2); } if (src.spectrum() == 3){ #if DEBUG_AHASH printf(" c1"); #endif #if MANUAL_GRAYSCALE C = new CImg(8,8,1,1,0); for (int i=0;i<8;i++){ for (int j=0;j<8;j++){ //(*C)(i,j) = 0.2989*src(i,j,0) + 0.5870*src(i,j,1) + 0.1140*src(i,j,2); (*C)(i,j) = (src(i,j,0)*src(i,j,0)) + (src(i,j,1)*src(i,j,1)) + (src(i,j,2)*src(i,j,2)); //(*C)(i,j) = src(i,j,0) + src(i,j,1) + src(i,j,2); //(*C)(i,j) = (src(i,j,0) + src(i,j,1) + src(i,j,2))/3; } } img = (*C); delete C; #else img = src.RGBtoYCbCr().channel(0); //.get_convolve(meanfilter); #endif } else { #if DEBUG_AHASH printf(" c3"); #endif img = src.channel(0); } #if DEBUG_AHASH printf("\nimg:\n"); for (int i=0;i< 8;i++){ for (int j=0;j< 8;j++){ float v = img(j,i); printf(" %f", v); } printf("\n"); } #endif subsec = img.unroll('x'); median = subsec.median(); mean = subsec.mean(); #if DEBUG_AHASH printf("median: %.10f\n", median); printf("mean: %.10f\n", mean); #endif hash = 0; printf("\nAHASH(median,%s): ", file); bc = hashgen(&subsec, (char*)&hash, 64, median, 1); printf(" %i %llu ", bc, hash); hexprint((char *)&hash, 8, 8); printf("\n"); hash = 0; printf("\nAHASH(mean,%s): ", file); bc = hashgen(&subsec, (char*)&hash, 64, mean, 1); printf(" %i %llu ", bc, hash); hexprint((char *)&hash, 8, 8); printf("\n"); #endif // AHASH #if RHASH src = osrc; src.resize(4,4,-100,-100,2); //src.save("testnbid.png"); char buf[48]; for (int i=0;i<48;i++){ buf[i] = src(int(i/3)%4,int(i/12),i%3); } printf("\nRHASH(%s): urn:rgb4x4:", file); hexprint(&buf[0], 48, 48); printf("\n"); # endif // RHASH return 0; } int main(int argc,char*argv[]){ // process files from commandline if (argc > 1) { for (int i=1;i