直方圖對比(兩個直方圖的相似性如何度量)


本文檔嘗試解答如下問題:

  • 如何使用OpenCV函數 compareHist 產生一個表達兩個直方圖的相似度的數值。
  • 如何使用不同的對比標准來對直方圖進行比較。

原理

  • 要比較兩個直方圖( H_{1} and H_{2} ), 首先必須要選擇一個衡量直方圖相似度的 對比標准 (d(H_{1}, H_{2})) 。

  • OpenCV 函數 compareHist 執行了具體的直方圖對比的任務。該函數提供了4種對比標准來計算相似度:

    1. Correlation ( CV_COMP_CORREL )

      d(H_1,H_2) =  \frac{\sum_I (H_1(I) - \bar{H_1}) (H_2(I) - \bar{H_2})}{\sqrt{\sum_I(H_1(I) - \bar{H_1})^2 \sum_I(H_2(I) - \bar{H_2})^2}}

      其中

      \bar{H_k} =  \frac{1}{N} \sum _J H_k(J)

      N 是直方圖中bin的數目。

    2. Chi-Square ( CV_COMP_CHISQR )

      d(H_1,H_2) =  \sum _I  \frac{\left(H_1(I)-H_2(I)\right)^2}{H_1(I)+H_2(I)}

    3. Intersection ( CV_COMP_INTERSECT )

      d(H_1,H_2) =  \sum _I  \min (H_1(I), H_2(I))

    4. Bhattacharyya 距離( CV_COMP_BHATTACHARYYA )

      d(H_1,H_2) =  \sqrt{1 - \frac{1}{\sqrt{\bar{H_1} \bar{H_2} N^2}} \sum_I \sqrt{H_1(I) \cdot H_2(I)}}

源碼

  • 本程序做什么?

    • 裝載一張 基准圖像 和 兩張 測試圖像 進行對比。
    • 產生一張取自 基准圖像 下半部的圖像。
    • 將圖像轉換到HSV格式。
    • 計算所有圖像的H-S直方圖,並歸一化以便對比。
    • 將 基准圖像 直方圖與 兩張測試圖像直方圖,基准圖像半身像直方圖,以及基准圖像本身的直方圖分別作對比。
    • 顯示計算所得的直方圖相似度數值。
  • 下載代碼: 點擊 這里

  • 代碼一瞥:

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp" #include <iostream> #include <stdio.h> using namespace std; using namespace cv; /** @函數 main */ int main( int argc, char** argv ) { Mat src_base, hsv_base; Mat src_test1, hsv_test1; Mat src_test2, hsv_test2; Mat hsv_half_down; /// 裝載三張背景環境不同的圖像 if( argc < 4 ) { printf("** Error. Usage: ./compareHist_Demo <image_settings0> <image_setting1> <image_settings2>\n"); return -1; } src_base = imread( argv[1], 1 ); src_test1 = imread( argv[2], 1 ); src_test2 = imread( argv[3], 1 ); /// 轉換到 HSV cvtColor( src_base, hsv_base, CV_BGR2HSV ); cvtColor( src_test1, hsv_test1, CV_BGR2HSV ); cvtColor( src_test2, hsv_test2, CV_BGR2HSV ); hsv_half_down = hsv_base( Range( hsv_base.rows/2, hsv_base.rows - 1 ), Range( 0, hsv_base.cols - 1 ) ); /// 對hue通道使用30個bin,對saturatoin通道使用32個bin int h_bins = 50; int s_bins = 60; int histSize[] = { h_bins, s_bins }; // hue的取值范圍從0到256, saturation取值范圍從0到180 float h_ranges[] = { 0, 256 }; float s_ranges[] = { 0, 180 }; const float* ranges[] = { h_ranges, s_ranges }; // 使用第0和第1通道 int channels[] = { 0, 1 }; /// 直方圖 MatND hist_base; MatND hist_half_down; MatND hist_test1; MatND hist_test2; /// 計算HSV圖像的直方圖 calcHist( &hsv_base, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false ); normalize( hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat() ); calcHist( &hsv_half_down, 1, channels, Mat(), hist_half_down, 2, histSize, ranges, true, false ); normalize( hist_half_down, hist_half_down, 0, 1, NORM_MINMAX, -1, Mat() ); calcHist( &hsv_test1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false ); normalize( hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat() ); calcHist( &hsv_test2, 1, channels, Mat(), hist_test2, 2, histSize, ranges, true, false ); normalize( hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat() ); ///應用不同的直方圖對比方法 for( int i = 0; i < 4; i++ ) { int compare_method = i; double base_base = compareHist( hist_base, hist_base, compare_method ); double base_half = compareHist( hist_base, hist_half_down, compare_method ); double base_test1 = compareHist( hist_base, hist_test1, compare_method ); double base_test2 = compareHist( hist_base, hist_test2, compare_method ); printf( " Method [%d] Perfect, Base-Half, Base-Test(1), Base-Test(2) : %f, %f, %f, %f \n", i, base_base, base_half , base_test1, base_test2 ); } printf( "Done \n" ); return 0; } 

