基于二维直方图的阈值分割

利用摄像头获取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 
#include 
#include 
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;xwidth;x++)
	{
		for (int y=0;yheight;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<


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



你可能感兴趣的:(C/C++)