基於二維直方圖的閾值分割

利用攝像頭獲取YUV422 640*480,然後變換爲YUV444 320*240,這種操作可以一定程度上增加圖像本身的清晰度(當然相對與直接獲取320*240的圖像)。

在 YCrCb 顏色空間中,Y 值主要表徵亮度,顏色主要由Cr 和 Cb 決定,因而直方圖由原本灰度圖像的一維變爲彩色圖像的 CrCb 維。考慮到二維空間上搜索峯值比較複雜,爲了簡化問題,將 Cr 和 Cb 的取值範圍 0-255 均分爲 32 份,其顏色落在同一區間的所有像素點累計在一起,只要搜索其中累計點數最多的“塊”即可,同時也大大減少了搜索時間。

通過大量實驗表明,比賽中的幾種重要顏色的CrCb分量在不同的光照變動並不明顯,完全可以在特定範圍內進行搜索。每一個峯值應該都有與之對應的物體。因此根據峯值出現的Cr和Cb取值範圍就可以回到圖像中找到對應的像素點,完成圖像分割的工作。下圖1爲根據實驗得到的二維直方圖。從圖中可以看出黃色與橙色有交叉。

在實際處理時需要考慮各種可能的情況:如果區域內出現兩個峯值,可以據 Cr 的數值加以判斷;如果有一個峯值,則要結合圖像中其他顏色出現的情況,如果有相當數量的粉色像素點,說明是球門柱的黃色;如果該峯值點數很多,說明是球門的黃色,否則是球的橙色。圖2爲分割的實驗結果。這種方法對於黃色藍色橙色的分割效果比較好,在光照變化不是很明顯的情況下可以有效的找到目標區域。

C++源程序:

// CvTest.cpp : 定義控制檯應用程序的入口點。
//

#include "stdafx.h"
#include <highgui.h>
#include <cv.h>
#include <fstream>
using namespace std;
using namespace cv;

int _tmain(int argc, _TCHAR* argv[])
{
	int hist[32][32]={0};
	CvScalar ptr = {};
	ofstream outfile;
	outfile.open("new.txt",ios::out);
	IplImage* src = cvLoadImage("show8.jpg", 1);
	IplImage* YUVImage = cvCreateImage(cvGetSize(src),8,3);
	CvPoint ycount={};
	int yColorNumber = 0;
	CvPoint ocount={};
	int oColorNumber = 0;
	CvPoint bcount={};
	int bColorNumber = 0;

	CvPoint ycenter={};
	CvPoint ocenter = {};
	CvPoint bcenter = {};


	cvCvtColor( src, YUVImage, CV_RGB2YCrCb );

	for (int x=0;x<YUVImage->width;x++)
	{
		for (int y=0;y<YUVImage->height;y++)
		{
			ptr = cvGet2D(YUVImage,y,x);
			hist[((unsigned)ptr.val[1])/8][((unsigned)ptr.val[2])/8]++;
			//blue max point(20,10)
			if ((unsigned)ptr.val[1]>149 && (unsigned)ptr.val[1]<175  &&  (unsigned)ptr.val[2]>50 && (unsigned)ptr.val[2]<90 )
			{
				ptr.val[0]=255;
				ptr.val[1]=0;
				ptr.val[2]=0;
				cvSet2D(src,y,x,ptr);
				bcount.x = bcount.x + x;
				bcount.y = bcount.y + y;
				bColorNumber++;
				continue;
			}
			//yellow max point(12,16)
			if ((unsigned)ptr.val[1]>80 && (unsigned)ptr.val[1]<110 &&  (unsigned)ptr.val[2]>80 && (unsigned)ptr.val[2]<159)
			{
				ptr.val[0]=0;
				ptr.val[1]=255;
				ptr.val[2]=255;
				cvSet2D(src,y,x,ptr);
				ycount.x = ycount.x + x;
				ycount.y = ycount.y + y;
				yColorNumber++;
				continue;
			}
			//origion max point(8,23)
			if ((unsigned)ptr.val[1]>40 && (unsigned)ptr.val[1]<105 &&  (unsigned)ptr.val[2]>160 && (unsigned)ptr.val[2]<250)
			{
				ptr.val[0]=0;
				ptr.val[1]=67;
				ptr.val[2]=255;
				cvSet2D(src,y,x,ptr);
				ocount.x = ocount.x + x;
				ocount.y = ocount.y + y;
				oColorNumber++;
				continue;
			}
			//green max point(16,13)
			if ((unsigned)ptr.val[1]>128 && (unsigned)ptr.val[1]<150 &&  (unsigned)ptr.val[2]>85&& (unsigned)ptr.val[2]<125)
			{
				ptr.val[0]=0;
				ptr.val[1]=255;
				ptr.val[2]=0;
				cvSet2D(src,y,x,ptr);
				continue;
			}
			

		}
	}
	for (int i=0;i<32;i++)
	{
		for (int j=0;j<32;j++)
		{
			if (hist[i][j]!=0)
			{
				printf("(x,y) (%d ,%d) :%d\n",i,j,hist[i][j]);
			}
			outfile<<hist[i][j]<<endl;
			
		}
	}
	
	ycenter.x  = ycount.x/yColorNumber;
	ycenter.y  = ycount.y/yColorNumber;

	ocenter.x = ocount.x/oColorNumber;
	ocenter.y = ocount.y/oColorNumber;

	bcenter.x = bcount.x/bColorNumber;
	bcenter.y = bcount.x/bColorNumber;

	cvCircle(src,ycenter,4,CV_RGB(255,100,0),-1,8,0);
	cvCircle(src,ocenter,4,CV_RGB(0,255,255),-1,8,0);	
	cvCircle(src,bcenter,4,CV_RGB(255,0,0),-1,8,0);


	cv::namedWindow("image",CV_WINDOW_AUTOSIZE);
	cv::imshow("image",src);
	cvWaitKey(0);
	outfile.close();
	return 0;
}


matlab程序:生成2維直方圖

function [ output_args ] = Untitled3( input_args )
%UNTITLED3 Summary of this function goes here
%   Detailed explanation goes here

m=32;
n=32;
[i,j]=ndgrid(1:m,1:n);

count=0;
fp=fopen('new.txt');
B=fscanf(fp,'%f');
A = zeros(32,32);
for ii=1:32
    for jj=1:32
        
        A(ii,jj)=B(jj+count);
    end
    count = count+32;
end

%A=rand(m,n)./(0.1+abs(i/500-.5))./(0.1+abs(j/40-.5))
bar3(A)
axis([0,n,0,m])
camproj perspective
view(-8,10)
xlabel('Cr')
ylabel('Cb')
zlabel('統計值')
end



發佈了59 篇原創文章 · 獲贊 91 · 訪問量 41萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章