日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

CalcBackProject函数

發(fā)布時(shí)間:2025/4/16 编程问答 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CalcBackProject函数 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

反向投影

目標(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?示例。
  • 代碼一瞥:

#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp"#include <iostream>using namespace cv; using namespace std;/// 全局變量 Mat src; Mat hsv; Mat hue; int bins = 25;/// 函數(shù)申明 void Hist_and_Backproj(int, void* );/** @函數(shù) main */ int main( int argc, char** argv ) {/// 讀取圖像src = imread( argv[1], 1 );/// 轉(zhuǎn)換到 HSV 空間cvtColor( src, hsv, CV_BGR2HSV );/// 分離 Hue 通道hue.create( hsv.size(), hsv.depth() );int ch[] = { 0, 0 };mixChannels( &hsv, 1, &hue, 1, ch, 1 );/// 創(chuàng)建 Trackbar 來(lái)輸入bin的數(shù)目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);/// 現(xiàn)實(shí)圖像imshow( window_image, src );/// 等待用戶反應(yīng)waitKey(0);return 0; }/** * @函數(shù) Hist_and_Backproj * @簡(jiǎn)介:Trackbar事件的回調(diào)函數(shù) */ 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() );/// 計(jì)算反向投影MatND backproj;calcBackProject( &hue, 1, 0, hist, backproj, &ranges, 1, true );/// 顯示反向投影imshow( "BackProj", backproj );/// 顯示直方圖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 ); }

解釋

  • 申明圖像矩陣,初始化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)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。