【OpenCV 】直方图均衡化,直方图计算,直方图对比
目錄
1.直方圖均衡化?
1.1 原理
1.2 直方圖均衡化
1.3 直方圖均衡化原理
1.4 代碼實例
1.5 運行效果
2. 直方圖計算?
2.1 目標(biāo)
2.2 直方圖
2.3 代碼實例
2.4 運行結(jié)果
3 直方圖對比?
3.1 目標(biāo)
3.2 原理
3.3 代碼
3.4 運行結(jié)果
1.直方圖均衡化?
-
什么是圖像的直方圖和為什么圖像的直方圖很有用
-
用OpenCV函數(shù) equalizeHist 對圖像進(jìn)行直方圖均衡化
1.1 原理
-
直方圖是圖像中像素強(qiáng)度分布的圖形表達(dá)方式.
-
它統(tǒng)計了每一個強(qiáng)度值所具有的像素個數(shù).
1.2 直方圖均衡化
-
直方圖均衡化是通過拉伸像素強(qiáng)度分布范圍來增強(qiáng)圖像對比度的一種方法.
-
說得更清楚一些, 以上面的直方圖為例, 你可以看到像素主要集中在中間的一些強(qiáng)度值上. 直方圖均衡化要做的就是 拉伸 這個范圍. 見下面左圖: 綠圈圈出了 少有像素分布其上的 強(qiáng)度值. 對其應(yīng)用均衡化后, 得到了中間圖所示的直方圖. 均衡化的圖像見下面右圖.
1.3 直方圖均衡化原理
OpenCV 【九】——calcHist ——圖像直方圖統(tǒng)計
-
1.4 代碼實例
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
?
using namespace cv;
using namespace std;
?
/** @function main */
int main( int argc, char** argv )
{Mat src, dst;
?char* source_window = "Source image";char* equalized_window = "Equalized Image";
?/// 加載源圖像src = imread( argv[1], 1 );
?if( !src.data ){ cout<<"Usage: ./Histogram_Demo <path_to_image>"<<endl;return -1;}
?/// 轉(zhuǎn)為灰度圖cvtColor( src, src, CV_BGR2GRAY );
?/// 應(yīng)用直方圖均衡化equalizeHist( src, dst );
?/// 顯示結(jié)果namedWindow( source_window, CV_WINDOW_AUTOSIZE );namedWindow( equalized_window, CV_WINDOW_AUTOSIZE );
?imshow( source_window, src );imshow( equalized_window, dst );
?/// 等待用戶按鍵退出程序waitKey(0);
?return 0;
}
?
1.5 運行效果
直方圖均衡化
?
2. 直方圖計算?
2.1 目標(biāo)
-
如何使用OpenCV函數(shù) split 將圖像分割成單通道數(shù)組。
-
如何使用OpenCV函數(shù) calcHist 計算圖像陣列的直方圖。
-
如何使用OpenCV函數(shù) normalize 歸一化數(shù)組。
2.2 直方圖
詳見OpenCV 【九】——calcHist ——圖像直方圖統(tǒng)計
-
讓我們再來搞清楚直方圖的一些具體細(xì)節(jié):
-
- dims: 需要統(tǒng)計的特征的數(shù)目, 在上例中,?dims = 1?因為我們僅僅統(tǒng)計了灰度值(灰度圖像)。
- bins: 每個特征空間?子區(qū)段?的數(shù)目,在上例中,?bins = 16
- range: 每個特征空間的取值范圍,在上例中,?range = [0,255]
-
怎樣去統(tǒng)計兩個特征呢? 在這種情況下, 直方圖就是3維的了,x軸和y軸分別代表一個特征, z軸是掉入?
-
?組合中的樣本數(shù)目。 同樣的方法適用于更高維的情形 (當(dāng)然會變得很復(fù)雜)。
2.3 代碼實例
-
本程序做什么?
-
裝載一張圖像
-
使用函數(shù) split 將載入的圖像分割成 R, G, B 單通道圖像
-
調(diào)用函數(shù) calcHist 計算各單通道圖像的直方圖
-
在一個窗口疊加顯示3張直方圖
-
-
下載代碼: 點擊 這里
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
?
using namespace std;
using namespace cv;
?
/** @函數(shù) main */
int main(int argc, char** argv)
{Mat src, dst;
?/// 裝載圖像src = imread("C:\\Users\\guoqi\\Desktop\\ch7\\4.jpg", 1);
?if (!src.data){return -1;}
?/// 分割成3個單通道圖像 ( R, G 和 B )vector<Mat> rgb_planes;split(src, rgb_planes);
?/// 設(shè)定bin數(shù)目int histSize = 255;
?/// 設(shè)定取值范圍 ( R,G,B) )float range[] = { 0, 255 };const float* histRange = { range };
?bool uniform = true; bool accumulate = false;
?Mat r_hist, g_hist, b_hist;
?/// 計算直方圖:calcHist(&rgb_planes[0], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate);calcHist(&rgb_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate);calcHist(&rgb_planes[2], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate);
?// 創(chuàng)建直方圖畫布int hist_w = 400; int hist_h = 400;int bin_w = cvRound((double)hist_w / histSize);
?Mat histImage(hist_w, hist_h, CV_8UC3, Scalar(0, 0, 0));
?/// 將直方圖歸一化到范圍 [ 0, histImage.rows ]normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
?/// 在直方圖畫布上畫出直方圖for (int i = 1; i < histSize; i++){line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(r_hist.at<float>(i - 1))),Point(bin_w*(i), hist_h - cvRound(r_hist.at<float>(i))),Scalar(0, 0, 255), 2, 8, 0);line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(g_hist.at<float>(i - 1))),Point(bin_w*(i), hist_h - cvRound(g_hist.at<float>(i))),Scalar(0, 255, 0), 2, 8, 0);line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(b_hist.at<float>(i - 1))),Point(bin_w*(i), hist_h - cvRound(b_hist.at<float>(i))),Scalar(255, 0, 0), 2, 8, 0);}
?/// 顯示直方圖namedWindow("calcHist Demo", CV_WINDOW_AUTOSIZE);imshow("calcHist Demo", histImage);
?waitKey(0);return 0;
}
?
2.4 運行結(jié)果
?
3 直方圖對比?
HSV 顏色空間
基于上述理由,在圖像處理中使用較多的是 HSV 顏色空間,它比 RGB 更接近人們對彩色的感知經(jīng)驗。非常直觀地表達(dá)顏色的色調(diào)、鮮艷程度和明暗程度,方便進(jìn)行顏色的對比。
在 HSV 顏色空間下,比 BGR 更容易跟蹤某種顏色的物體,常用于分割指定顏色的物體。
HSV 表達(dá)彩色圖像的方式由三個部分組成:
-
Hue(色調(diào)、色相)
-
Saturation(飽和度、色彩純凈度)
-
Value(明度)
用下面這個圓柱體來表示 HSV 顏色空間,圓柱體的橫截面可以看做是一個極坐標(biāo)系 ,H 用極坐標(biāo)的極角表示,S 用極坐標(biāo)的極軸長度表示,V 用圓柱中軸的高度表示。
?
Hue 用角度度量,取值范圍為0~360°,表示色彩信息,即所處的光譜顏色的位置。,表示如下:
?
顏色圓環(huán)上所有的顏色都是光譜上的顏色,從紅色開始按逆時針方向旋轉(zhuǎn),Hue=0 表示紅色,Hue=120 表示綠色,Hue=240 表示藍(lán)色等等。
在 GRB中 顏色由三個值共同決定,比如黃色為即 (255,255,0);在HSV中,黃色只由一個值決定,Hue=60即可。
HSV 圓柱體的半邊橫截面(Hue=60):
?
其中Saturation*水平方向表示飽和度,飽和度表示顏色接近光譜色的程度。飽和度越高,說明顏色越深,越接近光譜色飽和度越低,說明顏色越淺,越接近白色。飽和度為0表示純白色。取值范圍為0~100%,值越大,顏色越飽和。**
Value(明度):豎直方向表示明度,決定顏色空間中顏色的明暗程度,明度越高,表示顏色越明亮,范圍是 0-100%。明度為0表示純黑色(此時顏色最暗)。
可以通俗理解為:
在Hue一定的情況下,飽和度減小,就是往光譜色中添加白色,光譜色所占的比例也在減小,飽和度減為0,表示光譜色所占的比例為零,導(dǎo)致整個顏色呈現(xiàn)白色。
明度減小,就是往光譜色中添加黑色,光譜色所占的比例也在減小,明度減為0,表示光譜色所占的比例為零,導(dǎo)致整個顏色呈現(xiàn)黑色。
HSV 對用戶來說是一種比較直觀的顏色模型。我們可以很輕松地得到單一顏色,即指定顏色角H,并讓V=S=1,然后通過向其中加入黑色和白色來得到我們需要的顏色。增加黑色可以減小V而S不變,同樣增加白色可以減小S而V不變。例如,要得到深藍(lán)色,V=0.4 S=1 H=240度。要得到淺藍(lán)色,V=1 S=0.4 H=240度。
HSV 的拉伸對比度增強(qiáng)就是對 S 和 V 兩個分量進(jìn)行歸一化(min-max normalize)即可,H 保持不變。
RGB顏色空間更加面向于工業(yè),而HSV更加面向于用戶,大多數(shù)做圖像識別這一塊的都會運用HSV顏色空間,因為HSV顏色空間表達(dá)起來更加直觀!
3.1 目標(biāo)
-
如何使用OpenCV函數(shù) compareHist 產(chǎn)生一個表達(dá)兩個直方圖的相似度的數(shù)值。
-
如何使用不同的對比標(biāo)準(zhǔn)來對直方圖進(jìn)行比較。
3.2 原理
-
?and??), 首先必須要選擇一個衡量直方圖相似度的?對比標(biāo)準(zhǔn)?() 。
-
OpenCV 函數(shù)?compareHist?執(zhí)行了具體的直方圖對比的任務(wù)。該函數(shù)提供了4種對比標(biāo)準(zhǔn)來計算相似度:
-
要比較兩個直方圖(??and??), 首先必須要選擇一個衡量直方圖相似度的?對比標(biāo)準(zhǔn)?() 。
-
OpenCV 函數(shù)?compareHist?執(zhí)行了具體的直方圖對比的任務(wù)。該函數(shù)提供了4種對比標(biāo)準(zhǔn)來計算相似度:
-
Correlation ( CV_COMP_CORREL )
其中
?是直方圖中bin的數(shù)目。
-
-
Chi-Square ( CV_COMP_CHISQR )
-
Intersection ( CV_COMP_INTERSECT )
-
Bhattacharyya 距離( CV_COMP_BHATTACHARYYA )
-
3.3 代碼
-
本程序做什么?
-
裝載一張 基準(zhǔn)圖像 和 兩張 測試圖像 進(jìn)行對比。
-
產(chǎn)生一張取自 基準(zhǔn)圖像 下半部的圖像。
-
將圖像轉(zhuǎn)換到HSV格式。
-
計算所有圖像的H-S直方圖,并歸一化以便對比。
-
將 基準(zhǔn)圖像 直方圖與 兩張測試圖像直方圖,基準(zhǔn)圖像半身像直方圖,以及基準(zhǔn)圖像本身的直方圖分別作對比。
-
顯示計算所得的直方圖相似度數(shù)值。
-
-
下載代碼: 點擊 這里
-
代碼一瞥:
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
?
using namespace std;
using namespace cv;
?
/** @函數(shù) 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;
?/// 裝載三張背景環(huán)境不同的圖像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 );
?/// 轉(zhuǎn)換到 HSVcvtColor( 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個binint h_bins = 50; int s_bins = 60;int histSize[] = { h_bins, s_bins };
?// hue的取值范圍從0到256, saturation取值范圍從0到180float 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() );
?///應(yīng)用不同的直方圖對比方法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;}
?
3.4 運行結(jié)果
-
第一張為基準(zhǔn)圖像,其余兩張為測試圖像。同時我們會將基準(zhǔn)圖像與它自身及其半身圖像進(jìn)行對比。
-
我們應(yīng)該會預(yù)料到當(dāng)將基準(zhǔn)圖像直方圖及其自身進(jìn)行對比時會產(chǎn)生完美的匹配, 當(dāng)與來源于同一樣的背景環(huán)境的半身圖對比時應(yīng)該會有比較高的相似度, 當(dāng)與來自不同亮度光照條件的其余兩張測試圖像對比時匹配度應(yīng)該不是很好:
-
下面顯示的是結(jié)果數(shù)值:
對比標(biāo)準(zhǔn) 基準(zhǔn) - 基準(zhǔn) 基準(zhǔn) - 半身 基準(zhǔn) - 測試1 基準(zhǔn) - 測試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 標(biāo)準(zhǔn), 值越大相似度越大。因此可以看到對于采用這兩個方法的對比,基準(zhǔn) - 基準(zhǔn) 的對比結(jié)果值是最大的, 而 基準(zhǔn) - 半身 的匹配則是第二好(跟我們預(yù)測的一致)。而另外兩種對比標(biāo)準(zhǔn),則是結(jié)果越小相似度越大。 我們可以觀察到基準(zhǔn)圖像直方圖與兩張測試圖像直方圖的匹配是最差的,這再一次印證了我們的預(yù)測。
總結(jié)
以上是生活随笔為你收集整理的【OpenCV 】直方图均衡化,直方图计算,直方图对比的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 长安cs35多少钱啊?
- 下一篇: 求一个寿司拼盘好听的名字!