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?

TAG:OpenCV | 图像处理 |