opencv人脸跟踪

yubangzi 2015-06-11 11:38:11
程序实现了人脸跟踪,但是圈出的人脸选框只想要方框,怎么破???

#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
#include <stdio.h>
#include <ctype.h>
#include<iostream>

using namespace std;

static CvHaarClassifierCascade* faceCascade = 0;
const char* cascade_name ="E:\\OpenCV-2.4.9\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml";

IplImage *image = 0, *hsv = 0, *hue = 0, *mask[10] = {0}, *backproject[10] = {0}, *histimg[10] = {0};//backproject为反向投影图像
CvHistogram *hist[10] = {0};//存储颜色直方图
int nFaces ;
double area0[100] = {0},area1[100] = {0};//某一跟踪窗口的面积

int backproject_mode = 0;
int select_object = 0;
int track_object = 0;

CvPoint origin;
CvRect selection[10];
CvRect track_window[10] = {0};
CvBox2D track_box;
CvConnectedComp track_comp;

int hdims = 24;
float hranges_arr[] = {0,180};
float* hranges = hranges_arr;
int vmin = 90, vmax = 256, smin = 90;

CvScalar hsv2rgb( float hue );
void detectFaceInImage( IplImage *inputImg, CvHaarClassifierCascade* cascade );

int main ( )
{
CvCapture* capture = 0;
capture = cvCaptureFromCAM( 0 );

if( !capture )
{
fprintf(stderr,"Could not initialize capturing...\n");
return -1;
}

cvNamedWindow( "CamShiftDemo", 1 );
cvCreateTrackbar( "Vmin", "CamShiftDemo", &vmin, 256, 0 );//Vmin被创建的trackbar名字,CamShiftDemo为工具条属于的窗口,vmin这个变量指定创建时的滑块位置
cvCreateTrackbar( "Vmax", "CamShiftDemo", &vmax, 256, 0 );
cvCreateTrackbar( "Smin", "CamShiftDemo", &smin, 256, 0 );

IplImage* frame = 0;
frame = cvQueryFrame( capture );

while(1)
{
int c ;

frame = cvQueryFrame( capture );//获取摄像头的序列,将图像序列存在frame中
if( !frame )
break;

if(!image)//image是进行处理的图像,开始的时候image = 0;若image =0,则要分配初始空间
{
image = cvCreateImage( cvGetSize(frame),8,3);
image->origin = frame->origin;
hsv = cvCreateImage( cvGetSize(frame), 8, 3 );
hue = cvCreateImage( cvGetSize(frame), 8, 1 );
}
cvCopy( frame, image, 0 );
cvCvtColor( image, hsv, CV_RGB2HSV );

faceCascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
if( !faceCascade )
{
fprintf( stderr, "ERROR: Could not load classifier cascade\n" );
return -1;
}

if(!track_object)
{
detectFaceInImage(image,faceCascade);
}//检测人脸区域,将检测到的一系列人脸区域存储到selection[]中,得到初始的搜索窗口

else//track_object = 1或者是-1,进行人脸跟踪
{
int _vmin = vmin, _vmax = vmax;

cvSplit( hsv, hue, 0, 0, 0 );//提取人脸图像的Hue分量

if(track_object<0)//track_object < 0 ,表示刚刚检测到人脸区域,然后进行人脸区域直方图计算
{

for(int n = 0;n < nFaces; n++)
{
mask[n] = cvCreateImage( cvGetSize(frame), 8, 1 );//得到全黑的mask
cvZero(mask[n]);

backproject[n] = cvCreateImage( cvGetSize(frame), 8, 1 );
hist[n] = cvCreateHist( 1, &hdims, CV_HIST_ARRAY, &hranges, 1 );

cvSetImageROI(mask[n],selection[n]);//此时是检测到的人脸区域用于得到掩膜
cvAddS(mask[n],cvScalar(255),mask[n]);//得到mask掩膜,用于求人脸部分的hue分量的直方图

float max_val = 0.f;
cvSetImageROI(hue,selection[n]);
cvDilate(hue,hue,NULL,2);
cvErode(hue,hue,NULL,2);
cvSmooth(hue,hue,CV_MEDIAN,3,0,0,0);

cvCalcHist( &hue, hist[n], 0, mask[n] );//建立人脸区域Hue分量的颜色直方图
cvResetImageROI(hue);//释放ROI区域
cvResetImageROI(mask[n]);
track_window[n] = selection[n];//此时的跟踪窗口是上步中人脸检测得到的区域。
track_object = 1;//计算得到图像的直方图后,是track_objedt=1 ,方便后面进行跟踪,且不在计算初始的搜索窗口的颜色直方图以及掩膜图像
}

}
else
{
for(int k = 0;k < nFaces; k++)
{
cvZero(mask[k]);
cvSetImageROI(mask[k],track_window[k]);//此时是用跟踪到的人脸区域得到掩膜图像
cvAddS(mask[k],cvScalar(255),mask[k]);
cvResetImageROI(mask[k]);//得到mask掩膜,用于求人脸部分的hue分量的直方图
}

}

//下面是利用上面得到的直方图,以及掩膜图像得到反向投影图像
for(int m = 0;m < nFaces ; m++ )
{
cvCalcBackProject( &hue, backproject[m], hist[m] );//计算人脸部分的hue分量在整幅图像中的反向投影图
cvAnd( backproject[m], mask[m], backproject[m], 0 );
cvDilate(backproject[m],backproject[m],NULL,2);
cvErode(backproject[m],backproject[m],NULL,2);
}

for(int m = 0;m < nFaces; m++)
{

cvCamShift( backproject[m], track_window[m],
cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ),
&track_comp, &track_box );//使用camshift进行人脸跟踪

area0[m] = track_window[m].height * track_window[m].width;
area1[m] = track_comp.rect.height * track_comp.rect.width;

track_window[m] = track_comp.rect;//重新设置搜索窗口

if( image->origin )
track_box.angle = -track_box.angle;
cvEllipseBox( image, track_box, CV_RGB(255,0,0), 3, CV_AA, 0 );
}

for(int l = 0; l < nFaces ;l++)
{
if ((0.4 * area0[l] <= area1[l]) && (area1[l] <= 1.1 * area0[l]))
track_object = 1;
else
track_object = 0;
}

}

cvShowImage( "CamShiftDemo", image );//显示的是人脸图像的跟踪情况

c = cvWaitKey(5);//此处过大的话时间就会等很久,在这个小问题上一定要注意,否则的话跟踪效率很低。
if( c == 27 )//ESC,退出程序
break;
}

