基於opencv的檢測到人臉,便將人臉用骷髏頭代替。
阿新 • • 發佈:2018-12-13
工具:
/*Result window title*/ #define WND_RESULT "result" static CvMemStorage* storage = 0; static CvHaarClassifierCascade* cascade ; const char* cascade_name ; /*skull image*/ IplImage *g_skullImage; /*Tarckbar initial value*/ int g_trackbar_value=5; /*Trackbar total value*/ int g_trackbar_total = 10; /*Alpha blend' alpha*/ double g_alpha = 0; /*Trackba callback fuction*/ void switch_callback(int pos) { cout << "Trackbar event. pos:" << pos << endl; g_alpha = (double)pos / g_trackbar_total; }
void detect_and_draw(IplImage* img) { double scale = 1.2; //Image Preparation IplImage* gray = cvCreateImage(cvSize(img->width, img->height), 8, 1); IplImage* small_img = cvCreateImage( cvSize(cvRound(img->width / scale), cvRound(img->height / scale)), 8, 1); cvCvtColor(img, gray, CV_BGR2GRAY); cvResize(gray, small_img, CV_INTER_LINEAR); cvEqualizeHist(small_img, small_img); //直方圖均衡 //Detect objects if any cvClearMemStorage(storage); double t = (double)cvGetTickCount(); CvSeq* objects = cvHaarDetectObjects(small_img, cascade, storage, 1.1, 2, 0/*CV_HAAR_DO_CANNY_PRUNING*/, cvSize(30, 30)); t = (double)cvGetTickCount() - t; printf("detection time = %gms\n", t / ((double)cvGetTickFrequency()*1000.)); //Loop through found objects and draw boxes around them for (int i = 0; i<(objects ? objects->total : 0); ++i) { CvRect* r = (CvRect*)cvGetSeqElem(objects, i); CvRect r_scale = cvRect(r->x * scale, r->y * scale, r->width * scale, r->height * scale); // 改變骷髏頭影象大小 IplImage * skullResize = cvCreateImage( cvSize(r_scale.width, r_scale.height),g_skullImage->depth, g_skullImage->nChannels); cvResize(g_skullImage, skullResize, CV_INTER_LINEAR); // 將人臉檢測區域用骷髏頭影象代替 cvSetImageROI(img, r_scale); printf("Alpha: %f\t", g_alpha); cvAddWeighted(img, g_alpha, skullResize, 1.0 - g_alpha, 0.0, img); cvResetImageROI(img); cvReleaseImage(&skullResize); } cvShowImage(WND_RESULT, img); cvReleaseImage(&gray); cvReleaseImage(&small_img); }
應用層:
void opencv_4_3::ans_8() { //獲取攝像頭 VideoCapture capture(0); cascade_name = "E:\\opencv\\sources\\data\\haarcascades_cuda\\haarcascade_frontalface_alt2.xml"; cascade = (CvHaarClassifierCascade*)cvLoad(cascade_name, 0, 0, 0); if (!cascade) { cout << "Error:Could not load classifier cascade" << endl; return; } storage = cvCreateMemStorage(0); cvNamedWindow(WND_RESULT, CV_WINDOW_AUTOSIZE); Mat frame; capture >> frame; IplImage * frame_c; frame_c = &IplImage(frame); IplImage *skullImage = cvLoadImage("..//..//skull.jpg"); g_skullImage = cvCreateImage(cvGetSize(skullImage), 8, 3); skullImage->nChannels != 3 ? cvCvtColor(skullImage, g_skullImage, CV_GRAY2BGR) : cvCopy(skullImage, g_skullImage); cvCreateTrackbar("Switch", WND_RESULT, &g_trackbar_value, g_trackbar_total, switch_callback); g_alpha = (double)g_trackbar_value/ g_trackbar_total; char c; while (1) { capture >> frame; frame_c = &IplImage(frame); if (!frame_c) { return ; } detect_and_draw(frame_c); c = cvWaitKey(50); if (c == 27) break; } cvDestroyWindow(WND_RESULT); cvReleaseImage(&frame_c); //cvReleaseCapture(&capture); cvReleaseImage(&skullImage); cvReleaseImage(&g_skullImage); }
碰到的麻煩:
原來我是用cvCreateCameraCapture獲取的攝像頭視訊,結果總是攝像頭燈亮,但是載入不了視訊。
於是參考了博友的這段:
VideoCapture capture(0);
//0或-1表示筆記本內建攝像頭
Mat frame;
while(1)
{
capture >> frame;
imshow("讀取視訊", frame);
char c=cvWaitKey(33);
if(c==27)break;
//等待按鍵ESC
}
後來就是這段:
cascade_name = "E:\\opencv\\sources\\data\\haarcascades_cuda\\haarcascade_frontalface_alt2.xml";
cascade = (CvHaarClassifierCascade*)cvLoad(cascade_name, 0, 0, 0);
原先的路勁是E:\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt2.xml;
那麼(CvHaarClassifierCascade*)cvLoad(cascade_name, 0, 0, 0);就會報異常錯誤;