入门,学习笔记之一,很简单,算法很傻,只能说可以实践实践大概的流程吧,欢迎评论,欢迎指导。直接上源码,觉得算法核心主要有两部分吧。第一是提取出肤色区域,第二部分连通域及其坐标值的获得。
// color_detection.cpp : 定义控制台应用程序的入口点。
//
//----------------------------------------本程序用于肤色检测-------------------------------------------//
#include "stdafx.h"
#include <cv.h>
#include <cvaux.h>
#include <highgui.h>
#include <ml.h>
#include <cxcore.h>
//利用RGB方法进行肤色检测
void Skin_RGB_draw(IplImage *src, IplImage *dst)
{
int step = src->widthStep;
int channels = src->nChannels;
static int B=0;
static int G=0;
static int R=0;
cvNamedWindow("win1",1);
cvMoveWindow("win1",100,100);
cvNamedWindow("win2",1);
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* contour = 0;
CvSeq *contmax = 0;
CvRect rect=cvRect(0,0,0,0);
IplImage* _dst=cvCreateImage(cvGetSize(src),8,3);
cvZero(_dst);
IplImage* _mask=cvCreateImage(cvGetSize(src),8,1);
for (int i = 0; i < src->height; i++)
{
for (int j = 0; j < src->width; j++)
{
uchar *data_src = (uchar *)src->imageData+i*step+j*channels;
uchar *data_dst = (uchar *)_dst->imageData+i*step+j*channels;
B=*(data_src+0);
G=*(data_src+1);
R=*(data_src+2);
if (R>95 && G>40 && B>20 && (R-B)>15 && abs(R-G)>15 && R>G && R>B) //满足肤色的条件
{
memcpy(data_dst,data_src,channels);
}
else
{
continue;
}
}
}
cvCvtColor(_dst,_mask,CV_RGB2GRAY);
cvThreshold(_mask, _mask, 1, 255, CV_THRESH_BINARY );//二值化
cvShowImage("win1",_mask);
cvFindContours(_mask, storage, &contour, sizeof(CvContour),
CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); //提取出最外面的轮廓
double area,maxArea =100;//过滤掉连通区域过小的连通区域,阈值的确定现在固定,以后最好能做到动态确定
for( ; contour != 0; contour = contour->h_next )
{
area =fabs(cvContourArea( contour, CV_WHOLE_SEQ )); //获取当前轮廓面积
printf("area == %lf\n", area);
if (area>maxArea)
{
contmax=contour;//找出最大连通区域
maxArea=area;
rect=cvBoundingRect(contmax,0);
printf("x=%d,y=%d,width=%d,height=%d",rect.x,rect.y,rect.width,rect.height);
}
}
cvRectangle(src,cvPoint(rect.x,rect.y),
cvPoint(rect.x+rect.width,rect.y+rect.height),
cvScalar(0,0,255),2,8,0);
cvShowImage("win2",src);
cvCopyImage(src,dst);
cvReleaseImage(&_mask);
}
int _tmain(int argc, _TCHAR* argv[])
{
IplImage *img = 0;
IplImage *dst = 0;
img = cvLoadImage("D:/OpenCV2.1/samples/c/sharmy.jpg",1);
dst=cvCreateImage(cvGetSize(img),8,3);
if (!img)
{
printf("could not load image");
exit(0);
}
Skin_RGB_draw(img,dst);
cvWaitKey(0);
cvReleaseImage(&img);
return 0;
}
检测结果:
下一步使用HSV方法来提取肤色区域,据大牛说,HSV颜色空间受光照影响不大,再下一步就是进入视频捕捉肤色区域。