这个是之前学习openCV时做过的,时间长了怕找不到,还是写下来的好。
首先,图像直方图是什么?图像直方图是用以表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像素数。
直方图的意义:
1、直方图是图像中像素强度分布的图形表达方式。
2、它统计了每一个强度值所具有的像素个数。
openCV中封装了计算直方图的函数calcHist(),调用这个函数可以很方便的计算图像的颜色直方图。不过有一点需要注意,图像要转成HSV 格式,之后要定义bin的数目,也就是分成几个格子然后分别统计落在这些格子中的像素数。还有一些问题就直接结合代码说了。
另外,用于计算直方图相似度的函数是compareHist(),这个是CV的一个内建函数,可以直接调用。这个函数有4种距离标准可以选择。
参数:
0--相关系数,取值[-1,1],值越大相关性越好,说明越相似。
1--卡方,值越小越相似。
2--直方图相交,越是相似的图,这个值越大
3--Bhattacharyya距离,越小越好。
公式不好敲,大家有兴趣的可以百度看一下。。。。。。。。。。
//标准格式,没有什么可说的。
#include
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
int main()
{
//申请用于存储图像数据的Mat容器,src表示原始图像,hsv表示转换成hsv格式的图像
Mat srcImage_base,hsvImage_base;
Mat srcImage_test1,hsvImage_test1;
Mat srcImage_test2,hsvImage_test2;
Mat hsvImage_halfDown;
//我用的图,一张基准图,两张相似的测试图
srcImage_base=imread("n01443537_84.JPEG");
srcImage_test1=imread("n01443537_129.JPEG");
srcImage_test2=imread("n01443537_130.JPEG");
imshow("base",srcImage_base);
imshow("test1",srcImage_test1);
imshow("test2",srcImage_test2);
//转换图像格式
cvtColor(srcImage_base,hsvImage_base,COLOR_BGR2HSV);
cvtColor(srcImage_test1,hsvImage_test1,COLOR_BGR2HSV);
cvtColor(srcImage_test2,hsvImage_test2,COLOR_BGR2HSV);
//截取原始图像的半身图用于对比测试
hsvImage_halfDown=hsvImage_base(Range(hsvImage_base.rows/2,hsvImage_base.rows-1),Range(0,hsvImage_base.cols-1));
//h,s对应的bin的数目分别是50,60,即是把h范围是(0,255)的数分成50份分别统计每一份中的像素数。
int h_bins=50;int s_bins=60;
int histSize[]={h_bins,s_bins};
float h_ranges[]={0,256};
float s_ranges[]={0,180};
const float* ranges[]={h_ranges,s_ranges};
//只计算了h,s两个通道,所以channels是0和1
int channels[]={0,1};
//MatND 类型的容器用于存储calcHist计算出的直方图
MatND baseHist;
MatND halfDownHist;
MatND testHist1;
MatND testHist2;
calcHist(&hsvImage_base,1,channels,Mat(),baseHist,2,histSize,ranges,true,false);
normalize(baseHist,baseHist,0,1,NORM_MINMAX,-1,Mat());
calcHist(&hsvImage_halfDown,1,channels,Mat(),halfDownHist,2,histSize,ranges,true,false);
normalize(halfDownHist,halfDownHist,0,1,NORM_MINMAX,-1,Mat());
calcHist(&hsvImage_test1,1,channels,Mat(),testHist1,2,histSize,ranges,true,false);
normalize(testHist1,testHist1,0,1,NORM_MINMAX,-1,Mat());
calcHist(&hsvImage_test2,1,channels,Mat(),testHist2,2,histSize,ranges,true,false);
normalize(testHist2,testHist2,0,1,NORM_MINMAX,-1,Mat());
//分别用上述4种基准计算直方图之间的相似度
//基准图和基准图,基准图和半身基准图,基准图和测试图1,基准图和测试图2
for(int i=0;i<4;i++)
{
int compare_method=i;
double base_base=compareHist(baseHist,baseHist,compare_method);
double base_half=compareHist(baseHist,halfDownHist,compare_method);
double base_test1=compareHist(baseHist,testHist1,compare_method);
double base_test2=compareHist(baseHist,testHist2,compare_method);
printf("method[%d]result: \n\n base-base: %f, base-halfbase: %f, base-test1: %f, base-test2: %f \n----------------------------\n",i,base_base,base_half,base_test1,base_test2);
}
printf("All done");
waitKey(0);
return 0;
}
输出的结果如下:
从结果分析,直方图只能做相同图像相同事物的比较,在做相似性图像的比较时效果较差,很难直接用于工业上的图像的相似性检索等工作。