基于内容的图像检索是计算机视觉的一个重要课题。直方图是标志图像内容的一种有效方式。仅仅通过比较两幅图像的直方图测量出它们的相似度,OpenCV在cv::compareHist函数实现了这些方法。
//Compares two histograms.
double compareHist(InputArray H1, InputArray H2, int method)
其中的method包括:
method – Comparison method that could be one of the following:
– CV_COMP_CORREL Correlation
– CV_COMP_CHISQR Chi-Square
– CV_COMP_INTERSECT Intersection
– CV_COMP_BHATTACHARYYA Bhattacharyya distance
– CV_COMP_HELLINGER Synonym for CV_COMP_BHATTACHARYYA
这里仅仅为测试算法实现,对这些方法的原理不作深究。
首先设定一副参考图像:
1#
蓝天,然后在一堆图像中,搜索相似图像。分别评估它们与参考图像的相似度。待搜索的图像为:
2#
3#
4#
5#
6#(太明显了。。)
相似度评估结果为:
实现代码:
//类声明文件 ImageComparator.h
#pragma once
#include"opencv2/opencv.hpp"
#include"opencv2/core/core.hpp"
#include"opencv2/highgui/highgui.hpp"
//ColorHistogram.h参见另一篇博客:《OpenCV计算和显示图像直方图》
//http://blog.youkuaiyun.com/czl389/article/details/54317839
#include"ColorHistogram.h"
class ImageComparator
{
private:
int nbins;//直方图箱子数量
cv::Mat refH;
cv::Mat inputH;
ColorHistogram hist;
public:
ImageComparator() :nbins(8){}
void setReferenceImage(const cv::Mat& image);
double compare(const cv::Mat& image);
~ImageComparator();
};
//类实现文件 ImageComparator.cpp
#include "ImageComparator.h"
void ImageComparator::setReferenceImage(const cv::Mat& image)
{
hist.setSize(nbins);
refH = hist.getHueHistogram(image,65);
}
double ImageComparator::compare(const cv::Mat& image)
{
inputH = hist.getHueHistogram(image,65);
return cv::compareHist(refH,inputH,CV_COMP_INTERSECT);
}
ImageComparator::~ImageComparator()
{
}
//主文件 main.cpp
//compareHist
cv::Mat refImage = cv::imread("1.jpg");
cv::Mat input1 = cv::imread("2.jpg");
cv::Mat input2 = cv::imread("3.jpg");
cv::Mat input3 = cv::imread("4.jpg");
cv::Mat input4 = cv::imread("5.jpg");
cv::Mat input5 = cv::imread("6.jpg");
ImageComparator cmp;
cmp.setReferenceImage(refImage);
double rate = cmp.compare(refImage);//将参考图像与自身的相似度设为1;
double rate1=cmp.compare(input1)/rate;
double rate2 = cmp.compare(input2) / rate;
double rate3 = cmp.compare(input3) / rate;
double rate4 = cmp.compare(input4) / rate;
double rate5 = cmp.compare(input5) / rate;
std::cout << "similarity" << std::endl;
std::cout <<"1# -> 1#: "<< "1.00" << std::endl
<< "2# -> 1#: " << rate1 << std::endl
<< "3# -> 1#: " << rate2 << std::endl
<< "4# -> 1#: " << rate3 << std::endl
<< "5# -> 1#: " << rate4 << std::endl
<< "6# -> 1#: " << rate5 << std::endl;
std::cout << std::endl;