OpenCV学习(二十二) :反向投影:calcBackProject(),mixChannels()
OpenCV學習(二十二) :反向投影:calcHist(),minMaxLoc(),compareHist()
參考博客:
反向投影backproject的直觀理解
opencv 反向投影
顏色直方圖的計算、顯示、處理、對比及反向投影
一、概述
1、官方解釋:反向投影是一種記錄給定圖像中的像素點如何適應(yīng)直方圖模型像素分布的方式。簡單的講,
1)就是首先計算某一特征的直方圖模型;(特征可以為色調(diào)+飽和度、灰度值等等)
2)然后使用模型去尋找圖像中存在的該特征。例如,你有一個膚色直方圖(Hue-Saturation直方圖),你可以用它(色調(diào)和飽和度)來尋找圖像中的膚色區(qū)域:
2、反向投影圖就是圖像對應(yīng)位置像素的數(shù)量統(tǒng)計,也可以看做是密度統(tǒng)計。 反向投影圖在某一位置(點)的值是原圖對應(yīng)位置(點)的像素值所在原圖區(qū)間(bins)的總數(shù)目。(所以,一個區(qū)間點越多,在反向投影矩陣中就越亮。)
3、反向投影中的“反向”指的是從直方圖值到反向投影矩陣映射的過程。
4、通過反向投影,原始的圖像被簡化了,而這個簡化的過程實際上就是提取出圖像的某個特征。所以我們就可以用這個特征來對比兩幅圖,如果兩幅圖的反向投影矩陣相似或相同,那么我們就可以判定這兩幅圖這個特征是相同的。
5、反向投影的作用:
反向投影用于在輸入圖像(通常較大)中查找**特定圖像(通常較小或者僅1個像素,以下將其稱為模板圖像)**最匹配的點或者區(qū)域,也就是定位模板圖像出現(xiàn)在輸入圖像的位置。如圖:
第一個圖為源圖像,中間的那個小圖像是產(chǎn)生用于反向投影的直方圖的圖像,最后的用直方圖均衡化后的結(jié)果圖像,可以看到,蘋果的像素位置幾被找到了。
二、calcBackProject()函數(shù)
calcBackProject 的基本過程是:
1)拿到 特征圖像 (或模板圖像)
2)得到 特征圖像的直方圖
3)拿到測試圖像,依據(jù)測試圖像的每個像素的值,在特征圖像的直方圖中找到對應(yīng)的值,然后將直方圖的值賦給新的圖像,backproject算法就完成了。
三、CalcBackProjectPatch()函數(shù)
對于calcBackProjectPatch,整個是基于塊的形式,利用直方圖做匹配,類似于模板匹配,只不過這些模板轉(zhuǎn)換為直方圖,而原圖中以某點為基準,摳出來作對比的部分也轉(zhuǎn)換為直方圖,兩個直方圖作匹配,匹配的結(jié)果作為此點的值。
結(jié)果會是一張概率圖,概率越大的地方,代表此區(qū)域與模板的相似度越高。而且,當模板小于檢測的目標時,得到的結(jié)果圖也能反映出檢測區(qū)域的形狀。這個結(jié)果與模板匹配的結(jié)果很相似,但利用直方圖的方式,就能去除光照變化、邊緣遮擋,旋轉(zhuǎn)等因素的影響。另外
基于塊的反向投影。這種方法速度很慢,模版圖像別弄的太大了。
例如:
1)當模板圖像小與目標的時候,作為區(qū)域檢測器,測試如下:可以找到手區(qū)域
2)當模板等于目標的時候,測試如下:輸出圖像,較亮的部分就是人的頭部大致位置
詳情參考:
opencv 直方圖反向投影
函數(shù)原型:
void cvCalcBackProjectPatch( IplImage** image, // 輸入圖像:是一個單通道圖像數(shù)組,而非實際圖像 CvArr* dst, // 輸出結(jié)果:是一個單通道32位浮點圖像,它的寬度為W-w+1,高度為H-h+1,這里的W和H是輸入圖像的寬度和高度,w和h是模板圖像的寬度和高度 CvSize patch_size, // 模板圖像的大小:寬度和高度 CvHistogram* hist, // 模板圖像的直方圖:直方圖的維數(shù)和輸入圖像的個數(shù)相同,并且次序要一致;例如:輸入圖像包含色調(diào)和飽和度,那么直方圖的第0維是色調(diào),第1維是飽和度 int method, // 對比方式:跟直方圖對比中的方式類似,可以是:CORREL(相關(guān))、CHISQR(卡方)、INTERSECT(相交)、BHATTACHARYYA float factor // 歸一化因子,一般都設(shè)置成1,否則很可能會出錯;中文、英文以及各路轉(zhuǎn)載的文檔都錯了,這個參數(shù)的實際類型是double,而非float,我看了源代碼才搞定這個地方 )四、mixChannels()函數(shù)
mixChannels()函數(shù)用于將輸入數(shù)組的指定通道復制到輸出數(shù)組的指定通道。
其實我們接觸到的,split()和merge(),以及cvtColor的某些形式,都只是mixChannels()的一部分。
參考:
opencv3/C++ mixChannels()詳解:4通道圖像分割、HSV通道獲取
示例:
#include<opencv2/opencv.hpp> using namespace cv;int main() {Mat bgra( 500, 500, CV_8UC4, Scalar(255,255,0,255) );Mat bgr( bgra.rows, bgra.cols, CV_8UC3 );Mat alpha( bgra.rows, bgra.cols, CV_8UC1 );Mat out[] = { rgb, alpha };int from_to[] = { 0, 2, 1, 1, 2, 0, 3, 3 };// 輸入1一個矩陣,輸出2個舉證,4個索引對mixChannels( &bgra, 1, out, 2, from_to, 4 );imshow("bgra", bgra); // 青色imshow("bgr", bgr); // 黃色(通道值改變,色彩空間不變)waitKey(0);return 0; }五、示例:
使用模型直方圖(代表手掌的皮膚色調(diào))來檢測測試圖像中 的皮膚區(qū)域。
1)對測試圖像中的每個像素(p(i,j),獲取色調(diào)數(shù)據(jù)并找到該色調(diào)(h(i,j),s(i,j))在直方圖中的bin的位置;
2)查詢模型直方圖中對應(yīng)的bin-(hi,j,si,j)并讀取該bin的數(shù)值;
3)將此數(shù)值存儲在新的圖像中(BackProjection)。你也可以先歸一化模型直方圖,這樣測試圖像的輸出就可以在屏幕顯示了;
4)通過對測試圖像中的每個像素采用以上步驟,我們得到了下面的BackProjection結(jié)果圖:
5)使用統(tǒng)計學的語言,BackProjection中存儲的數(shù)值代表了測試圖像中該像素屬于皮膚區(qū)域的概率。比如上圖為例,亮起的區(qū)域是皮膚區(qū)域的概率更大,而更暗的區(qū)域則表示更低的概率(注意手掌內(nèi)部和邊緣的陰影影響了檢測的精度)。
直方圖計算 bins(特征空間子區(qū)段的數(shù)目)回調(diào)函數(shù):
void on_BinChange(int, void* ) {// 1、參數(shù)準備MatND hist;int histSize = MAX( g_bins, 2 ); // 組距 最小為2float hue_range[] = { 0, 180 };const float* ranges = { hue_range };// 2、計算直方圖并歸一化// 將handhue取值替換為g_hueImage圖像的中心部分,作為特征圖像Mat handhue_feature= g_hueImage(Rect(g_hueImage.rows/2-25, g_hueImage.cols/2-25, 50, 50)).clone();// g_hueImageimshow("handhue_feature", handhue_feature); // 顯示特征// 將handhue_feature的取值 替換為g_hueImage圖像的中心部分,作為特征圖像calcHist( &handhue_feature, 1, 0, Mat(), hist, 1, &histSize, &ranges, true, false );normalize( hist, hist, 0, 255, NORM_MINMAX, -1, Mat() ); // 歸一化直方圖數(shù)值范圍為0~255之間// 3、計算 獲取反向投影MatND backproj;calcBackProject( &g_hueImage, 1, 0, hist, backproj, &ranges, 1, true );// 4、顯示反向投影imshow( "反向投影圖", backproj );// 5、繪制直方圖的參數(shù)準備int w = 400; int h = 400;int bin_w = cvRound( (double) w / histSize );Mat histImg = Mat::zeros( w, h, CV_8UC3 );// 6、繪制直方圖for( int i = 0; i < g_bins; i ++ ){ rectangle( histImg, Point( i*bin_w, h ), Point( (i+1)*bin_w, h - cvRound( hist.at<float>(i)*h/255.0 ) ), Scalar( 100, 123, 255 ), -1 ); }// 7、顯示直方圖窗口imshow( "直方圖", histImg ); }源圖+色調(diào)圖
特征圖:
總結(jié)
以上是生活随笔為你收集整理的OpenCV学习(二十二) :反向投影:calcBackProject(),mixChannels()的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: tensorflow中GPU的设置
- 下一篇: C++查看各种数据类型所占字节和最大最小