OpenCV開發筆記(五十七):紅胖子8分鐘帶你深入瞭解直方圖反向投影(圖文並茂+淺顯易懂+程序源碼)

若該文爲原創文章,未經允許不得轉載
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客導航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/106200662
各位讀者,知識無窮而人力有窮,要麼改需求,要麼找專業人士,要麼自己研究
紅胖子(紅模仿)的博文大全:開發技術集合(包含Qt實用技術、樹莓派、三維、OpenCV、OpenGL、ffmpeg、OSG、單片機、軟硬結合等等)持續更新中…(點擊傳送門)

OpenCV開發專欄(點擊傳送門)

上一篇:《OpenCV開發筆記(五十六):紅胖子8分鐘帶你深入瞭解多種圖形擬合逼近輪廓(圖文並茂+淺顯易懂+程序源碼)
下一篇:持續補充中…


前言

  紅胖子,來也 !
  做了部分人臉識別後,又回到直方圖相關的研究-直方圖方向投影。


Demo

  在這裏插入圖片描述
  在這裏插入圖片描述
  在這裏插入圖片描述
  在這裏插入圖片描述
  在這裏插入圖片描述


直方圖

  參考博文《OpenCV開發筆記(四十七):紅胖子8分鐘帶你深入瞭解直方圖(圖文並茂+淺顯易懂+程序源碼)


直方圖反向投影

概述

  反向投影是計算像素和直方圖模型中像素吻合度的一種方法。
  通俗來說,就是用已知一個對象的直方圖模型去目標圖像中尋找是否有相似的對象。例如,如果有膚色的直方圖,可以使用反向投影來在圖像中尋找膚色區域。
  有一點需要注意,反向投影中一般使用HSV色彩空間,使用HS兩個通道直方圖模型去進行匹配計算。

關於HSV顏色空間

  HSV是一種將RGB色彩空間中的點在倒圓錐體中的表示方法。HSV即色相(Hue)、飽和度(Saturation)、明度(Value),又稱HSB(B即Brightness)。色相是色彩的基本屬性,就是平常說的顏色的名稱,如紅色、黃色等。飽和度(S)是指色彩的純度,越高色彩越純,低則逐漸變灰,取0-100%的數值。明度(V),取0-max(計算機中HSV取值範圍和存儲的長度有關)。HSV顏色空間可以用一個圓錐空間模型來描述。

  • 圓錐的頂點處,V=0,H和S無定義,代表黑色;
  • 圓錐的頂面中心處V=max,S=0,H無定義,代表白色;
    在這裏插入圖片描述

反向投影原理

  • 步驟一:先將已知的圖片進行顏色空間轉換爲HSV顏色空間;
  • 步驟二:對H通道進行單元劃分起二維空間上計算對應直方圖;
  • 步驟三:計算直方圖空間上的最大值,並進行歸一化繪製響應的直方圖信息;
  • 步驟四:計算反向投影圖像;

計算反向投影函數原型

/** @overload */
void calcBackProject( const Mat* images,
                   int nimages,
                   const int* channels,
                   const SparseMat& hist,
                   OutputArray backProject,
                   const float** ranges,
                   double scale = 1,
                   bool uniform = true );
/** @overload */
void calcBackProject( InputArrayOfArrays images,
                   const std::vector<int>& channels,
                   InputArray hist,
                   OutputArray dst,
                   const std::vector<float>& ranges,
                   double scale );
void calcBackProject( const Mat* images,
                   int nimages,
                   const int* channels,
                   InputArray hist,
                   OutputArray backProject,
                   const float** ranges,
                   double scale = 1,
                   bool uniform = true );
  • 參數一:const Mat*類型的images,輸入的數組(或數組集),它們須爲相同的深度(CV_8U或CV_32F)和相同的尺寸,而通道數則可以任意;
  • 參數二:int類型的nimages,輸入數組的個數,也就是第一個參數中存放了多少張image;
  • 參數三:const int*類型的channels,需要統計的通道(dim)索引。第一個數組通道從0到images[0].channels()-1,而第二個數組通道從images[0].channels()到images[0].channels()+images[1].channels()–1;
  • 參數四:InputArray類型的hist,輸入的直方圖;
  • 參數五:OutputArray類型的backProject,目標反向投影陣列,其須爲單通道,並且和image[0]有相同的大小和深度;
  • 參數六:const float**類型的ranges,表示每一個維度數組(第六個參數dims)的每一維的邊界陣列,可以理解爲每一維數值的取值範圍;
  • 參數七:double類型的scale,有默認值1,輸出的方向投影可選的縮放因子;
  • 參數八:bool類型的uniform,指示直方圖是否均勻的標識符,有默認值true;

Demo源碼

void OpenCVManager::testCalcBackProject()
{
    QString fileName1 =
            "E:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/19.jpg";
    cv::Mat srcMat = cv::imread(fileName1.toStdString());
    cv::Mat dstMat;
    int width = 400;
    int height = 300;

    cv::resize(srcMat, srcMat, cv::Size(width, height));

    cv::String windowName = _windowTitle.toStdString();
    cvui::init(windowName);

    cv::Mat windowMat = cv::Mat(cv::Size(srcMat.cols * 2,
                                         srcMat.rows * 2),
                                srcMat.type());

    cv::Mat allMat = cv::Mat(srcMat.rows, srcMat.cols, srcMat.type());
    allMat = cv::Scalar(0, 0, 0);

    int bins = 255;
    while(true)
    {
        // 刷新全圖黑色
        windowMat = cv::Scalar(0, 0, 0);

        // 原圖複製
        cv::Mat mat = windowMat(cv::Range(srcMat.rows * 0, srcMat.rows * 1),
                                cv::Range(srcMat.cols * 0, srcMat.cols * 1));
        cv::addWeighted(mat, 0.0f, srcMat, 1.0f, 0.0f, mat);

        {
            // 步驟一:先將已知的圖片進行顏色空間轉換爲HSV顏色空間;
            cv::Mat hsvMat;
            cv::cvtColor(srcMat, hsvMat, cv::COLOR_BGR2HSV);
            // 步驟二:對H和S通道進行分離,計算H上的直方圖;
            cv::Mat hueMat;
            hueMat.create(hsvMat.size(), hsvMat.depth());
            int channel[] = {0, 0};
            cv::mixChannels(&hsvMat, 1, &hueMat, 1, channel, 1);
            // 步驟三:計算直方圖空間上的最大值,並進行歸一化繪製響應的直方圖信息;
            // 調整bins值2~255
            cvui::printf(windowMat, 75 + width * 1, 20 + height * 0, "thresh");
            cvui::trackbar(windowMat, 75 + width * 1, 40 + height * 0, 165, &bins, 2, 255);
            cv::MatND hueHistMat;
            int histSize = MAX(bins, 2);
            float hueRange[] = {0, 180};
            const float *ranges = {hueRange};
            cv::calcHist(&hueMat, 1, 0, cv::Mat(), hueHistMat, 1, &histSize, &ranges, true, false);
            cv::normalize(hueHistMat, hueHistMat, 0, 255, cv::NORM_MINMAX, -1, cv::Mat());
            // 步驟四:計算反向投影圖像
            cv::MatND backprojectMat;
            cv::calcBackProject(&hueMat, 1, 0, hueHistMat, backprojectMat, &ranges, 1, true);

            // copy顯示
            mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2),
                            cv::Range(srcMat.cols * 0, srcMat.cols * 1));
            cv::cvtColor(backprojectMat, dstMat, cv::COLOR_GRAY2BGR);
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);

            // 對直方圖進行均衡化
            mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2),
                            cv::Range(srcMat.cols * 1, srcMat.cols * 2));
            cv::equalizeHist(backprojectMat, dstMat);
            cv::cvtColor(dstMat, dstMat, cv::COLOR_GRAY2BGR);
            cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);
        }

        // 更新
        cvui::update();
        // 顯示
        cv::imshow(windowName, windowMat);
        // esc鍵退出
        if(cv::waitKey(25) == 27)
        {
            break;
        }
    }
}  

工程模板:對應版本號v1.51.0

  對應版本號v1.51.0


上一篇:《OpenCV開發筆記(五十六):紅胖子8分鐘帶你深入瞭解多種圖形擬合逼近輪廓(圖文並茂+淺顯易懂+程序源碼)
下一篇:持續補充中…


原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客導航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/106200662

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章