1.24【OpenCV圖像處理】直方圖對比
直方圖比較compareHist()、相關性計算、卡方計算、十字交叉計算、巴氏距離計算
1.24.1 直方圖比較方法概述
比較方法原理:對輸入的兩張圖像計算得到直方圖H1與H2,歸一化到相同的尺度空間然後可以通過計算H1與H2的之間的距離得到兩個直方圖的相似程度,進而比較圖像本身的相似程度。通常用HSV色彩空間的HS兩個通道的直方圖數據作比較。
Opencv提供的比較方法(對比標準 )有四種:
Correlation 相關性比較
Chi-Square 卡方比較
Intersection 十字交叉性
Bhattacharyya distance 巴氏距離
1.24.2 直方圖比較方法 - compareHist函數封裝好了
(1)相關性計算(CV_COMP_CORREL)
其中均值
,N是直方圖的BIN個數,H1,H2分別表示兩個圖像的直方圖數據。
結果是0~1, d(H1,H2)=1 則相關性最強;=0 則最不相關。
(2)卡方計算(CV_COMP_CHISQR)
d(H1,H2)=0 則相關性最強;越大越不相關(數值很大,幾百幾千)。
(3)十字交叉計算(CV_COMP_INTERSECT)
取最小者,越大越相關。
(4)巴氏距離計算(CV_COMP_BHATTACHARYYA )
結果是0~1,d(H1,H2)=0 則相關性最強; =1 則最不相似。
1.24.3 相關API
compareHist(
InputArray h1, // 直方圖數據,下同
InputArray H2,
int method // 比較方法,上述四種方法之一。
)
double basetest1 = compareHist(hist_base, hist_test1, CV_COMP_BHATTACHARYYA);//比較出來的結果放到double數據里nputText(test1, convertToString(basetest1), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);n
使用步驟:
1)首先把圖像從RGB色彩空間轉換到HSV色彩空間,只用H和S通道的數據 - cvtColor
cvtColor(base, hsvbase, CV_BGR2HSV); //轉化為HSV空間
float h_ranges[] = { 0, 180 }; //H 色調取值範圍,hue varies from 0 to 179
float s_ranges[] = { 0, 256 }; //S 飽和度取值範圍,saturation from 0 to 255
2)計算H和S通道的直方圖,然後歸一化到[0~1]之間 - calcHist和normalize;
calcHist(&hsvbase, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false); //第一幅直方圖計算,輸入圖像指針,圖像數,通道數,輸入掩膜,輸出直方圖,維度2維,等級,值域
normalize(hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat()); //歸一化,低值0,高值1
3)使用上述四種比較方法之一進行比較 - compareHist
double basebase = compareHist(hist_base, hist_base, CV_COMP_BHATTACHARYYA); //比較出來的結果放到double數據里
putText(base, convertToString(basebase), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA); //添加文本
完整程序:
/*1.24 直方圖比較*/n#include <opencv2/opencv.hpp>n#include <iostream>n#include <math.h>nnusing namespace std;nusing namespace cv;nnstring convertToString(double d); //double轉化為Stringnnint main(int argc, char** argv) {nMat base, test1, test2;nMat hsvbase, hsvtest1, hsvtest2;n base = imread("E:/OpenCV/testimage/lena.png");nif (!base.data) {n printf("could not load image...n");nreturn -1;n }n test1 = imread("E:/OpenCV/testimage/lenanoise.png");n test2 = imread("E:/OpenCV/testimage/test7.jpg"); //輸入三幅圖nn/*轉化為HSV空間*/n cvtColor(base, hsvbase, CV_BGR2HSV); //轉化為HSV空間n cvtColor(test1, hsvtest1, CV_BGR2HSV);n cvtColor(test2, hsvtest2, CV_BGR2HSV);nn/*三幅直方圖計算並歸一化0-1之間*/nint h_bins = 50; int s_bins = 60; // 直方圖等級nint histSize[] = { h_bins, s_bins }; //給一個數組[]就可直接引用了,否則也可給一個指針*地址來&引用 n float h_ranges[] = { 0, 180 }; //H 色調取值範圍,hue varies from 0 to 179nfloat s_ranges[] = { 0, 256 }; //S 飽和度取值範圍,saturation from 0 to 255nconst float* ranges[] = { h_ranges, s_ranges }; //常量指針不可以改動nint channels[] = { 0, 1 };// Use the o-th and 1-st channelsnMatND hist_base; //多通道多維nMatND hist_test1;nMatND hist_test2; n calcHist(&hsvbase, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false); //第一幅直方圖計算,輸入圖像指針,圖像數,通道數,輸入掩膜,輸出直方圖,維度2維,等級,值域n normalize(hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat()); //歸一化,低值0,高值1n calcHist(&hsvtest1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false);n normalize(hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat());n calcHist(&hsvtest2, 1, channels, Mat(), hist_test2, 2, histSize, ranges, true, false);n normalize(hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat());nn /*兩兩直方圖比較*/ndouble basebase = compareHist(hist_base, hist_base, CV_COMP_CORREL); //比較出來的結果放到double數據里ndouble basetest1 = compareHist(hist_base, hist_test1, CV_COMP_CORREL);ndouble basetest2 = compareHist(hist_base, hist_test2, CV_COMP_CORREL);ndouble basetest1test2 = compareHist(hist_test1, hist_test2, CV_COMP_CORREL);n printf("相關性計算(CV_COMP_CORREL):n test1 compare with test2 correlation value :%f", basetest1test2);nn/*比較值列印到圖像上*/nMat test1test2;n test2.copyTo(test1test2);n putText(base, convertToString(basebase), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA); //添加文本n putText(test1, convertToString(basetest1), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);n putText(test2, convertToString(basetest2), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);n putText(test1test2, convertToString(basetest1test2), Point(50, 50), CV_FONT_HERSHEY_COMPLEX, 1, Scalar(0, 0, 255), 2, LINE_AA);nn imshow("hsvbase", hsvbase);n imshow("base vs base", base);n imshow("test1 vs base", test1);n imshow("test2 vs base", test2);n imshow("tes1 vs test2", test1test2);nn waitKey(0);nreturn 0;n}nn/*double轉化為字元串String,以讓比較值列印到圖像上*/nstring convertToString(double d) {nostringstream os;nif (os << d) //double d向os里輸出nreturn os.str();nreturn "invalid conversion";n}n
運行結果:
推薦閱讀:
※opencv和pcl的區別?
※如何從入門開始學習OpenCV?
※關於opencv中對齊圖片的問題?
※如何在CLion上配置使用OpenCV?