写的很粗糙但非常实用
void shibie(IplImage *pSrcImage,IplImage* img_d,Surface* m)
{
//通过一个IplImag对象识别一个魔方面的状态img_d是通过去背景处理后的图
IplImage *g_pGrayImage = NULL;
CvSeq *g_pcvSeq = NULL;
//////////////////////////////
//增强关键颜色
CvScalar s;
for(int i=0;i<pSrcImage->height;i++){
for(int j=0;j<pSrcImage->width;j++){
s=cvGet2D(pSrcImage,i,j);
if(s.val[2]>230&&s.val[1]>110&&s.val[1]<170&&s.val[0]<100&&s.val[0]>30)
{
//增强橙色
s.val[0]=50;
s.val[1]=140;
s.val[2]=250;
cvSet2D(pSrcImage,i,j,s);
}else if(s.val[2]<25&&s.val[1]>140&&s.val[1]<200&&s.val[0]<120&&s.val[0]>50)
{
//增强绿色
s.val[0]=90;
s.val[1]=170;
s.val[2]=0;
cvSet2D(pSrcImage,i,j,s);
}else if(s.val[2]>0&&s.val[2]<29&&s.val[1]>36&&s.val[1]<70&&s.val[0]<220&&s.val[0]>170)
{
//增强蓝色
s.val[0]=190;
s.val[1]=50;
s.val[2]=10;
cvSet2D(pSrcImage,i,j,s);
}else if(s.val[2]>220&&s.val[2]<250&&s.val[1]>170&&s.val[1]<210&&s.val[0]<20)
{
//增强黄色
s.val[0]=10;
s.val[1]=190;
s.val[2]=220;
cvSet2D(pSrcImage,i,j,s);
}
}
}
// 显示颜色增强后原图
//cvNamedWindow("颜色增强后原图", CV_WINDOW_AUTOSIZE);
//cvShowImage("颜色增强后原图", pSrcImage);
//////////////////////////////
//去除背景
for(i=0;i<pSrcImage->height;i++)
{
for(int j=0;j<pSrcImage->width;j++)
{
s=cvGet2D(pSrcImage,i,j);
if(!((s.val[0]==50&&s.val[1]==140&&s.val[2]==250)||(s.val[0]==90&&s.val[1]==170&&s.val[2]==0)||(s.val[0]==190&&s.val[1]==50&&s.val[2]==10)||(s.val[0]==10&&s.val[1]==190&&s.val[2]==220)))
{
s.val[0]=0;
s.val[1]=0;
s.val[2]=0;
cvSet2D(pSrcImage,i,j,s);
}
}
}
// 转为灰度图
g_pGrayImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1);
cvCvtColor(pSrcImage, g_pGrayImage, CV_BGR2GRAY);
// 转为二值图
IplImage *pBinaryImage = cvCreateImage(cvGetSize(g_pGrayImage), IPL_DEPTH_8U, 1);
cvThreshold(g_pGrayImage, pBinaryImage, 0, 255, CV_THRESH_BINARY);
CvMemStorage* cvMStorage = cvCreateMemStorage();
// 检索轮廓并返回检测到的轮廓的个数
cvFindContours(pBinaryImage,cvMStorage, &g_pcvSeq,sizeof(CvContour),CV_RETR_EXTERNAL);
IplImage *pOutlineImage = cvCreateImage(cvGetSize(g_pGrayImage), IPL_DEPTH_8U, 3);
int _levels = 1;
cvZero(pOutlineImage);
cvDrawContours(pOutlineImage, g_pcvSeq, CV_RGB(255,0,0), CV_RGB(0,255,0), _levels);
cvShowImage("pstrWindowsOutLineTitle", pOutlineImage);
////////////////////
//在原图上绘制轮廓
//IplImage *pSrcImage = cvLoadImage("c:\\123.jpg", CV_LOAD_IMAGE_UNCHANGED);
cvDrawContours(pSrcImage, g_pcvSeq, CV_RGB(0,255,0), CV_RGB(0,255,0), _levels,3);
//////////////////////////////
//通过轮廓定位并计算魔方块坐标
int x,y,x1,y1,H,W,D,x2,y2;
x=y=x1=y1=1;
int B=1;//跳出标记
//找左上角
for(i=0;i<pSrcImage->height&&B==1;i++)
{
for(int j=0;j<pSrcImage->width&&B==1;j++)
{
s=cvGet2D(pSrcImage,i,j);
if(s.val[2]==0&&s.val[1]==255&&s.val[0]==0)
{
y=i;
B=0;
}
}
}
B=1;
for(int j=0;j<pSrcImage->width&&B==1;j++)
{
for(int i=0;i<pSrcImage->height&&B==1;i++)
{
s=cvGet2D(pSrcImage,i,j);
if(s.val[2]==0&&s.val[1]==255&&s.val[0]==0)
{
x=j;
B=0;
}
}
}
//找右下角
B=1;
for(i=pSrcImage->height-1;i>=0&&B==1;i--)
{
for(int j=pSrcImage->width-1;j>=0&&B==1;j--)
{
s=cvGet2D(pSrcImage,i,j);
if(s.val[2]==0&&s.val[1]==255&&s.val[0]==0)
{
y1=i;
B=0;
}
}
}
B=1;
for(j=pSrcImage->width-1;j>=0&&B==1;j--)
{
for(i=pSrcImage->height-1;i>=0&&B==1;i--)
{
s=cvGet2D(pSrcImage,i,j);
if(s.val[2]==0&&s.val[1]==255&&s.val[0]==0)
{
x1=j;
B=0;
}
}
}
H=y1-y;
W=x1-x;
D=(W+H)/6;
for(i=y+(D/2),y2=1;i<y1;i+=D,y2++)
for(j=x+(D/2),x2=1;j<x1;j+=D,x2++)
{
s=cvGet2D(pSrcImage,i,j);
if(s.val[0]==50&&s.val[1]==140&&s.val[2]==250) m->s[y2][x2]=(Colors)5;//橙色
if(s.val[0]==90&&s.val[1]==170&&s.val[2]==0) m->s[y2][x2]=(Colors)4;//绿色
if(s.val[0]==190&&s.val[1]==50&&s.val[2]==10) m->s[y2][x2]=(Colors)2;//蓝色
if(s.val[0]==10&&s.val[1]==190&&s.val[2]==220) m->s[y2][x2]=(Colors)6;//黄色
cvSet2D(pSrcImage,i,j,s);
}
s.val[0]=0;
s.val[1]=0;
s.val[2]=255;
cvSet2D(pSrcImage,y,x,s);
cvSet2D(pSrcImage,y1,x1,s);
for(i=y+(D/2);i<y1;i+=D)
for(j=x+(D/2);j<x1;j+=D)
{
cvSet2D(pSrcImage,i,j,s);
}
cvNamedWindow("定位矩形区域", CV_WINDOW_AUTOSIZE);
cvShowImage("定位矩形区域", pSrcImage);
/////////////////////
cvReleaseMemStorage(&cvMStorage);
cvReleaseImage(&pBinaryImage);
cvReleaseImage(&pOutlineImage);
}