这道题是利用OpenCV例子程序里自带的人脸检测程序,做点图像的复制操作以及alpha融合。
说明:人脸检测的程序我参照了网上现有的例子程序,没有用我用的OpenCV版本(2.4.5)的facedetect.c,人脸检测部分是一个月前写的程序,这次做了点改动,以前的部分注释了起来。
代码:
1 #include <opencv/cv.h> 2 #include <opencv/highgui.h> 3 #include <opencv_libs.h> 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <assert.h> 9 #include <math.h> 10 #include <float.h> 11 #include <limits.h> 12 #include <time.h> 13 #include <ctype.h> 14 15 /* 16 *《学习OpenCV》第四章第八题 17 * 完成时间:3:43 10/5 星期六 2013 18 * 作者:qdsclove@163.com 19 */ 20 21 22 /* Result window title */ 23 #define WND_RESULT "result" 24 25 static CvMemStorage* storage = 0; 26 static CvHaarClassifierCascade* cascade = 0; 27 28 void detect_and_draw( IplImage* image ); 29 30 const char* cascade_name = 31 "haarcascade_frontalface_alt.xml"; 32 33 /* Skull image */ 34 IplImage* g_skullImage; 35 36 /* Trackbar initial value */ 37 int g_trackbar_value = 5; 38 /* Tackbar total values */ 39 int g_trackbar_total = 10; 40 41 /* Alpha blend's alpha */ 42 double g_alpha = 0; 43 44 /* Trackbar callback function */ 45 void switch_callback(int pos) 46 { 47 printf("Trackbar event. pos: %d ", pos); 48 g_alpha = (double)pos / g_trackbar_total; 49 } 50 51 int main( ) 52 { 53 CvCapture* capture = cvCreateCameraCapture(0); 54 if(!capture) 55 { 56 printf("Camera error. "); 57 return -1; 58 } 59 cascade_name = "haarcascade_frontalface_alt2.xml"; 60 cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 ); 61 62 if( !cascade ) 63 { 64 printf( "ERROR: Could not load classifier cascade " ); 65 return -1; 66 } 67 68 storage = cvCreateMemStorage(0); 69 cvNamedWindow( WND_RESULT, 1 ); 70 71 IplImage* frame = cvQueryFrame(capture); 72 if(!frame) 73 { 74 return -1; 75 } 76 77 // Load skull image 78 IplImage* skullImage = cvLoadImage("skull.jpg", CV_LOAD_IMAGE_UNCHANGED); 79 if(!skullImage) 80 { 81 printf("ERROR: Can't load skull image. "); 82 return -1; 83 } 84 g_skullImage = cvCreateImage(cvGetSize(skullImage), skullImage->depth, 3); 85 if(skullImage->nChannels != 3) 86 { 87 cvCvtColor(skullImage, g_skullImage, CV_GRAY2BGR); 88 } 89 else 90 { 91 cvCopy(skullImage, g_skullImage); 92 } 93 94 // Create trackbar 95 cvCreateTrackbar("Switch", WND_RESULT, &g_trackbar_value, 96 g_trackbar_total, switch_callback ); 97 // Initialize Alpha-Blend's alpha 98 g_alpha = (double)g_trackbar_value / g_trackbar_total; 99 100 char c; 101 while( 1 ) 102 { 103 frame = cvQueryFrame(capture); 104 if(!frame) 105 { 106 return -1; 107 } 108 109 detect_and_draw( frame ); 110 111 c = cvWaitKey(50); 112 if(c == 27) 113 { 114 break; 115 } 116 } 117 118 cvDestroyWindow(WND_RESULT); 119 cvReleaseImage(&frame); 120 cvReleaseCapture(&capture); 121 cvReleaseImage(&skullImage); 122 cvReleaseImage(&g_skullImage); 123 124 return 0; 125 } 126 127 128 void detect_and_draw(IplImage* img ) 129 { 130 double scale=1.2; 131 static CvScalar colors[] = { 132 {{0,0,255}},{{0,128,255}},{{0,255,255}},{{0,255,0}}, 133 {{255,128,0}},{{255,255,0}},{{255,0,0}},{{255,0,255}} 134 };//Just some pretty colors to draw with 135 136 //Image Preparation 137 // 138 IplImage* gray = cvCreateImage(cvSize(img->width,img->height),8,1); 139 IplImage* small_img=cvCreateImage(cvSize(cvRound(img->width/scale),cvRound(img->height/scale)),8,1); 140 cvCvtColor(img,gray, CV_BGR2GRAY); 141 cvResize(gray, small_img, CV_INTER_LINEAR); 142 143 cvEqualizeHist(small_img,small_img); //直方图均衡 144 145 //Detect objects if any 146 // 147 cvClearMemStorage(storage); 148 double t = (double)cvGetTickCount(); 149 CvSeq* objects = cvHaarDetectObjects(small_img, 150 cascade, 151 storage, 152 1.1, 153 2, 154 0/*CV_HAAR_DO_CANNY_PRUNING*/, 155 cvSize(30,30)); 156 157 t = (double)cvGetTickCount() - t; 158 printf( "detection time = %gms ", t/((double)cvGetTickFrequency()*1000.) ); 159 160 //Loop through found objects and draw boxes around them 161 for(int i=0;i<(objects? objects->total:0);++i) 162 { 163 CvRect* r=(CvRect*)cvGetSeqElem(objects,i); 164 165 CvRect r_scale = cvRect( r->x * scale, r->y * scale, r->width * scale, r->height * scale ); 166 // 改变骷髅头图像大小 167 IplImage * skullResize = cvCreateImage( cvSize(r_scale.width, r_scale.height), 168 g_skullImage->depth, g_skullImage->nChannels ); 169 cvResize(g_skullImage, skullResize, CV_INTER_LINEAR); 170 171 // 将人脸检测区域用骷髅头图像代替 172 cvSetImageROI(img, r_scale); 173 // b -- Alpha blend 174 printf("Alpha: %f ", g_alpha); 175 cvAddWeighted( img, g_alpha, skullResize, 1.0 - g_alpha, 0.0, img); 176 /* This is a part 177 cvCopy(skullResize, img); */ 178 cvResetImageROI(img); 179 cvReleaseImage(&skullResize); 180 181 // cvRectangle(img, cvPoint(r->x*scale,r->y*scale), cvPoint((r->x+r->width)*scale,(r->y+r->height)*scale), colors[i%8]); 182 } 183 /* for( int i = 0; i < (objects? objects->total : 0); i++ ) 184 { 185 CvRect* r = (CvRect*)cvGetSeqElem( objects, i ); 186 CvPoint center; 187 int radius; 188 center.x = cvRound((r->x + r->width*0.5)*scale); 189 center.y = cvRound((r->y + r->height*0.5)*scale); 190 radius = cvRound((r->width + r->height)*0.25*scale); 191 cvCircle( img, center, radius, colors[i%8], 3, 8, 0 ); 192 } */ 193 194 cvShowImage( WND_RESULT, img ); 195 cvReleaseImage(&gray); 196 cvReleaseImage(&small_img); 197 }
运行结果(此时的alpha为0.2):