cvReleaseCapture( &capture );
cvDestroyWindow("CamShiftDemo");

return 0;
}
//下面是颜色空间
CvScalar hsv2rgb( float hue )
{
int rgb[3], p, sector;
static const int sector_data[][3]=
{{0,2,1}, {1,2,0}, {1,0,2}, {2,0,1}, {2,1,0}, {0,1,2}};
hue *= 0.033333333333333333333333333333333f;
sector = cvFloor(hue);
p = cvRound(255*(hue - sector));
p ^= sector & 1 ? 255 : 0;

rgb[sector_data[sector][0]] = 255;
rgb[sector_data[sector][1]] = 0;
rgb[sector_data[sector][2]] = p;

return cvScalar(rgb[2], rgb[1], rgb[0],0);
}

void detectFaceInImage( IplImage* inputImg,CvHaarClassifierCascade* cascade)
{
CvSize minFeatureSize = cvSize(50,50);
int flags = CV_HAAR_DO_CANNY_PRUNING;
float search_scale_factor = 1.2f;
IplImage *detectImg;
IplImage *greyImg = 0;

CvMemStorage* storage;

CvSize size;
int ms;

storage = cvCreateMemStorage(0);
cvClearMemStorage( storage );

// If the image is color, use a greyscale copy of the image.
detectImg = (IplImage*)inputImg;
if (inputImg->nChannels > 1)
{
size = cvSize(inputImg->width, inputImg->height);
greyImg = cvCreateImage(size, IPL_DEPTH_8U, 1 );
cvCvtColor( inputImg, greyImg, CV_BGR2GRAY );
detectImg = greyImg; // Use the greyscale image.
}

// Detect all the faces in the greyscale image.
double t = (double)cvGetTickCount();
CvSeq* rects = cvHaarDetectObjects( detectImg, cascade, storage,search_scale_factor,2,flags, minFeatureSize);
t = (double)cvGetTickCount() - t;
ms = cvRound( t / ((double)cvGetTickFrequency() * 1000.0) );
nFaces = rects->total;
printf("Face Detection took %d ms and found %d objects\n", ms, nFaces);

if (nFaces > 0)
{
for(int i = 0; i < nFaces; i++)
{
selection[i] = *(CvRect*)cvGetSeqElem( rects, i );
cvRectangle(inputImg,cvPoint(selection[i].x-3,selection[i].y-3),cvPoint(selection[i].x+selection[i].width+2,selection[i].y+selection[i].height+2),CV_RGB(255,0,0),3);
track_object = -1;
}
}
else
selection[0] = cvRect(-1,-1,-1,-1);

if (greyImg)
cvReleaseImage( &greyImg );
cvReleaseMemStorage( &storage );
}

...全文
1826 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
请问楼主解决了吗?我老是觉得视频有点卡啊
kuangjiqingma 2016-11-17
  • 打赏
  • 举报
回复
请问这个人脸跟踪实时性怎么样??一帧图像的跟踪消耗多少ms
姚永祥 2016-08-19
  • 打赏
  • 举报
回复
楼主你好。请问这是个什么啊?const char* cascade_name ="E:\\OpenCV-2.4.9\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml";
ceerqingting66 2016-04-19
  • 打赏
  • 举报
回复
最终楼主解决了以上问题了么?求发一份解决版本给我吧,谢谢了~~
stephen_csdn 2016-04-15
  • 打赏
  • 举报
回复
引用 13 楼 yubangzi 的回复:
引用 12 楼 Dream_WHui 的回复:
谢谢可以了,,还有个问题辛苦一下您,就是画出的方框,总是一闪一闪的,是怎么回事?
这个很正常的,因为是一帧一帧处理的,每处理一帧就画一次矩形。
怎样改可以使当检测到人脸时方框一直保留,不是一闪一闪的[/quote]每一帧处理的速度快一点,应该就感觉不到一闪一闪了。这是程序的问题吧。[/quote] 刚开始学,不是特别懂[/quote] 没用过opencv组件,闪的话肯定是帧数问题,肉眼感觉到停顿,如果while是渲染循环的话,我看你有一个c = cvWaitKey(5);这个5是不是时间?如果是的话,你算一个时间,比如30帧的话,你可以填一个1/30试试?
llllllleizi 2016-04-15
  • 打赏
  • 举报
回复
请问有C++版本的么,跟C的差别大不大
qq_20653869 2016-04-15
  • 打赏
  • 举报
回复
请问这个使用C还是C++写的啊,两者的区别大么?
「已注销」 2015-06-13
  • 打赏
  • 举报
回复
引用 8 楼 Dream_WHui 的回复:
cvEllipseBox( image, track_box, CV_RGB(255,0,0), 3, CV_AA, 0 );//这个是画椭圆的函数
cvRectangle(inputImg,cvPoint(selection[i].x-3,selection[i].y-3),cvPoint(selection[i].x+selection[i].width+2,selection[i].y+selection[i].height+2),CV_RGB(255,0,0),3);//这个是画矩形的函数
你可以尝试将画椭圆的函数 注释掉!
谢谢可以了,,还有个问题辛苦一下您,就是画出的方框,总是一闪一闪的,是怎么回事?
Dream_WHui 2015-06-13
  • 打赏
  • 举报
回复
引用 9 楼 yubangzi 的回复:
[quote=引用 8 楼 Dream_WHui 的回复:]
cvEllipseBox( image, track_box, CV_RGB(255,0,0), 3, CV_AA, 0 );//这个是画椭圆的函数
cvRectangle(inputImg,cvPoint(selection[i].x-3,selection[i].y-3),cvPoint(selection[i].x+selection[i].width+2,selection[i].y+selection[i].height+2),CV_RGB(255,0,0),3);//这个是画矩形的函数
你可以尝试将画椭圆的函数 注释掉!
谢谢可以了,,还有个问题辛苦一下您,就是画出的方框,总是一闪一闪的,是怎么回事?[/quote]
引用 9 楼 yubangzi 的回复:
[quote=引用 8 楼 Dream_WHui 的回复:]
cvEllipseBox( image, track_box, CV_RGB(255,0,0), 3, CV_AA, 0 );//这个是画椭圆的函数
cvRectangle(inputImg,cvPoint(selection[i].x-3,selection[i].y-3),cvPoint(selection[i].x+selection[i].width+2,selection[i].y+selection[i].height+2),CV_RGB(255,0,0),3);//这个是画矩形的函数
你可以尝试将画椭圆的函数 注释掉!
谢谢可以了,,还有个问题辛苦一下您,就是画出的方框,总是一闪一闪的,是怎么回事?[/quote] 这个很正常的,因为是一帧一帧处理的,每处理一帧就画一次矩形。
「已注销」 2015-06-13
  • 打赏
  • 举报
