直方圖比較方法-概述
對輸入的兩張圖像計算得到直方圖H1與H2,歸一化到相同的尺度空間
然后可以通過計算H1與H2的之間的距離得到兩個直方圖的相似程度進
而比較圖像本身的相似程度。Opencv提供的比較方法有四種:
- Correlation 相關(guān)性比較 -(計算結(jié)果范圍為 -1到1 -1很不相關(guān),1完全一樣 )
- Chi-Square 卡方比較 -(計算結(jié)果越接近0,兩個直方圖越相似)
- Intersection 十字交叉性 -(計算公式為取兩個直方圖每個相同位置的值的最小值,然后求和,這個比較方式不是很好,不建議使用)
- Bhattacharyya distance 巴氏距離 - (比較結(jié)果是很準的,計算結(jié)果范圍為 0-1 ,0表示兩個直方圖非常相關(guān),1最不相似)
1. 直方圖比較方法-相關(guān)性計算(CV_COMP_CORREL)
計算結(jié)果范圍為 -1到1 -1很不相關(guān),1完全一樣
2. 直方圖比較方法-卡方計算(CV_COMP_CHISQR)
計算結(jié)果越接近0,兩個直方圖越相似
H1,H2分別表示兩個圖像的直方圖數(shù)據(jù)
3. 直方圖比較方法-十字計算(CV_COMP_INTERSECT)
計算公式為取兩個直方圖每個相同位置的值的最小值,然后求和,這個比較方式不是很好,不建議使用
H1,H2分別表示兩個圖像的直方圖數(shù)據(jù)
4. 直方圖比較方法-巴氏距離計算(CV_COMP_BHATTACHARYYA )
比較結(jié)果是很準的,計算結(jié)果范圍為 0-1 ,0表示兩個直方圖非常相關(guān),1最不相似
H1,H2分別表示兩個圖像的直方圖數(shù)據(jù)
相關(guān)API(cv::compareHist)
- 首先把圖像從RGB色彩空間轉(zhuǎn)換到HSV色彩空間cvtColor
- 計算圖像的直方圖,然后歸一化到[0~1]之間calcHist和normalize;
- 使用上述四種比較方法之一進行比較compareHist
compareHist(
InputArray h1, // 直方圖數(shù)據(jù),下同
InputArray H2,
int method// 比較方法,上述四種方法之一
)
程序步驟:
- 加載圖像數(shù)據(jù)
- 從RGB空間轉(zhuǎn)換到HSV空間
- 計算直方圖并歸一化
- 比較直方圖,并返回值
程序代碼
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace std;
using namespace cv;
string convertToString(double d);
int main(int argc, char** argv) {
// 1. 聲明儲存基準圖像和另外兩張對比圖像的矩陣( RGB 和 HSV )
Mat base, test1, test2;
Mat hsvbase, hsvtest1, hsvtest2;
// 2. 裝載基準圖像(src_base) 和兩張測試圖像:
base = imread("E:/Experiment/OpenCV/Pictures/lenanoise.jpg");
if (!base.data) {
printf("could not load image...\n");
return -1;
}
test1 = imread("E:/Experiment/OpenCV/Pictures/lena.jpg");
test2 = imread("E:/Experiment/OpenCV/Pictures/lena1.jpg");
// 3. 將圖像轉(zhuǎn)化到HSV格式:
cvtColor(base, hsvbase, CV_BGR2HSV);//轉(zhuǎn)換為 HSV 顏色空間,也是3通道
cvtColor(test1, hsvtest1, CV_BGR2HSV);
cvtColor(test2, hsvtest2, CV_BGR2HSV);
// 4. 初始化計算直方圖需要的實參(bins, 范圍,通道 H 和 S ).
int h_bins = 50; int s_bins = 60;
int histSize[] = { h_bins, s_bins };
// hue varies from 0 to 179, saturation from 0 to 255
float h_ranges[] = { 0, 180 };
float s_ranges[] = { 0, 256 };
const float* ranges[] = { h_ranges, s_ranges };
// Use the o-th and 1-st channels
int channels[] = { 0, 1 };
// 5. 創(chuàng)建儲存直方圖的 MatND 實例:
//ND 表示二維或多維的Mat ,typedef Mat MatND; 源碼中MatND的聲明。 Mat表示二維的數(shù)組
MatND hist_base;
MatND hist_test1;
MatND hist_test2;
// 6. 計算基準圖像,兩張測試圖像
calcHist(&hsvbase, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false);
normalize(hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat());//歸一化到 0-1 之間
calcHist(&hsvtest1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false);
normalize(hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat());
calcHist(&hsvtest2, 1, channels, Mat(), hist_test2, 2, histSize, ranges, true, false);
normalize(hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat());
// 7. 使用4種對比標準將基準圖像(hist_base)的直方圖與其余各直方圖進行對比:
//比較的算法 CV_COMP_CORREL CHISQR INTERSECT BHATTACHARYYA
double basebase = compareHist(hist_base, hist_base, CV_COMP_CORREL);
double basetest1 = compareHist(hist_base, hist_test1, CV_COMP_CORREL);
double basetest2 = compareHist(hist_base, hist_test2, CV_COMP_CORREL);
double tes1test2 = compareHist(hist_test1, hist_test2, CV_COMP_CORREL);
printf("test1 compare with test2 correlation value :%f", tes1test2);
Mat test12;
test2.copyTo(test12);
// 8. 將比較的結(jié)果轉(zhuǎn)換為string,然后以文字的方式繪制到圖形上
putText(base, convertToString(basebase), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);
putText(test1, convertToString(basetest1), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);
putText(test2, convertToString(basetest2), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);
putText(test12, convertToString(tes1test2), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);
namedWindow("base", CV_WINDOW_AUTOSIZE);
namedWindow("test1", CV_WINDOW_AUTOSIZE);
namedWindow("test2", CV_WINDOW_AUTOSIZE);
imshow("base", base);
imshow("test1", test1);
imshow("test2", test2);
imshow("test12", test12);
waitKey(0);
return 0;
}
string convertToString(double d) {
ostringstream os;
if (os << d) // << 運算符重載了,將double轉(zhuǎn)成string
return os.str();
return "invalid conversion";
}
運行截圖
參考博客:
- https://blog.csdn.net/huanghuangjin/article/details/81175339
- https://blog.csdn.net/LYKymy/article/details/83210430
來源:http://www./content-4-105551.html
|