API說明:
1 cv::CascadeClassifier::detectMultiScale(InputArray image,//輸入灰度圖像 2 CV_OUT std::vector<Rect>& objects,//返回目標的外接矩形 3 double scaleFactor = 1.1,//檢測的尺度跳變量,這個值越大,某些尺寸的對象無法被檢測,但檢測更快 4 int minNeighbors = 3,//有多少個重疊的檢測標記才被認為有小 5 int flags = 0, //新版本中沒用 6 Size minSize = Size(),//目標的最小尺寸 7 Size maxSize = Size()//目標的最大尺寸,可以排除尺寸不合理的對象 8 );
利用opencv自帶的數據進行人臉檢測:
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace cv; 5 using namespace std; 6 7 String fileName = "D:/opencv3.1/opencv/build/etc/haarcascades/haarcascade_frontalface_alt.xml";//設置文件路徑 8 CascadeClassifier face_classifier;//創建分類器 9 10 int main(int argc, char** argv) { 11 if (!face_classifier.load(fileName)) {//加載分類數據 12 printf("could not load face feature data...\n"); 13 return -1; 14 } 15 16 Mat src = imread("D:/vcprojects/images/test.png"); 17 if (src.empty()) { 18 printf("could not load image...\n"); 19 return -1; 20 } 21 imshow("input image", src); 22 Mat gray; 23 cvtColor(src, gray, COLOR_BGR2GRAY);//轉成灰度圖 24 equalizeHist(gray, gray);//直方圖均衡化,提高對比度 25 26 vector<Rect> faces; 27 face_classifier.detectMultiScale(gray, faces, 1.2, 3, 0, Size(24, 24));//在多尺度上檢測 28 for (size_t t = 0; t < faces.size(); t++) { 29 rectangle(src, faces[static_cast<int>(t)], Scalar(0, 0, 255), 2, 8, 0); 30 } 31 32 imshow("detect faces", src); 33 waitKey(0); 34 return 0; 35 }
進階:人眼檢測
1 #include<opencv2/opencv.hpp> 2 #include<iostream> 3 4 using namespace cv; 5 using namespace std; 6 7 CascadeClassifier face_cascader; 8 CascadeClassifier eye_cascader; 9 String facefile = "D:/opencv3.1/opencv/build/etc/haarcascades/haarcascade_frontalface_alt.xml"; 10 String eyefile = "D:/opencv3.1/opencv/build/etc/haarcascades/haarcascade_eye.xml"; 11 12 int main(int argc, char** argv) { 13 if (!face_cascader.load(facefile)) { 14 printf("could not load face feature data...\n"); 15 return -1; 16 } 17 if (!eye_cascader.load(eyefile)) { 18 printf("could not load eye feature data...\n"); 19 return -1; 20 } 21 namedWindow("camera-demo", CV_WINDOW_AUTOSIZE); 22 VideoCapture capture(0); 23 Mat frame; 24 Mat gray; 25 vector<Rect> faces; 26 vector<Rect> eyes; 27 while (capture.read(frame)) { 28 cvtColor(frame, gray, COLOR_BGR2GRAY); 29 equalizeHist(gray, gray); 30 face_cascader.detectMultiScale(gray, faces, 1.2, 3, 0, Size(30, 30)); 31 32 //眼睛一定在人臉范圍內,通過截取ROI,縮小檢測范圍提高檢測的准確度和速度 33 for (size_t t = 0; t < faces.size(); t++) { 34 Rect roi; 35 roi.x = faces[static_cast<int>(t)].x; 36 roi.y = faces[static_cast<int>(t)].y; 37 roi.width = faces[static_cast<int>(t)].width; 38 roi.height = faces[static_cast<int>(t)].height / 2; 39 Mat faceROI = frame(roi);//截取眼睛ROI,在臉的上半部分 40 eye_cascader.detectMultiScale(faceROI, eyes, 1.2, 3, 0, Size(20, 20)); 41 for (size_t k = 0; k < eyes.size(); k++) { 42 Rect rect; 43 rect.x = faces[static_cast<int>(t)].x + eyes[k].x; 44 rect.y = faces[static_cast<int>(t)].y + eyes[k].y; 45 rect.width = eyes[k].width; 46 rect.height = eyes[k].height; 47 rectangle(frame, rect, Scalar(0, 255, 0), 2, 8, 0);//坐標變換得到眼睛真正的坐標 48 } 49 rectangle(frame, faces[static_cast<int>(t)], Scalar(0, 0, 255), 2, 8, 0); 50 } 51 imshow("camera-demo", frame); 52 char c = waitKey(30); 53 if (c == 27) { 54 break; 55 } 56 } 57 waitKey(0); 58 return 0; 59 }
級聯分類器+模板匹配提高檢測的穩定性,實現眼睛的追蹤:
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace cv; 5 using namespace std; 6 7 String facefile = "D:/opencv3.1/opencv/build/etc/haarcascades/haarcascade_frontalface_alt.xml";//人臉數據 8 String lefteyefile = "D:/opencv3.1/opencv/build/etc/haarcascades/haarcascade_eye.xml";//左眼數據 9 String righteyefile = "D:/opencv3.1/opencv/build/etc/haarcascades/haarcascade_eye.xml";//右眼數據 10 CascadeClassifier face_detector; 11 CascadeClassifier leftyeye_detector; 12 CascadeClassifier righteye_detector; 13 14 Rect leftEye, rightEye; 15 //Mat& im:ROI區域的圖片 16 //Mat& tpl:模板圖片 17 //Rect& rect:輸入原來目標的外接矩形,返回目標的新外接矩形 18 void trackEye(Mat& im, Mat& tpl, Rect& rect) { 19 Mat result; 20 int result_cols = im.cols - tpl.cols + 1; 21 int result_rows = im.rows - tpl.rows + 1; 22 23 // 模板匹配 24 result.create(result_rows, result_cols, CV_32FC1); 25 matchTemplate(im, tpl, result, TM_CCORR_NORMED); 26 27 // 尋找位置 28 double minval, maxval; 29 Point minloc, maxloc; 30 minMaxLoc(result, &minval, &maxval, &minloc, &maxloc); 31 if (maxval > 0.75) { 32 rect.x = rect.x + maxloc.x;//從ROI中的坐標變換為原圖的坐標 33 rect.y = rect.y + maxloc.y; 34 } 35 else { 36 rect.x = rect.y = rect.width = rect.height = 0; 37 } 38 } 39 40 int main(int argc, char** argv) { 41 //加載特征數據 42 if (!face_detector.load(facefile)) { 43 printf("could not load data file...\n"); 44 return -1; 45 } 46 if (!leftyeye_detector.load(lefteyefile)) { 47 printf("could not load data file...\n"); 48 return -1; 49 } 50 if (!righteye_detector.load(righteyefile)) { 51 printf("could not load data file...\n"); 52 return -1; 53 } 54 55 Mat frame; 56 VideoCapture capture(0); 57 namedWindow("demo-win", CV_WINDOW_AUTOSIZE); 58 59 Mat gray; 60 vector<Rect> faces; 61 vector<Rect> eyes; 62 Mat lefttpl, righttpl; // 模板 63 while (capture.read(frame)) { 64 flip(frame, frame, 1); 65 cvtColor(frame, gray, COLOR_BGR2GRAY); 66 equalizeHist(gray, gray); 67 face_detector.detectMultiScale(gray, faces, 1.1, 3, 0, Size(30, 30));//檢測人臉 68 for (size_t t = 0; t < faces.size(); t++) { 69 rectangle(frame, faces[t], Scalar(255, 0, 0), 2, 8, 0); 70 71 // 計算 offset ROI 72 int offsety = faces[t].height / 4; 73 int offsetx = faces[t].width / 8; 74 int eyeheight = faces[t].height / 2 - offsety; 75 int eyewidth = faces[t].width / 2 - offsetx; 76 77 // 截取左眼區域 78 Rect leftRect; 79 leftRect.x = faces[t].x + offsetx; 80 leftRect.y = faces[t].y + offsety; 81 leftRect.width = eyewidth; 82 leftRect.height = eyeheight; 83 Mat leftRoi = gray(leftRect); 84 85 // 檢測左眼 86 leftyeye_detector.detectMultiScale(leftRoi, eyes, 1.1, 1, 0, Size(20, 20)); 87 if (lefttpl.empty()) { 88 if (eyes.size()) { 89 leftRect = eyes[0] + Point(leftRect.x, leftRect.y); 90 lefttpl = gray(leftRect); 91 rectangle(frame, leftRect, Scalar(0, 0, 255), 2, 8, 0); 92 } 93 } 94 else { 95 // 跟蹤, 基於模板匹配 96 leftEye.x = leftRect.x; 97 leftEye.y = leftRect.y; 98 trackEye(leftRoi, lefttpl, leftEye); 99 if (leftEye.x > 0 && leftEye.y > 0) { 100 leftEye.width = lefttpl.cols; 101 leftEye.height = lefttpl.rows; 102 rectangle(frame, leftEye, Scalar(0, 0, 255), 2, 8, 0); 103 } 104 } 105 106 // 截取右眼區域 107 Rect rightRect; 108 rightRect.x = faces[t].x + faces[t].width / 2; 109 rightRect.y = faces[t].y + offsety; 110 rightRect.width = eyewidth; 111 rightRect.height = eyeheight; 112 Mat rightRoi = gray(rightRect); 113 114 // 檢測右眼 115 righteye_detector.detectMultiScale(rightRoi, eyes, 1.1, 1, 0, Size(20, 20)); 116 if (righttpl.empty()) { 117 if (eyes.size()) { 118 rightRect = eyes[0] + Point(rightRect.x, rightRect.y); 119 righttpl = gray(rightRect); 120 rectangle(frame, rightRect, Scalar(0, 255, 255), 2, 8, 0); 121 } 122 } 123 else { 124 // 跟蹤, 基於模板匹配 125 rightEye.x = rightRect.x; 126 rightEye.y = rightRect.y; 127 trackEye(rightRoi, righttpl, rightEye); 128 if (rightEye.x > 0 && rightEye.y > 0) { 129 rightEye.width = righttpl.cols; 130 rightEye.height = righttpl.rows; 131 rectangle(frame, rightEye, Scalar(0, 255, 255), 2, 8, 0); 132 } 133 } 134 } 135 imshow("demo-win", frame); 136 char c = waitKey(100); 137 if (c == 27) { // ESC 138 break; 139 } 140 } 141 142 // release resource 143 capture.release(); 144 waitKey(0); 145 return 0; 146 }
自定義級聯分類器的訓練和使用:待續
命令行參數:
-
-vec <vec_file_name>
輸出文件,內含用於訓練的正樣本。
-
-img <image_file_name>
輸入圖像文件名(例如一個公司的標志)。
-
-bg <background_file_name>
背景圖像的描述文件,文件中包含一系列的圖像文件名,這些圖像將被隨機選作物體的背景。
-
-num <number_of_samples>
生成的正樣本的數目。
-
-bgcolor <background_color>
背景顏色(目前為灰度圖);背景顏色表示透明顏色。因為圖像壓縮可造成顏色偏差,顏色的容差可以由 -bgthresh 指定。所有處於 bgcolor-bgthresh 和 bgcolor+bgthresh 之間的像素都被設置為透明像素。
-
-bgthresh <background_color_threshold>
-
-inv
如果指定該標志,前景圖像的顏色將翻轉。
-
-randinv
如果指定該標志,顏色將隨機地翻轉。
-
-maxidev <max_intensity_deviation>
前景樣本里像素的亮度梯度的最大值。
-
-maxxangle <max_x_rotation_angle>
X軸最大旋轉角度,必須以弧度為單位。
-
-maxyangle <max_y_rotation_angle>
Y軸最大旋轉角度,必須以弧度為單位。
-
-maxzangle <max_z_rotation_angle>
Z軸最大旋轉角度,必須以弧度為單位。
-
-show
很有用的調試選項。如果指定該選項,每個樣本都將被顯示。如果按下 Esc 鍵,程序將繼續創建樣本但不再顯示。
-
-w <sample_width>
輸出樣本的寬度(以像素為單位)。
-
-h <sample_height>
輸出樣本的高度(以像素為單位)。