opencv-compareHist直方图比较
对输入的两张图像进行直方图均衡化及直方图计算步骤后,可以对两个图像的直方图进行对比
步骤
a.先用cvtColor()把图像从RGB色彩空间转换到HSV色彩空间;
b.计算图像的直方图,然后归一化到[0~1]之间,用到函数 calcHist() 和 normalize() ;
c.使用四种方法之一进行比较,用到函数compareHist()
实例
lm.jpg
lm1.jpg
lm2.jpg
#include<opencv2/opencv.hpp> #include<iostream> int main(int argc, char** argv) { cv::Mat src1 = cv::imread("D:/bb/tu/lm.jpg"); cv::Mat src2 = cv::imread("D:/bb/tu/lm1.jpg"); cv::Mat src3 = cv::imread("D:/bb/tu/lm2.jpg"); if (!src1.data || !src2.data || !src3.data) { std::cout << "图片导入错误"; return -1; } imshow("【src1原图】", src1); imshow("【src2原图】", src2); imshow("【src3原图】", src3); //从RGB色彩空间转化为HSV色彩空间,对 HS 两通道进行直方图统计 cvtColor(src1, src1, cv::COLOR_BGR2HSV); cvtColor(src3, src3, cv::COLOR_BGR2HSV); cvtColor(src2, src2, cv::COLOR_BGR2HSV); //定义直方图计算所需要的各种参数 int h_bins = 50; //H通道分成50份 int s_bins = 60; //S通道分成60份 int histSize[] = { h_bins,s_bins }; float h_ranges[] = { 0,180 }; //H通道x轴取值范围0-180 float s_ranges[] = { 0,256 }; //S通道x轴取值范围0-256 const float* ranges[] = { h_ranges, s_ranges }; int channels[] = { 0,1 };//对H和S两个通道进行直方图计算 //MatND 是 Mat的别名,方便区分经过直方图计算处理后和输入图像 cv::MatND hist_src1; cv::MatND hist_src2; cv::MatND hist_src3; //计算直方图并归一化处理 calcHist(&src1, 3, channels, cv::Mat(), hist_src1, 2, histSize, ranges, true, false); /* 参数2:由于图像是3通道的彩色图像,每个通道看做一个图像,所以是3 参数5: 【 h_bins行,s_bins = 60列 】 参数7:H通道的x轴被分成180分,S通道的x轴被分成255分 参数8:H通道的x轴取值范围是r1,S通道的x轴取值范围是r2 */ normalize(hist_src1, hist_src1, 0, 1, cv::NORM_MINMAX, -1, cv::Mat()); calcHist(&src2, 3, channels, cv::Mat(), hist_src2, 2, histSize, ranges, true, false); normalize(hist_src2, hist_src2, 0, 1, cv::NORM_MINMAX, -1, cv::Mat()); calcHist(&src3, 3, channels, cv::Mat(), hist_src3, 2, histSize, ranges, true, false); normalize(hist_src3, hist_src3, 0, 1, cv::NORM_MINMAX, -1, cv::Mat()); double src1_src1 = cv::compareHist(hist_src1, hist_src1, cv::HISTCMP_CORREL);//直方图比较 /* 参数1:比较图像1 参数2:比较图像2 参数3:比较方法 cv::HISTCMP_CORREL-->相关性比较(Correlation),取值为[0,1],越接近1,直方图相似度越高 cv::HISTCMP_CHISQR-->卡方Chi-square,取值为[0,1],越接近0,直方图相似度越高 cv::HISTCMP_INTERSECT-->相交Intersection, cv::HISTCMP_BHATTACHARYYA-->巴氏距离Bhattacharyya,在直方图相似度计算时,巴氏距离获得的 效果最好,但计算是最为复杂的。巴氏距离的计算结果,其值完全匹配为1,完全不匹配则为0 */ std::cout << "src1与src1相关性比较结果:" << src1_src1 << std::endl; // 1 double src1_src2 = cv::compareHist(hist_src1, hist_src2, cv::HISTCMP_CORREL); std::cout << "src1与src2相关性比较结果:" << src1_src2 << std::endl; //0.0287919 double src1_src3 = cv::compareHist(hist_src1, hist_src3, cv::HISTCMP_CORREL); std::cout << "src1与src3相关性比较结果:" << src1_src3 << std::endl; //0.0287075 cv::waitKey(0); return 0; }
比较方法:
相关性比较(Correlation)
相关性比较公式如下:
其中
如果H1 = H2,即两个图的直方图一样,分子等于分母,值为1,所以在不严格的情况下,当值为1时,可以认为两个图是一样的。但是也有可能会出现两个图不一样,但是两个图的直方图是一样的情况。因为直方图计算的是像素点个数的分布情况,但是不会显示像素点的位置,所以有可能会出现两幅图片不一样,但是相同像素的个数完全一样,那他们的直方图也是一样的,不过这种情况不常有