#include "cv.h"
#include "highgui.h"
#include <iostream.h>
char filename[100];
char subfilename[100];
void GetSubFileName( char subfilename[100],int i,char filename[100] );
IplImage* GetSubImage( IplImage* src ,CvRect rect)
{
IplImage* subImg=cvCreateImage( cvSize( rect.width,rect.height ),
IPL_DEPTH_8U,
3);
CvScalar s;
for( int row=1;row<rect.height;row++ )
{
for( int col=1;col<rect.width;col++ )
{
s=cvGet2D( src,row+rect.y,col+rect.x );
cvSet2D( subImg,row,col,s );
}
}
return subImg;
}
void OutputLarger( IplImage* img, CvRect face_rect,char savepath[100] )
{
CvPoint mid;
mid.x=face_rect.x+face_rect.width/2;
mid.y=face_rect.y+face_rect.height/3;
CvRect new_rect;
new_rect.x=face_rect.x-int(0.2*face_rect.width/2);//新矩形的x,y坐标往左上移动
if( new_rect.x<1 )
new_rect.x=1;
new_rect.y=face_rect.y-int(0.4*face_rect.height*(double(2)/3));
if( new_rect.y<1 )
new_rect.y=1;
new_rect.width=int(face_rect.width*1.2);
new_rect.height=int( face_rect.height*1.4 );
CvScalar s;
IplImage* subImg=cvCreateImage( cvSize( new_rect.width,new_rect.height ),
IPL_DEPTH_8U,
3);
for( int row=1;row<new_rect.height;row++ )
{
for( int col=1;col<new_rect.width;col++ )
{
s=cvGet2D( img,row+new_rect.y,col+new_rect.x );
cvSet2D( subImg,row,col,s );
}
}
cvSaveImage( savepath,subImg );
}
void GetSubFileName( char subfilename[100],int i,char filename[100] )
{
char tmp[]={'0'+i,'\0'};
memset(subfilename,0,100);
strcpy(subfilename,"sub");
strcat(subfilename,tmp );
strcat(subfilename,filename);
}
CvHaarClassifierCascade* load_object_detector( const char* cascade_path )
{
return (CvHaarClassifierCascade*)cvLoad( cascade_path );//现在分类器都存储在xml文件中,所以用load,再类型转换
}
void detect_and_draw_objects( IplImage* image,
CvHaarClassifierCascade* cascade,
int do_pyramids )
{
IplImage* small_image = image;
CvMemStorage* storage = cvCreateMemStorage(0);//默认大小的存储块是64kb
CvSeq* faces;//OpenCv基础动态数据结构
int i, scale = 1;
if( do_pyramids )//如果声明,则Gaussian金字塔向下采样,把图像变小再做可以提高速度,但是精度不如用原始图像好
{
small_image = cvCreateImage( cvSize(image->width/2,image->height/2),
IPL_DEPTH_8U, 3 );
cvPyrDown( image, small_image, CV_GAUSSIAN_5x5 );//向下采样,输出是原始图像的一半 ,先使用指定滤波器对输入图像进行卷积
//然后通过去除偶数的行与列向下采样图像
scale = 2;
}
else
{
//small_image = cvCreateImage( cvSize(image->width,image->height ),IPL_DEPTH_8U,3 );
small_image=image;
}
faces = cvHaarDetectObjects( small_image, cascade, storage, 1.2, 2,
0/*CV_HAAR_DO_CANNY_PRUNING*/ );
for( i = 0; i < faces->total; i++ )
{
CvRect face_rect = *(CvRect*)cvGetSeqElem( faces, i );//序列,索引构成
/*
绘制简单、指定粗细或者带填充的 矩形
void cvRectangle( CvArr* img, CvPoint pt1, CvPoint pt2, CvScalar color,
int thickness=1, int line_type=8, int shift=0 );
img
图像.
pt1
矩形的一个顶点。
pt2
矩形对角线上的另一个顶点
color
线条颜色 (RGB) 或亮度(灰度图像 )(grayscale image)。
thickness
组成矩形的线条的粗细程度。取负值时(如 CV_FILLED)函数绘制填充了色彩的矩形。
line_type
线条的类型。见cvLine的描述
shift
坐标点的小数点位数。
函数 cvRectangle 通过对角线上的两个顶点绘制矩形。
*/
//去除那些重叠的区域 ,判断是否画出来
bool canDraw=true;
for( int j=0;j<faces->total;j++ )
{
if( i==j ) //除去自己的
continue;
CvRect compareTo=*(CvRect*)cvGetSeqElem( faces,j );//取出那些其他的脸矩形区域
if( face_rect.x > compareTo.x && face_rect.y > compareTo.y
&& face_rect.x+face_rect.width < compareTo.x+compareTo.width
&& face_rect.y+face_rect.height < compareTo.y+compareTo.height )
{
canDraw = false;//被包含,不draw出来
break;
}
}
if( true==canDraw )
{
//取出更大的子图
GetSubFileName( subfilename,i,filename );
OutputLarger(image,face_rect,subfilename);
// 框出子图像
cvRectangle( image, cvPoint(face_rect.x*scale,face_rect.y*scale),
cvPoint((face_rect.x+face_rect.width)*scale,
(face_rect.y+face_rect.height)*scale),
CV_RGB(255,0,0), 1 );
//end of 框出
//保存子图像
IplImage* subImg=cvCreateImage( cvSize( face_rect.width,face_rect.height ),
IPL_DEPTH_8U,
3);
CvScalar s;
for( int row=1;row<face_rect.height;row++ )
{
for( int col=1;col<face_rect.width;col++ )
{
s=cvGet2D( image,row+face_rect.y,col+face_rect.x );
cvSet2D( subImg,row,col,s );
}
}
//GetSubFileName(subfilename,i,filename);
//cvSaveImage( subfilename,subImg );
//end of 保存子图像
}
}// for all faces detected
if( small_image != image )
cvReleaseImage( &small_image );
cvReleaseMemStorage( &storage );
}
int main()
{
IplImage* image;
int flag=0;
cout<<"文件名: 0表示原始图,1表示下采样"<<endl;
while(cin>>filename>>flag && strcmp(filename,"exit")!=0 )
{
if( image = cvLoadImage( filename, 1 ) )
{
//时间测试,开始时间
double time=(double)cvGetTickCount();
CvHaarClassifierCascade* cascade = load_object_detector("haarcascade_frontalface_alt.xml");
detect_and_draw_objects( image, cascade, flag );
//结束时间
time=cvGetTickCount()-time;
cout<<"time:::"<<time<<endl;
cvNamedWindow( "test", /*0*/ CV_WINDOW_AUTOSIZE);//指定autosize时,以原始尺寸显示
cvShowImage( "test", image );
cvSaveImage( "result.jpg",image );
cvWaitKey(0);
cvReleaseHaarClassifierCascade( &cascade );
cvReleaseImage( &image );
}
}
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
前往页