1. 程式人生 > >0018-影象直方圖的反向投影的計算

0018-影象直方圖的反向投影的計算

直方圖反向投影的用途這裡暫時不講,先給大家看一個簡單的例子,通過這個例子讓大家瞭解到直方圖反向投影是怎麼樣的一種運算,大家瞭解它的運算後就可以發揮自己的才智去運用它了。

設有原灰度影象矩陣:

Image=
  9    5    7    9
  1    2    3    5
  6    7    8    1
  2    3    5    6

將灰度值劃分為如下四個區間:

[0,2]   [3,5]   [6,7]   [8,10]

很容易得到這個影象矩陣的直方圖hist= 4  5  4  3

好,接下來計算反向投影矩陣:

反向投影矩陣的大小和原灰度影象矩陣的大小相同!

原影象中座標為(0,0)的灰度值為9,9位於區間[8,10] 中,區間[8,10] 對應的直方圖值為3,所以反向投影矩陣中中座標為(0,0)的值記為3

按上面的計算方法,可以得到Image的直方圖反向投影矩陣為:

back_Projection=
  3    5    4    3
  4    4    5    5
  4    4    3    4
  4    5    5    4
從上面的計算過程我們來理解直方圖的反向投影到底代表什麼

各位朋友,如果你想知道“直方圖的反向投影到底代表什麼”,可以搜尋公眾號"qxsf321",並關注,然後回覆0018獲取答案。

OpenCV提供了函式calcBackProject來計算影象的直方圖反向投影,函式原型如下
C++: void calcBackProject(const Mat* images, int nimages, const int* channels, InputArray hist, OutputArray backProject, const float** ranges, double scale=1, bool uniform=true )
引數介紹下
images

:源影象陣列指標
nimages:源影象張數
channels:要計算直方圖反向投影的通道編號。通道編號方法:第一張圖的通道編號為0至images[0].channels()-1,第二張圖的通道編號為images[0].channels()至images[0].channels() + images[1].channels()-1,以此類推,注意這個引數是指標。
hist:影象的直方圖矩陣
backProject:函式計算出的直方圖反向投影圖的儲存矩陣
ranges:各個通道取值的邊界值或區間劃分。
scale:反向投影圖的尺度係數。最終函式生成的的反向投影圖會乘以這個係數。
uniform:直方圖是否均勻化的標誌,意義暫時不清楚,等以後搞清楚了再來補充說明。

用函式calcBackProject來計算影象的直方圖反向投影的原始碼如下
原始碼中使用的影象下載連結:http://pan.baidu.com/s/1kUJMx1t 密碼:r3d3

//opencv版本:OpenCV3.0
//VS版本:VS2013
//Author:qxsf321.net

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>    
#include <opencv2/imgproc/types_c.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/highgui/highgui_c.h>

#include <iostream>

using namespace cv;
using namespace std;

int main()
{

        Mat img = imread("02.jpg");
        if (img.empty())
        {
                cout << "Error: Could not load image" << endl;
                return 0;
        }

        Mat srcImage;
        cvtColor(img, srcImage, CV_BGR2GRAY);

        imshow("【原圖的灰度圖】", srcImage);

        //為計算直方圖配置變數  
        //首先是需要計算的通道編號,就是需要計算哪個通道的直方圖(BGR空間需要確定計算,計算方法見帖子中對相關引數的說明)  
        int channels = 0;
        //然後是定義直方圖計算結果的儲存空間
        Mat dstHist;
        //接下來是直方圖的每一個維度的數目(這個數目用於將每一維度的數值分組)  
        int histSize[] = { 256 };
        //最後是確定每個維度的取值範圍,就是每一維度的橫座標的取值範圍  
        //首先得定義一個數組用來儲存單個維度的的取值範圍  
        float midRanges[] = { 0, 256 };
        //然後把這個陣列再放到一個二維陣列中
        const float *ranges[] = { midRanges };

        const float *ranges2 = { midRanges };

        //準備工作做好後,就可以呼叫calcHis函式計算直方圖資料了
        calcHist(&srcImage, 1, &channels, Mat(), dstHist, 1, histSize, ranges, true, false);

        //calcHist函式呼叫結束後,dstHist變數中將儲存直方圖資料 

        //對直方圖資料進行歸一化處理,把值歸一化到0到255
        normalize(dstHist, dstHist, 0, 255, NORM_MINMAX, -1, Mat());

        // 計算反向投影
        Mat backproj;
        calcBackProject(&srcImage, 1, 0, dstHist, backproj, &ranges2, 1, true);

        /// Draw the backproj  
        imshow("BackProj", backproj);

        waitKey(0);

        return 0;
}


程式碼說明
計算直方圖的程式碼這裡就不說了,不清楚的可參看博文https://blog.csdn.net/lehuoziyuan/article/details/84064822
這裡說下歸一化函式normalize,原型如下
C++: void normalize(InputArray src, InputOutputArray dst, double alpha=1, double beta=0, int norm_type=NORM_L2, int dtype=-1, InputArray mask=noArray() )
引數意義如下
src:待歸一化的矩陣
dst:歸一化後的矩陣
alpha:歸一化後值的下邊界
beta: 歸一化後值的上邊界,這個值當normType=NORM_L1或normType=NORM_L2時無效。
normType:歸一化型別,具體型別如下有NORM_INF, NORM_L1, or NORM_L2,實際上是選擇哪個數成為歸一化後的最大值。當為NORM_INF時,最大值為beta;當為NORM_L1時,最大值為矩陣的L1範數;當為NORM_L2時,最大值為矩陣的L2範數;
dtype:當這個值為負值時,輸出矩陣和輸入矩陣的資料型別一致;當為其它值時,不僅資料型別要一致,深度和通道數也要一樣。
mask:掩碼陣列。掩碼中的非0元素對應的影象元素將會被計算,0元素則被遮蔽不參與計算,可選引數。
程度執行結果截圖如下