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元素則被遮蔽不參與計算,可選引數。
程度執行結果截圖如下: