大家好,欢迎大家学习OpenCV4.8 开发实战专栏,长期更新,不断分享源码。
专栏代码全部基于C++ 与Python双语演示,领学习资料(Free) & 进交流答疑群,+ V: OpenCVXueTang_Asst
本文关键知识点:图像直方图比较
图像直方图比较,就是计算两幅图像的直方图数据,比较两组数据的相似性,从而得到两幅图像之间的相似程度,直方图比较在早期的CBIR中是应用很常见的技术手段,通常会结合边缘处理、词袋等技术一起使用。
OpenCV中直方图比较的API很简单
compareHist(hist1,hist2, method)
-常见比较方法有
相关性
卡方
交叉
巴氏
图像直方图比较是一种用于评估两个图像相似性的技术。直方图表示图像中像素值的分布,通过比较两个图像的直方图,可以推断它们之间的相似性。compareHist(hist1,hist2, method)
函数通常用于OpenCV库中,它提供了多种方法来比较两个直方图。以下是几种方法的解释:
-
相关性(Correlation):
相关性方法测量两个直方图的相似度,其值范围在[-1, 1]之间。值越接近1,表示两个直方图越相似。相关性方法通过计算两个直方图之间的归一化互相关来衡量相似度。公式:
[
\text{Correlation}(H1, H2) = \frac{\sum_{I}(H1(I) - \bar{H1}) \cdot (H2(I) - \bar{H2})}{\sqrt{\sum_{I}(H1(I) - \bar{H1})^2 \cdot \sum_{I}(H2(I) - \bar{H2})^2}}
]
其中, H 1 ( I ) H1(I) H1(I) 和 H 2 ( I ) H2(I) H2(I) 是两个直方图在灰度级I的值, H 1 ˉ \bar{H1} H1ˉ 和 H 2 ˉ \bar{H2} H2ˉ 是它们的平均值。 -
卡方(Chi-Square):
卡方方法通过计算两个直方图之间的卡方统计量来衡量它们之间的差异。卡方值越小,表示两个直方图越相似。卡方方法更敏感于直方图中的较大差异。公式:
[
\text{Chi-Square}(H1, H2) = \sum_{I} \frac{(H1(I) - H2(I))^2}{H1(I) + H2(I)}
] -
交叉(Intersection):
交叉方法通过计算两个直方图交集的和来衡量它们的相似度。交集的和越大,表示两个直方图越相似。这种方法对于直方图中存在相同灰度级的频率较为敏感。公式:
[
\text{Intersection}(H1, H2) = \sum_{I} \min(H1(I), H2(I))
] -
巴氏距离(Bhattacharyya Distance):
巴氏距离是一种衡量两个概率分布之间相似度的度量。在直方图比较中,它用于测量两个直方图之间的相似度。巴氏距离越小,表示两个直方图越相似。公式:
[
\text{Bhattacharyya Distance}(H1, H2) = -\ln\left(\sum_{I} \sqrt{H1(I) \cdot H2(I)}\right)
]
在使用 compareHist
函数时,您可以选择上述方法之一作为参数 method
来比较两个直方图。例如,在OpenCV中,您可以通过以下方式调用该函数:
import cv2
# 假设 hist1 和 hist2 是已经计算好的两个直方图
similarity = cv2.compareHist(hist1, hist2, cv2.HISTCMP_CORREL) # 使用相关性方法
选择哪种方法取决于您的具体应用和所需的相似度度量标准。
演示代码
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int artc, char** argv) {
Mat src1 = imread("D:/vcprojects/images/m1.png");
Mat src2 = imread("D:/vcprojects/images/m2.png");
Mat src3 = imread("D:/vcprojects/images/flower.png");
Mat src4 = imread("D:/vcprojects/images/wm_test.png");
imshow("input1", src1);
imshow("input2", src2);
imshow("input3", src3);
imshow("input4", src4);
Mat hsv1, hsv2, hsv3, hsv4;
cvtColor(src1, hsv1, COLOR_BGR2HSV);
cvtColor(src2, hsv2, COLOR_BGR2HSV);
cvtColor(src3, hsv3, COLOR_BGR2HSV);
cvtColor(src4, hsv4, COLOR_BGR2HSV);
int h_bins = 60; int s_bins = 64;
int histSize[] = { h_bins, s_bins };
float h_ranges[] = { 0, 180 };
float s_ranges[] = { 0, 256 };
const float* ranges[] = { h_ranges, s_ranges };
int channels[] = { 0, 1 };
Mat hist1, hist2, hist3, hist4;
calcHist(&hsv1, 1, channels, Mat(), hist1, 2, histSize, ranges, true, false);
calcHist(&hsv2, 1, channels, Mat(), hist2, 2, histSize, ranges, true, false);
calcHist(&hsv3, 1, channels, Mat(), hist3, 2, histSize, ranges, true, false);
calcHist(&hsv4, 1, channels, Mat(), hist4, 2, histSize, ranges, true, false);
normalize(hist1, hist1, 0, 1, NORM_MINMAX, -1, Mat());
normalize(hist2, hist2, 0, 1, NORM_MINMAX, -1, Mat());
normalize(hist3, hist3, 0, 1, NORM_MINMAX, -1, Mat());
normalize(hist4, hist4, 0, 1, NORM_MINMAX, -1, Mat());
for (int i = 0; i < 4; i++)
{
int compare_method = i;
double src1_src2 = compareHist(hist1, hist2, compare_method);
double src3_src4 = compareHist(hist3, hist4, compare_method);
printf(" Method [%d] : src1_src2 : %f, src3_src4: %f, \n", i, src1_src2, src3_src4);
}
waitKey(0);
return 0;
}
python 代码演示
import cv2 as cv
src1 = cv.imread("D:/images/m1.png")
src2 = cv.imread("D:/images/m2.png")
src3 = cv.imread("D:/images/flower.png")
src4 = cv.imread("D:/images/test.jpg")
cv.imshow("input1", src1)
cv.imshow("input2", src2)
cv.imshow("input3", src3)
cv.imshow("input4", src4)
hsv1 = cv.cvtColor(src1, cv.COLOR_BGR2HSV)
hsv2 = cv.cvtColor(src2, cv.COLOR_BGR2HSV)
hsv3 = cv.cvtColor(src3, cv.COLOR_BGR2HSV)
hsv4 = cv.cvtColor(src4, cv.COLOR_BGR2HSV)
hist1 = cv.calcHist([hsv1], [0, 1], None, [60, 64], [0, 180, 0, 256])
hist2 = cv.calcHist([hsv2], [0, 1], None, [60, 64], [0, 180, 0, 256])
hist3 = cv.calcHist([hsv3], [0, 1], None, [60, 64], [0, 180, 0, 256])
hist4 = cv.calcHist([hsv4], [0, 1], None, [60, 64], [0, 180, 0, 256])
print(hist1.dtype)
cv.normalize(hist1, hist1, 0, 1.0, cv.NORM_MINMAX, dtype=cv.CV_32F)
cv.normalize(hist2, hist2, 0, 1.0, cv.NORM_MINMAX)
cv.normalize(hist3, hist3, 0, 1.0, cv.NORM_MINMAX)
cv.normalize(hist4, hist4, 0, 1.0, cv.NORM_MINMAX)
methods = [cv.HISTCMP_CORREL, cv.HISTCMP_CHISQR,
cv.HISTCMP_INTERSECT, cv.HISTCMP_BHATTACHARYYA]
str_method = ""
for method in methods:
src1_src2 = cv.compareHist(hist1, hist2, method)
src3_src4 = cv.compareHist(hist3, hist4, method)
if method == cv.HISTCMP_CORREL:
str_method = "Correlation"
if method == cv.HISTCMP_CHISQR:
str_method = "Chi-square"
if method == cv.HISTCMP_INTERSECT:
str_method = "Intersection"
if method == cv.HISTCMP_BHATTACHARYYA:
str_method = "Bhattacharyya"
print("%s src1_src2 = %.2f, src3_src4 = %.2f"%(str_method, src1_src2, src3_src4))
cv.waitKey(0)
cv.destroyAllWindows()
结束语
学习贵在坚持,学习OpenCV贵在每一天的代码练习,原理跟基本的函数解释,相关知识,后续更新边学边理解,搞技术永远要坚持做长期主义者!我们一起努力!!!
注:领学习资料(Free) & 进交流答疑群,+ V: OpenCVXueTang_Asst