天天看點

opencv學習之四:rgb通道的分離以及直方圖的顯示計算1、rgb分離2、直方圖的顯示計算:3、直方圖反向投影

1、rgb分離

rgb分離用一個簡單的函數split即可,注意,分離之後如果分别顯示3個通道,得到的結果将是都是灰色的。需要将生成的3個單通道merge一下,才是我們看到的效果:

opencv學習之四:rgb通道的分離以及直方圖的顯示計算1、rgb分離2、直方圖的顯示計算:3、直方圖反向投影

split和merge的代碼如下:

vector<Mat> bgr_planes(src.channels());
		vector<Mat> mbgr(src.channels());
		
		split(src, bgr_planes);

		mbgr[0] = bgr_planes[2];
		mbgr[1] = zero;
		mbgr[2] = zero;
		merge(mbgr, displayb);

		mbgr[0] = zero;
		mbgr[1] = bgr_planes[1];
		mbgr[2] = zero;	
		merge(mbgr, displayg);
	
		mbgr[0] = zero;
		mbgr[1] = zero;
		mbgr[2] = bgr_planes[0];
		merge(mbgr, displayr);

		imshow("r",displayr);
		imshow("g", displayg);
		imshow("b", displayb);
           

2、直方圖的顯示計算:

使用的是calcHist函數,我們将圖像的3個通道分離之後,分别計算3個通道的直方圖。 calcHist(&bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate);中bgr_planes為要計算的直方圖圖像,為mat類型,b_hist儲存計算之後的直方圖,histSize, histRange分别為大小和範圍。

Mat histImage(hist_h, hist_w, CV_8UC3, Scalar(0, 0, 0));建立了一個畫布顯示直方圖, normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());直方圖均衡化。

3、直方圖反向投影

以下摘自連結: http://blog.163.com/[email protected]/blog/static/370829982010112810358501/     圖像的反向投影圖是用輸入圖像的某一位置上像素值(多元或灰階)對應在直方圖的一個bin上的值來代替該像素值,是以得到的反向投影圖是單通的。用統計學術語,輸出圖像象素點的值是觀測數組在某個分布(直方圖)下的機率。

opencv學習之四:rgb通道的分離以及直方圖的顯示計算1、rgb分離2、直方圖的顯示計算:3、直方圖反向投影

  其中 b(xi) 表示在位置 xi 上像素對應的直方圖第 b(xi) 個 bin ,直方圖共 m 個 bin ,qu表示第u個bin的值。

還是以例子說明 (1)例如灰階圖像如下

Image=

  0    1    2    3

  4    5    6    7

  8    9   10   11

  8    9   14   15

(2)該灰階圖的直方圖為(bin指定的區間為[0,3),[4,7),[8,11),[12,16)

Histogram=

  4    4    6    2

(3)反向投影圖

Back_Projection=

  4    4    4    4

  4    4    4    4

  6    6    6    6

  6    6    2    2

例如位置(0,0)上的像素值為0,對應的bin為[0,3),是以反向直方圖在該位置上的值這個bin的值4。

以下部分摘自連接配接

http://blog.csdn.net/yee_yj/article/details/6035913

1.反向投影的作用是什麼?

    反向投影用于在輸入圖像(通常較大)中查找特定圖像(通常較小或者僅1個像素,以下将其稱為模闆圖像)最比對的點或者區域,也就是定位模闆圖像出現在輸入圖像的位置。

2.反向投影如何查找(工作)?

    查找的方式就是不斷的在輸入圖像中切割跟模闆圖像大小一緻的圖像塊,并用直方圖對比的方式與模闆圖像進行比較。

假設我們有一張100x100的輸入圖像,有一張10x10的模闆圖像,查找的過程是這樣的:

(1)從輸入圖像的左上角(0,0)開始,切割一塊(0,0)至(10,10)的臨時圖像;

(2)生成臨時圖像的直方圖;

(3)用臨時圖像的直方圖和模闆圖像的直方圖對比,對比結果記為c;

(4)直方圖對比結果c,就是結果圖像(0,0)處的像素值;

(5)切割輸入圖像從(0,1)至(10,11)的臨時圖像,對比直方圖,并記錄到結果圖像;

(6)重複(1)~(5)步直到輸入圖像的右下角。

************************************************************************************************************************************* 全部代碼如下:

/**
* @function calcHist_Demo.cpp
* @brief Demo code to use the function calcHist
* @author
*/

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>

using namespace std;
using namespace cv;

/**
* @function main
*/


int main(int, char** argv)
{


	
	VideoCapture  cap(0);
	  
	


	/// Load image
	
	if (!cap.isOpened())
	{
		return -1;
	}

	while (1)

	{
		Mat src;
		cap >> src;
		/// Separate the image in 3 places ( B, G and R )
		int w = src.cols;
		int h = src.rows;

		Mat displayr;
		Mat displayb;
		Mat displayg;


		displayr.create(h, w, CV_8UC3);
		displayg.create(h, w, CV_8UC3);
		displayb.create(h, w, CV_8UC3);

		Mat zero;
		zero.create(h, w, CV_8UC1);
		zero = Scalar(0);


		vector<Mat> bgr_planes(src.channels());
		vector<Mat> mbgr(src.channels());
		
		split(src, bgr_planes);

		mbgr[0] = bgr_planes[2];
		mbgr[1] = zero;
		mbgr[2] = zero;
		merge(mbgr, displayb);

		mbgr[0] = zero;
		mbgr[1] = bgr_planes[1];
		mbgr[2] = zero;	
		merge(mbgr, displayg);
	
		mbgr[0] = zero;
		mbgr[1] = zero;
		mbgr[2] = bgr_planes[0];
		merge(mbgr, displayr);

		imshow("r",displayr);
		imshow("g", displayg);
		imshow("b", displayb);

		
		/// Establish the number of bins
		int histSize = 256;

		/// Set the ranges ( for B,G,R) )
		float range[] = { 0, 256 };
		const float* histRange = { range };

		bool uniform = true; bool accumulate = false;

		Mat b_hist, g_hist, r_hist;

		/// Compute the histograms:
		calcHist(&bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate);
		calcHist(&bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate);
		calcHist(&bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate);

		// Draw the histograms for B, G and R
		int hist_w = 512; int hist_h = 400;
		int bin_w = cvRound((double)hist_w / histSize);

		Mat histImage(hist_h, hist_w, CV_8UC3, Scalar(0, 0, 0));

		/// Normalize the result to [ 0, histImage.rows ]
		normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
		normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
		normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());

		/// Draw for each channel
		for (int i = 1; i < histSize; i++)
		{
			line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(b_hist.at<float>(i - 1))),
				Point(bin_w*(i), hist_h - cvRound(b_hist.at<float>(i))),
				Scalar(255, 0, 0), 2, 8, 0);
			line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(g_hist.at<float>(i - 1))),
				Point(bin_w*(i), hist_h - cvRound(g_hist.at<float>(i))),
				Scalar(0, 255, 0), 2, 8, 0);
			line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(r_hist.at<float>(i - 1))),
				Point(bin_w*(i), hist_h - cvRound(r_hist.at<float>(i))),
				Scalar(0, 0, 255), 2, 8, 0);
		}

		/// Display
		namedWindow("calcHist Demo", WINDOW_AUTOSIZE);
		imshow("calcHist Demo", histImage);

		if (waitKey(33) > 0)
			break;


	}


	return 0;

}