回复
引用 12 楼 Dream_WHui 的回复:
谢谢可以了,,还有个问题辛苦一下您,就是画出的方框,总是一闪一闪的,是怎么回事?
这个很正常的,因为是一帧一帧处理的,每处理一帧就画一次矩形。[/quote] 怎样改可以使当检测到人脸时方框一直保留,不是一闪一闪的[/quote]每一帧处理的速度快一点,应该就感觉不到一闪一闪了。这是程序的问题吧。[/quote] 刚开始学,不是特别懂
Dream_WHui 2015-06-13
  • 打赏
  • 举报
回复
引用 11 楼 yubangzi 的回复:
引用 10 楼 Dream_WHui 的回复:
谢谢可以了,,还有个问题辛苦一下您,就是画出的方框,总是一闪一闪的,是怎么回事?
这个很正常的,因为是一帧一帧处理的,每处理一帧就画一次矩形。
怎样改可以使当检测到人脸时方框一直保留,不是一闪一闪的[/quote]每一帧处理的速度快一点,应该就感觉不到一闪一闪了。这是程序的问题吧。
「已注销」 2015-06-13
  • 打赏
  • 举报
回复
引用 10 楼 Dream_WHui 的回复:
谢谢可以了,,还有个问题辛苦一下您,就是画出的方框,总是一闪一闪的,是怎么回事?
这个很正常的,因为是一帧一帧处理的,每处理一帧就画一次矩形。[/quote] 怎样改可以使当检测到人脸时方框一直保留,不是一闪一闪的
Dream_WHui 2015-06-12
  • 打赏
  • 举报
回复
引用 7 楼 yubangzi 的回复:
[quote=引用 6 楼 Dream_WHui 的回复:] 这是你程序的结果 就是方框啊
你这个是图片吧!我的这个是调用摄像头的,检测出来是方框和圆圈交替的[/quote]
cvEllipseBox( image, track_box, CV_RGB(255,0,0), 3, CV_AA, 0 );//这个是画椭圆的函数
cvRectangle(inputImg,cvPoint(selection[i].x-3,selection[i].y-3),cvPoint(selection[i].x+selection[i].width+2,selection[i].y+selection[i].height+2),CV_RGB(255,0,0),3);//这个是画矩形的函数
你可以尝试将画椭圆的函数 注释掉!
「已注销」 2015-06-12
  • 打赏
  • 举报
回复
引用 6 楼 Dream_WHui 的回复:
这是你程序的结果 就是方框啊
你这个是图片吧!我的这个是调用摄像头的,检测出来是方框和圆圈交替的
Dream_WHui 2015-06-12
  • 打赏
  • 举报
回复
这是你程序的结果 就是方框啊
Dream_WHui 2015-06-12
  • 打赏
  • 举报
回复
引用 4 楼 yubangzi 的回复:
[quote=引用 3 楼 zhao4zhong1 的回复:] 试试注释掉某句,不对再恢复,注释调下一句,……
刚开始学,不太懂,能辛苦您帮忙改一下吗?[/quote] 现在出现的是什么样子?
「已注销」 2015-06-12
  • 打赏
  • 举报
回复
引用 3 楼 zhao4zhong1 的回复:
试试注释掉某句,不对再恢复,注释调下一句,……
刚开始学,不太懂,能辛苦您帮忙改一下吗?
赵4老师 2015-06-12
  • 打赏
  • 举报
回复
试试注释掉某句,不对再恢复,注释调下一句,……
「已注销」 2015-06-12
  • 打赏
  • 举报
回复
引用 1 楼 zhao4zhong1 的回复:
OpenCV自带的例子就是方框,我记得。
想把上面的程序修改一下,只出现方框,怎么改
赵4老师 2015-06-12
  • 打赏
  • 举报
回复
OpenCV自带的例子就是方框,我记得。

24,854

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