#if !defined COLHISTOGRAM
#define COLHISTOGRAM
#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>
class ColorHistogram {
private:
int histSize[3];
float hranges[2];
const float* ranges[3];
int channels[3];
public:
ColorHistogram() {
// Prepare arguments for a color histogram
histSize[0]= histSize[1]= histSize[2]= 256;
hranges[0]= 0.0; // BRG range
hranges[1]= 255.0;
ranges[0]= hranges; // all channels have the same range
ranges[1]= hranges;
ranges[2]= hranges;
channels[0]= 0; // the three channels
channels[1]= 1;
channels[2]= 2;
}
// Computes the histogram.
cv::MatND getHistogram(const cv::Mat &image) {
cv::MatND hist;
// BGR color histogram
hranges[0]= 0.0; // BRG range
hranges[1]= 255.0;
channels[0]= 0; // the three channels
channels[1]= 1;
channels[2]= 2;
// Compute histogram
cv::calcHist(&image,
1, // histogram of 1 image only
channels, // the channel used
cv::Mat(), // no mask is used
hist, // the resulting histogram
3, // it is a 3D histogram
histSize, // number of bins
ranges // pixel value range
);
return hist;
}
// Computes the histogram.
cv::SparseMat getSparseHistogram(const cv::Mat &image) {
cv::SparseMat hist(3,histSize,CV_32F);
// BGR color histogram
hranges[0]= 0.0; // BRG range
hranges[1]= 255.0;
channels[0]= 0; // the three channels
channels[1]= 1;
channels[2]= 2;
// Compute histogram
cv::calcHist(&image,
1, // histogram of 1 image only
channels, // the channel used
cv::Mat(), // no mask is used
hist, // the resulting histogram
3, // it is a 3D histogram
histSize, // number of bins
ranges // pixel value range
);
return hist;
}
// Computes the 2D ab histogram.
// BGR source image is converted to Lab
cv::MatND getabHistogram(const cv::Mat &image) {
cv::MatND hist;
// Convert to Lab color space
cv::Mat lab;
cv::cvtColor(image, lab, CV_BGR2Lab);
// Prepare arguments for a 2D color histogram
hranges[0]= -128.0;
hranges[1]= 127.0;
channels[0]= 1; // the two channels used are ab
channels[1]= 2;
// Compute histogram
cv::calcHist(&lab,
1, // histogram of 1 image only
channels, // the channel used
cv::Mat(), // no mask is used
hist, // the resulting histogram
2, // it is a 2D histogram
histSize, // number of bins
ranges // pixel value range
);
return hist;
}
// Computes the 1D Hue histogram with a mask.
// BGR source image is converted to HSV
cv::MatND getHueHistogram(const cv::Mat &image) {
cv::MatND hist;
// Convert to Lab color space
cv::Mat hue;
cv::cvtColor(image, hue, CV_BGR2HSV);
// Prepare arguments for a 1D hue histogram
hranges[0]= 0.0;
hranges[1]= 180.0;
channels[0]= 0; // the hue channel
// Compute histogram
cv::calcHist(&hue,
1, // histogram of 1 image only
channels, // the channel used
cv::Mat(), // no mask is used
hist, // the resulting histogram
1, // it is a 1D histogram
histSize, // number of bins
ranges // pixel value range
);
return hist;
}
cv::Mat colorReduce(const cv::Mat &image, int div=64) {
int n= static_cast<int>(log(static_cast<double>(div))/log(2.0));
// mask used to round the pixel value
uchar mask= 0xFF<<n; // e.g. for div=16, mask= 0xF0
cv::Mat_<cv::Vec3b>::const_iterator it= image.begin<cv::Vec3b>();
cv::Mat_<cv::Vec3b>::const_iterator itend= image.end<cv::Vec3b>();
// Set output image (always 1-channel)
cv::Mat result(image.rows,image.cols,image.type());
cv::Mat_<cv::Vec3b>::iterator itr= result.begin<cv::Vec3b>();
for ( ; it!= itend; ++it, ++itr) {
(*itr)[0]= ((*it)[0]&mask) + div/2;
(*itr)[1]= ((*it)[1]&mask) + div/2;
(*itr)[2]= ((*it)[2]&mask) + div/2;
}
return result;
}
};
#endif
#if !defined ICOMPARATOR
#define ICOMPARATOR
#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include "ColorHistogram.h"
class ImageComparator {
private:
cv::Mat reference;
cv::Mat input;
cv::MatND refH;
cv::MatND inputH;
ColorHistogram hist;
int div;
public:
ImageComparator() : div(32) {
}
// Color reduction factor
// The comparaison will be made on images with
// color space reduced by this factor in each dimension
void setColorReduction( int factor) {
div= factor;
}
int getColorReduction() {
return div;
}
void setReferenceImage(const cv::Mat& image) {
reference= hist.colorReduce(image,div);
refH= hist.getHistogram(reference);
}
double compare(const cv::Mat& image) {
input= hist.colorReduce(image,div);
inputH= hist.getHistogram(input);
return cv::compareHist(refH,inputH,CV_COMP_INTERSECT);
}
};
#endif
#include <iostream>
using namespace std;
#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include "imageComparator.h"
int main()
{
// Read reference image
cv::Mat image= cv::imread("D:/test/opencv/waves.jpg");
if (!image.data)
return 0;
// Display image
cv::namedWindow("Query Image");
cv::imshow("Query Image",image);
ImageComparator c;
c.setReferenceImage(image);
// Read an image and compare it with reference
cv::Mat input= cv::imread("D:/test/opencv/dog.jpg");
cout << "waves vs dog: " << c.compare(input) << endl;
// Read an image and compare it with reference
input= cv::imread("D:/test/opencv/marais.jpg");
cout << "waves vs marais: " << c.compare(input) << endl;
// Read an image and compare it with reference
input= cv::imread("D:/test/opencv/bear.jpg");
cout << "waves vs bear: " << c.compare(input) << endl;
// Read an image and compare it with reference
input= cv::imread("D:/test/opencv/beach.jpg");
cout << "waves vs beach: " << c.compare(input) << endl;
// Read an image and compare it with reference
input= cv::imread("D:/test/opencv/polar.jpg");
cout << "waves vs polar: " << c.compare(input) << endl;
// Read an image and compare it with reference
input= cv::imread("D:/test/opencv/moose.jpg");
cout << "waves vs moose: " << c.compare(input) << endl;
// Read an image and compare it with reference
input= cv::imread("D:/test/opencv/lake.jpg");
cout << "waves vs lake: " << c.compare(input) << endl;
// Read an image and compare it with reference
input= cv::imread("D:/test/opencv/fundy.jpg");
cout << "waves vs fundy: " << c.compare(input) << endl;
cv::waitKey(0);
return 0;
}