#1, principle
Each picture can generate a histogram of color distributions (histogram). If the histogram of the two pictures is close enough, you can think of them as similar.
Any one color is made up of red, green, and Blue (RGB), so there are 4 histogram (the histogram of the primary color + the last synthesized straight-side graph).
If you can take 256 values for each primary color, there are 16 million colors (256 of three) for the entire colour space. For these 16 million kinds of color comparison histogram, the calculation is too large, so the need to adopt a simplified method. 0~255 can be divided into four districts: 0~63 is the No. 0 district, 64~127 is 1th, 128~191 is 2nd, and 192~255 is the 3rd area. This means that red and green blue have 4 zones, which can form a total of 64 combinations (4 of 3).
Any one color is bound to belong to one of these 64 combinations, so you can count the number of pixels that each combination contains.
is a picture of the color distribution table, the last column in the table is extracted, composed of a 64-dimensional vector (7414, 230, 0, 0, 8, ..., 109, 0, 0, 3415, 53929). This vector is the characteristic value of this image or "fingerprint".
So, looking for a similar image becomes the vector that finds its closest resemblance. This can be calculated using Pearson correlation coefficients or cosine similarity.
#2, C + + code implementation
#include <math.h>
#include <bitset>
#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <time.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace Std;
using namespace CV;
void getRGB (Mat &pic, Vector<int > &pixvec);
int Bit2int (bitset<2>& bbit, bitset<2>& Gbit, bitset<2>& rbit);
Bitset<2> classify (int val);
Double Correlation (vector<int> &pix1, vector<int> &pix2);
void Getnamefromtxt (vector<string> &orignamepic, String FileName, string origfilename);
int main () {
Double beginTime = clock ();
String Filename= "RawData";
String oeder1 = "DIR. \ \" + FileName + "\\*.jpg/b >filenamelist.txt";
System (OEDER1.C_STR ());
Vector<string> Picname;
Getnamefromtxt (Picname, FileName, "FileNameList.TXT");
int piclen = Picname.size ();
for (int m = 0; m < Piclen; m++) {
cout << "Compare" << m << "-th picture with the others!" << Endl;
for (int n = m+1; n < Piclen; n++) {
Mat Pic1 = Imread (Picname[m], 1);
Mat Pic2 = Imread (Picname[n], 1);
Pixvec
Vector<int> Pix1vec (64, 0);
getRGB (Pic1, Pix1vec);
Vector<int> Pix2vec (64, 0);
getRGB (Pic2, Pix2vec);
Double correlval = correlation (Pix1vec, Pix2vec);
cout << "The value of correlation coefficient is:" << correlval << Endl;
if (Correlval > 0.999999) {
String movepic = "move. \ \" + picname[m]+ "Deletepic >nul";
System (MOVEPIC.C_STR ());
Break
}
}
}
Double endTime = clock ();
cout << "BeginTime:" << beginTime << Endl
<< "EndTime:" << endTime << Endl
<< "Endtime-begintime:" << endtime-begintime << "MS" << Endl;
System ("Pause");
return 0;
}
void Getnamefromtxt (vector<string> &orignamepic, String fileName, String origfilename) {
Ifstream Orignamein (origfilename);
while (! Orignamein.eof ()) {
String Cachenameo;
Getline (Orignamein, Cachenameo);
int len = Cachenameo.size ();
if (len>0) {
String realname = fileName + "\ \" + Cachenameo;
Orignamepic.push_back (Realname);
}
}
Orignamein.close ();
String order = "Del" + Origfilename;
System (ORDER.C_STR ());
}
void getRGB (Mat &pic, Vector<int > &pixvec) {
int rownum=pic.rows;
int colnum=pic.cols;
int Pixnum=colnum*pic.channels ();
if (Pic.channels ()!=3)
cout<< "The channel of the picture was not 3!" <<endl;
Mat_<vec3b>::iterator it=pic.begin<vec3b> ();
Mat_<vec3b>::iterator itend=pic.end<vec3b> ();
for (; it!=itend;++it) {
Bitset<2> Bpix,gpix,rpix;
Bpix=classify ((*it) [0]);
Gpix=classify ((*it) [1]);
Rpix=classify ((*it) [2]);
int Clasval=bit2int (Bpix, Gpix, Rpix);
pixvec[clasval]++;
}
}
int Bit2int (bitset<2>& bbit,bitset<2>& gbit,bitset<2>& rbit) {
Bitset<6> Bitval;
for (int i=0;i<2;i++) {
Bitval[0*2+i]=rbit[i];
Bitval[1*2+i]=gbit[i];
Bitval[2*2+i]=bbit[i];
}
return Bitval.to_ulong ();
}
Bitset<2> classify (int val) {
if (val<64) {
bitset<2> bitval (0);
return bitval;
}
Else if (val<128) {
bitset<2> bitval (1);
return bitval;
}
Else if (val<192) {
bitset<2> bitval (2);
return bitval;
}
Else {//if (val<256)
bitset<2> bitval (3);
return bitval;
}
}
Double Correlation (vector<int> &pix1, vector<int> &pix2) {
Double xysum=0.0, xsum=0.0, ysum=0.0;
Double xmean=0.0, ymean=0.0;
int len=pix1.size ();
for (int i=0; i<len; i++) {
Xmean + = Pix1[i];
Ymean + = Pix2[i];
}
Xmean = (double) xmean/(double) Len;
Ymean = (double) ymean/(double) Len;
for (int j=0;j<len;j++) {
Xysum + = ((double) pix1[j]-xmean) * ((double) pix2[j]-ymean);
Xsum + = ((double) pix1[j]-xmean) * ((double) pix1[j]-xmean);
Ysum + = ((double) pix2[j]-ymean) * ((double) pix2[j]-ymean);
}
Double finalval= (double) xysum/(double) (sqrt (Xsum) *sqrt (ysum));
return finalval;
}
#3, program Run results
The principle and implementation of similarity image search--color distribution method