解釋

  1. 聲明儲存基准圖像和另外兩張對比圖像的矩陣( RGB 和 HSV )

    Mat src_base, hsv_base; Mat src_test1, hsv_test1; Mat src_test2, hsv_test2; Mat hsv_half_down; 
  2. 裝載基准圖像(src_base) 和兩張測試圖像:

    if( argc < 4 ) { printf("** Error. Usage: ./compareHist_Demo <image_settings0> <image_setting1> <image_settings2>\n"); return -1; } src_base = imread( argv[1], 1 ); src_test1 = imread( argv[2], 1 ); src_test2 = imread( argv[3], 1 ); 
  3. 將圖像轉化到HSV格式:

    cvtColor( src_base, hsv_base, CV_BGR2HSV ); cvtColor( src_test1, hsv_test1, CV_BGR2HSV ); cvtColor( src_test2, hsv_test2, CV_BGR2HSV ); 
  4. 同時創建包含基准圖像下半部的半身圖像(HSV格式):

    hsv_half_down = hsv_base( Range( hsv_base.rows/2, hsv_base.rows - 1 ), Range( 0, hsv_base.cols - 1 ) ); 
  5. 初始化計算直方圖需要的實參(bins, 范圍,通道 H 和 S ).

    int h_bins = 50; int s_bins = 32; int histSize[] = { h_bins, s_bins }; float h_ranges[] = { 0, 256 }; float s_ranges[] = { 0, 180 }; const float* ranges[] = { h_ranges, s_ranges }; int channels[] = { 0, 1 }; 
  6. 創建儲存直方圖的 MatND 實例:

    MatND hist_base; MatND hist_half_down; MatND hist_test1; MatND hist_test2; 
  7. 計算基准圖像,兩張測試圖像,半身基准圖像的直方圖:

    calcHist( &hsv_base, 1, channels, Mat(), hist_base, 2, histSize, ranges, true, false ); normalize( hist_base, hist_base, 0, 1, NORM_MINMAX, -1, Mat() ); calcHist( &hsv_half_down, 1, channels, Mat(), hist_half_down, 2, histSize, ranges, true, false ); normalize( hist_half_down, hist_half_down, 0, 1, NORM_MINMAX, -1, Mat() ); calcHist( &hsv_test1, 1, channels, Mat(), hist_test1, 2, histSize, ranges, true, false ); normalize( hist_test1, hist_test1, 0, 1, NORM_MINMAX, -1, Mat() ); calcHist( &hsv_test2, 1, channels, Mat(), hist_test2, 2, histSize, ranges, true, false ); normalize( hist_test2, hist_test2, 0, 1, NORM_MINMAX, -1, Mat() ); 
  8. 按順序使用4種對比標准將基准圖像(hist_base)的直方圖與其余各直方圖進行對比:

    for( int i = 0; i < 4; i++ ) { int compare_method = i; double base_base = compareHist( hist_base, hist_base, compare_method ); double base_half = compareHist( hist_base, hist_half_down, compare_method ); double base_test1 = compareHist( hist_base, hist_test1, compare_method ); double base_test2 = compareHist( hist_base, hist_test2, compare_method ); printf( " Method [%d] Perfect, Base-Half, Base-Test(1), Base-Test(2) : %f, %f, %f, %f \n", i, base_base, base_half , base_test1, base_test2 ); } 

結果

  1. 使用下列輸入圖像:

    Base_0

    Test_1

    Test_2

    第一張為基准圖像,其余兩張為測試圖像。同時我們會將基准圖像與它自身及其半身圖像進行對比。

  2. 我們應該會預料到當將基准圖像直方圖及其自身進行對比時會產生完美的匹配, 當與來源於同一樣的背景環境的半身圖對比時應該會有比較高的相似度, 當與來自不同亮度光照條件的其余兩張測試圖像對比時匹配度應該不是很好:

  3. 下面顯示的是結果數值:

對比標准 基准 - 基准 基准 - 半身 基准 - 測試1 基准 - 測試2
Correlation 1.000000 0.930766 0.182073 0.120447
Chi-square 0.000000 4.940466 21.184536 49.273437
Intersection 24.391548 14.959809 3.889029 5.775088
Bhattacharyya 0.000000 0.222609 0.646576 0.801869

對於 Correlation 和 Intersection 標准, 值越大相似度越大。因此可以看到對於采用這兩個方法的對比,*基准 - 基准* 的對比結果值是最大的, 而 基准 - 半身 的匹配則是第二好(跟我們預測的一致)。而另外兩種對比標准,則是結果越小相似度越大。 我們可以觀察到基准圖像直方圖與兩張測試圖像直方圖的匹配是最差的,這再一次印證了我們的預測。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM