CalcBackProject函数
反向投影
目標(biāo)
本文檔嘗試解答如下問(wèn)題:
- 什么是反向投影,它可以實(shí)現(xiàn)什么功能?
- 如何使用OpenCV函數(shù)?calcBackProject?計(jì)算反向投影?
- 如何使用OpenCV函數(shù)?mixChannels?組合圖像的不同通道?
原理
什么是反向投影?
- 反向投影是一種記錄給定圖像中的像素點(diǎn)如何適應(yīng)直方圖模型像素分布的方式。
- 簡(jiǎn)單的講, 所謂反向投影就是首先計(jì)算某一特征的直方圖模型,然后使用模型去尋找圖像中存在的該特征。
- 例如, 你有一個(gè)膚色直方圖 ( Hue-Saturation 直方圖 ),你可以用它來(lái)尋找圖像中的膚色區(qū)域:
反向投影的工作原理?
-
我們使用膚色直方圖為例來(lái)解釋反向投影的工作原理:
-
假設(shè)你已經(jīng)通過(guò)下圖得到一個(gè)膚色直方圖(Hue-Saturation), 旁邊的直方圖就是?模型直方圖?( 代表手掌的皮膚色調(diào)).你可以通過(guò)掩碼操作來(lái)抓取手掌所在區(qū)域的直方圖:
-
下圖是另一張手掌圖(測(cè)試圖像) 以及對(duì)應(yīng)的整張圖像的直方圖:
-
我們要做的就是使用?模型直方圖?(代表手掌的皮膚色調(diào)) 來(lái)檢測(cè)測(cè)試圖像中的皮膚區(qū)域。以下是檢測(cè)的步驟
-
對(duì)測(cè)試圖像中的每個(gè)像素 (??),獲取色調(diào)數(shù)據(jù)并找到該色調(diào)(??)在直方圖中的bin的位置。
-
查詢?模型直方圖?中對(duì)應(yīng)的bin -??- 并讀取該bin的數(shù)值。
-
將此數(shù)值儲(chǔ)存在新的圖像中(BackProjection)。 你也可以先歸一化?模型直方圖?,這樣測(cè)試圖像的輸出就可以在屏幕顯示了。
-
通過(guò)對(duì)測(cè)試圖像中的每個(gè)像素采用以上步驟, 我們得到了下面的 BackProjection 結(jié)果圖:
-
使用統(tǒng)計(jì)學(xué)的語(yǔ)言,?BackProjection?中儲(chǔ)存的數(shù)值代表了測(cè)試圖像中該像素屬于皮膚區(qū)域的?概率?。比如以上圖為例, 亮起的區(qū)域是皮膚區(qū)域的概率更大(事實(shí)確實(shí)如此),而更暗的區(qū)域則表示更低的概率(注意手掌內(nèi)部和邊緣的陰影影響了檢測(cè)的精度)。
源碼
-
本程序做什么?
-
裝載圖像
-
轉(zhuǎn)換原圖像到 HSV 格式,再分離出?Hue?通道來(lái)建立直方圖 (使用 OpenCV 函數(shù)?mixChannels)
- 讓用戶輸入建立直方圖所需的bin的數(shù)目。
- 計(jì)算同一圖像的直方圖 (如果bin的數(shù)目改變則更新直方圖) 和反向投影圖。
-
顯示反向投影圖和直方圖。
-
-
下載源碼:
- 點(diǎn)擊?這里?獲取簡(jiǎn)單版的源碼 (本教程使用簡(jiǎn)單版)。
- 要嘗試更炫的代碼 (使用 H-S 直方圖和 floodFill 來(lái)定義皮膚區(qū)域的掩碼)你可以點(diǎn)擊?增強(qiáng)版演示
- 當(dāng)然你也可以從實(shí)例庫(kù)里下載經(jīng)典的?camshiftdemo?示例。
-
代碼一瞥:
解釋
申明圖像矩陣,初始化bin數(shù)目:
Mat src; Mat hsv; Mat hue; int bins = 25;讀取輸入圖像并轉(zhuǎn)換到HSV 格式:
src = imread( argv[1], 1 ); cvtColor( src, hsv, CV_BGR2HSV );本教程僅僅使用Hue通道來(lái)創(chuàng)建1維直方圖 (你可以從上面的鏈接下載增強(qiáng)版本,增強(qiáng)版本使用了更常見(jiàn)的H-S直方圖,以獲取更好的結(jié)果):
hue.create( hsv.size(), hsv.depth() ); int ch[] = { 0, 0 }; mixChannels( &hsv, 1, &hue, 1, ch, 1 );你可以看到這里我們使用?mixChannels?來(lái)抽取 HSV圖像的0通道(Hue)。 該函數(shù)接受了以下的實(shí)參:
- &hsv:?一系列輸入圖像的數(shù)組, 被拷貝的通道的來(lái)源
- 1:?輸入數(shù)組中圖像的數(shù)目
- &hue:?一系列目的圖像的數(shù)組, 儲(chǔ)存拷貝的通道
- 1:?目的數(shù)組中圖像的數(shù)目
- ch[] = {0,0}:?通道索引對(duì)的數(shù)組,指示如何將輸入圖像的某一通道拷貝到目的圖像的某一通道。在這里,&hsv圖像的Hue(0) 通道被拷貝到&hue圖像(單通道)的0 通道。
- 1:?通道索引對(duì)德數(shù)目
創(chuàng)建Trackbar方便用戶輸入bin數(shù)目。 Trackbar的任何變動(dòng)將會(huì)調(diào)用函數(shù)?Hist_and_Backproj?。
char* window_image = "Source image"; namedWindow( window_image, CV_WINDOW_AUTOSIZE ); createTrackbar("* Hue bins: ", window_image, &bins, 180, Hist_and_Backproj ); Hist_and_Backproj(0, 0);顯示并等待用戶突出程序:
imshow( window_image, src );waitKey(0); return 0;Hist_and_Backproj 函數(shù):?初始化函數(shù)?calcHist?需要的實(shí)參, bin數(shù)目來(lái)自于 Trackbar:
void Hist_and_Backproj(int, void* ) {MatND hist;int histSize = MAX( bins, 2 );float hue_range[] = { 0, 180 };const float* ranges = { hue_range };計(jì)算直方圖并歸一化到范圍?
calcHist( &hue, 1, 0, Mat(), hist, 1, &histSize, &ranges, true, false ); normalize( hist, hist, 0, 255, NORM_MINMAX, -1, Mat() );調(diào)用函數(shù)?calcBackProject?計(jì)算同一張圖像的反向投影
MatND backproj; calcBackProject( &hue, 1, 0, hist, backproj, &ranges, 1, true );所有的實(shí)參都已經(jīng)知道了(與計(jì)算直方圖的實(shí)參一樣), 僅僅增加了 backproj 矩陣,用來(lái)儲(chǔ)存原圖像(&hue)的反向投影。
顯示 backproj:
imshow( "BackProj", backproj );顯示1維 Hue 直方圖:
int w = 400; int h = 400; int bin_w = cvRound( (double) w / histSize ); Mat histImg = Mat::zeros( w, h, CV_8UC3 );for( int i = 0; i < bins; i ++ ){ rectangle( histImg, Point( i*bin_w, h ), Point( (i+1)*bin_w, h - cvRound( hist.at<float>(i)*h/255.0 ) ), Scalar( 0, 0, 255 ), -1 ); }imshow( "Histogram", histImg );結(jié)果
下面是對(duì)一張樣本圖像(猜猜是什么?又是一掌)進(jìn)行的測(cè)試結(jié)果。 你可以改變bin的數(shù)目來(lái)觀察它是如何影響結(jié)果圖像的:
|
|
|
|
總結(jié)
以上是生活随笔為你收集整理的CalcBackProject函数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: preCornerDetect函数
- 下一篇: cvCalcBackProject的例子