openCV -- rectangle函數的使用+統計直方圖


void rectangle(Mat& img, Point pt1,Point pt2,const Scalar& color, int thickness=1, int lineType=8, int shift=0)

  

img 圖像.

pt1 矩形的一個頂點。

pt2 矩形對角線上的另一個頂點

color 線條顏色 (RGB) 或亮度(灰度圖像 )(grayscale image)。

thickness 組成矩形的線條的粗細程度。取負值時(如 CV_FILLED)函數繪制填充了色彩的矩形。

line_type 線條的類型。

 

其中關於坐標點pt1以及pt2的說明一個矩形的一個頂點,pt2則是相對pt1的另外一點,即確定一個矩形,只需要矩形對角線上的兩點即可,這個很好理解。但是指定這兩個點的時候是很有考究的。筆者做了一個測試,測試代碼為,當然筆者最近在這一個關於圖像處理的一個小型的MFC程序,正在構建階段,因此直接在該程序框架上試驗:

void CMFC_OpenCVtestDlg::OnGrayHist()
{
	// TODO:  在此添加命令處理程序代碼
	Mat image(img);
 
	cvtColor(image,image,CV_BGR2GRAY);
	float range[] = { 0, 255 };
	const float *histRange[] = { range };
	MatND dsthist;
	int bins = 256;
	int hist_size[] = { bins };
	int channnels = 0;
	//------------------------------------------------------//
	calcHist(&image, 1, &channnels, Mat(), dsthist, 1, hist_size, histRange, true, false);
	double max_Value, min_Value;
	minMaxLoc(dsthist, &min_Value, &max_Value, 0, 0);
 
	int histHeight = 256;
	Mat Histimage = Mat::zeros(histHeight, bins, CV_8UC3);
	IplImage *pImage;
	for (int i = 0; i < bins; i++)
	{
		float binValue = dsthist.at<float>(i);
		int intensity = cvRound(binValue*histHeight / max_Value);
		rectangle(Histimage, Point(i, histHeight - 1), Point(i + 1, histHeight - intensity), Scalar(255,128,64));
	}
 
	//imshow("Hist",Histimage);
	pImage = &Histimage.operator IplImage();
	DrawToMFC(IDC_PROG, pImage);
	GetDlgItem(IDC_Hist)->SetWindowTextA("灰色直方圖");
}

其中:img是一個IplImage *類型的變量,這是一個全局變量,主要是因為在OpenCV2.2版本以后,CvvImage類被取消掉了,因此在OpenCV3.0與MFC結合,在picture控件上顯示圖像時出現了麻煩,因此將CvvImage.cpp以及CvvImage.h拷貝到了工程目錄下使用。而CvvImage類的成員函數Copyof(IplImage *pImage)只接受IplImage *類型的變量,因此定義了一個該全局變量(ps:這個真是對程序的說明,不是本文討論的重點)

void CMFC_OpenCVtestDlg::DrawToMFC(int Ctrol_ID, IplImage * pImage)
{
	CDC* pDC = GetDlgItem(Ctrol_ID)->GetDC();
	HDC hDC = pDC->GetSafeHdc();
	CvvImage cimg;
	cimg.CopyOf(pImage);
	CRect rect;
	GetDlgItem(Ctrol_ID)->GetClientRect(&rect);
	cimg.DrawToHDC(hDC, &rect);
	ReleaseDC(pDC);
}

  

錯誤理解:在函數OnGrayHist()中,關於pt1,pt2的設置是:Point(i, histHeight - 1), Point(i + 1, histHeight - intensity);

如果我們將pt1,pt2理解為一個矩形的左上角坐標以及右上角坐標,那么疑問就來了,豈不是每一個直方圖的點都在最頂端,畫出來的矩形和我們理解的矩形就是倒着的了,筆者也是這么認為的,因此看了良久,決定把代碼改了,把pt1,pt2的坐標改為了:Point(i, 0), Point(i + 1, intensity);這樣畫出來的矩形就應該和我們想象中的一樣了,結果卻不是這樣的:

 

恰恰和我們理解的相反,因此正確的理解應該是這樣的:

在計算過程中,intensity是相應的統計點的數量,Height是畫圖區域的高,在點pt1的橫坐標表示的統計點,也就是像素1到256的點,在區域中表示為橫坐標,而縱坐標則不是表示的到橫坐標的縱向距離,而是到畫圖區域最高點的距離,因此設置為Height,則等同於到橫坐標的縱向距離為0;p2的解釋也就更能理解了,i+1表示矩形的寬度為1,

而縱坐標Height-intensity則是該統計點的高度,也就是頻數。

因此將pt1和pt2理解為左下角右上角的含義才更為貼切。

為了驗證想法否正確,將rectangle()函數的相應代碼修改:

rectangle(Histimage, Point(i, histHeight - 1), Point(i + 1, histHeight - intensity_red), Scalar(0, 0, 255));

 

 

  

 

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM