直方图比较方法
对输入的两张图像计算得到直方图H1和H2,归一化得到相同的尺度空间然后可以通过计算H1和H2之间的距离得到两个直方图相似程度进而比较图像本身的相似程度。opencv提供的比较方法有四种:
- Correlation相关性比较(CV_COMP_CORREL)越接近1越相似
- Chi-Square卡方比较(CV_COMP_CHISQR)越接近0越相似
- Intersection十字交叉性(CV_COMP_INTERSECT)对于相似度比较这个算法不太好
- Bhattacharyya distance巴氏距离(CV_COMP_BHATTACHARYYA)越接近1越相似
直方图一般比较步骤:
- 加载图像
- 将图像色彩空间由BGR转换为HSV空间(由于直方图对亮度和灰度比较敏感,色彩空间转换就是突出这两个因素尽量去除其他因素)
- 计算直方图进行归一化处理,归一化到0到1之间,calcHist和normalize
- 直方图比较,使用上述四种方法之一,compareHist
参考链接:https://blog.csdn.net/shuiyixin/article/details/80257822
API介绍
API
double compareHist(InputArray h1,InputArray H2,int method)
参数介绍
- 第一个参数InputArray类型 h1,直方图数据,下同
- 第二个参数InputArray类型 h2,直方图数据,下同
- 第三个参数int类型 method比较方法,上述四种方法之一
- 返回值:采用上述四中方法之一计算后的两个直方图相关系数
代码演示
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
#define Pic_Path "/home/image/Pictures/my_picture/"
#define Pic_Name "model_1.jpeg"
#define Pic_Name1 "model_1_gray.jpeg"
#define Pic_Name2 "model_1_point.jpeg"
string convertToString(double d) {
ostringstream os;
if (os<<d)
{
return os.str();
}
return "invalid conversion";
}
//直方图比较
int main(void)
{
string pic = string(Pic_Path) + string(Pic_Name);
cout << pic << endl;
string pic1 = string(Pic_Path) + string(Pic_Name1);
cout << pic1 << endl;
string pic2 = string(Pic_Path) + string(Pic_Name2);
cout << pic2 << endl;
cv::Mat src,srctest1,srctest2;
//读取原始图片
src = cv::imread(pic.c_str());
srctest1 = cv::imread(pic1.c_str());
srctest2 = cv::imread(pic2.c_str());
if(src.empty()||srctest1.empty()||srctest2.empty() )
{
cout << "其中有图片不存在" << endl;
return -1;
}
cv::namedWindow("src",cv::WINDOW_AUTOSIZE);
cv::imshow("src",src);
cv::namedWindow("srctest1",cv::WINDOW_AUTOSIZE);
cv::imshow("srctest1",srctest1);
cv::namedWindow("srctest2",cv::WINDOW_AUTOSIZE);
cv::imshow("srctest2",srctest2);
//从RGB色彩空间转化为HSV色彩空间 色调、饱和度、亮度
cvtColor(src, src, CV_BGR2HSV);
cvtColor(srctest1, srctest1, CV_BGR2HSV);
cvtColor(srctest2, srctest2, CV_BGR2HSV);
//定义直方图计算所需要的各种参数
int h_bins = 50; //直方图通道1色调级数
int s_bins = 60; //直方图通道2饱和度级数
int histSize[] = { h_bins,s_bins }; //直方图计算函数中的直方图级数参数
float h_ranges[] = { 0,180 }; //直方图通道0色调通道值域范围
float s_ranges[] = { 0,256 }; //直方图通道1饱和度通道值域范围
const float* ranges[] = { h_ranges, s_ranges }; //直方图计算函数中的直方图值域范围参数
int channels[] = { 0,1 }; //直方图计算函数中的通道参数
//MatND 是 Mat的别名,方便区分经过直方图计算处理后和输入图像
MatND hist_src;
MatND hist_srctest1;
MatND hist_srctest2;
//计算直方图并归一化处理
//原始图像 图像数目 通道数 MAsk 输出直方图数据 维数 直方图级数 值域范围 默认参数1 默认参数2
//const Mat* int const int* InputArray OutputArray int const int* const float* bool bool
calcHist(&src, 1, channels, Mat(), hist_src, 2, histSize, ranges, true, false);
normalize(hist_src, hist_src, 0, 1, NORM_MINMAX, -1, Mat());
calcHist(&srctest1, 1, channels, Mat(), hist_srctest1, 2, histSize, ranges, true, false);
normalize(hist_srctest1, hist_srctest1, 0, 1, NORM_MINMAX, -1, Mat());
calcHist(&srctest2, 1, channels, Mat(), hist_srctest2, 2, histSize, ranges, true, false);
normalize(hist_srctest2, hist_srctest2, 0, 1, NORM_MINMAX, -1, Mat());
//直方图比较
double src_src = compareHist(hist_src, hist_src, CV_COMP_CORREL);
double src_srctest1 = compareHist(hist_src, hist_srctest1, CV_COMP_CORREL);
double src_srctest2 = compareHist(hist_src, hist_srctest2, CV_COMP_CORREL);
//打印计算后的相关性值
cout << "src compare with src correlation value : " << src_src << endl;
cout << "src compare with srctest1 correlation value : " << src_srctest1 << endl;
cout << "src compare with srctest2 correlation value : " << src_srctest2 << endl;
//给每个图像上添加文字,内容为该图片和原始图片的比较结果
putText(src, convertToString(src_src), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 255, 255), 2, LINE_AA);
putText(srctest1, convertToString(src_srctest1), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);
putText(srctest2, convertToString(src_srctest2), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(255, 0, 255), 2, LINE_AA);
//图像的显示
namedWindow("自身比较", CV_WINDOW_AUTOSIZE);
namedWindow("灰度比较", CV_WINDOW_AUTOSIZE);
namedWindow("杂质比较", CV_WINDOW_AUTOSIZE);
//namedWindow(OUTPUT_TITLE, CV_WINDOW_AUTOSIZE);
imshow("自身比较", src);
imshow("灰度比较", srctest1);
imshow("杂质比较", srctest2);
cv::waitKey(0);
cv::destroyAllWindows();
}
运行结果
/home/image/Pictures/my_picture/model_1.jpeg
/home/image/Pictures/my_picture/model_1_gray.jpeg
/home/image/Pictures/my_picture/model_1_point.jpeg
src compare with src correlation value : 1
src compare with srctest1 correlation value : -0.00129504
src compare with srctest2 correlation value : 0.999878
原始图片
计算结果
补充知识
色调 H : 0 ~ 180
用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°, 蓝色为240°。它们的补色是:黄色为60°,青色为180°, 品红为300°;
饱和度 S :0 ~ 255
饱和度S表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和。
亮度 V : 0 ~ 255
亮度表示颜色明亮的程度,对于光源色,亮度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。