Opencv3.41 - Object Detection(objdetect module) - Cascade Classifier - C++版本

Here we learn how to use objdetect module to find objects in our images or videos.

Goal
In this tutorial you will learn how to:
Use the cv::CascadeClassifier class to detect objects in a video stream. Particularly, we will use the functions:
cv::CascadeClassifier::load to load a .xml classifier file. It can be either a Haar or a LBP classifer
cv::CascadeClassifier::detectMultiScale to perform the detection.

這裏對需要用到的這兩個函數進行說明:
1 、Functions : cv::CascadeClassifier::load

C/C++: bool cv::CascadeClassifier::load ( const String & filename )

Python: retval = cv.CascadeClassifier.load( filename )
作用 :Loads a classifier from a file.
Parameters :
filename Name of the file from which the classifier is loaded. The file may contain an old HAAR classifier trained by the haartraining application or a new cascade classifier trained by the traincascade application.

2 、Functions : cv::CascadeClassifier::detectMultiScale

C/C++ : void cv::CascadeClassifier::detectMultiScale ( InputArray image,
std::vector< Rect > & objects,
double scaleFactor = 1.1,
int minNeighbors = 3,
int flags = 0,
Size minSize = Size(),
Size maxSize = Size() )

Python : objects = cv.CascadeClassifier.detectMultiScale( image[, scaleFactor[, minNeighbors[, flags[, minSize[, maxSize]]]]] )

作用:Detects objects of different sizes in the input image. The detected objects are returned as a list of rectangles.
Parameters :
image Matrix of the type CV_8U containing an image where objects are detected.
objects Vector of rectangles where each rectangle contains the detected object, the rectangles may be partially outside the original image.
scaleFactor Parameter specifying how much the image size is reduced at each image scale.
minNeighbors Parameter specifying how many neighbors each candidate rectangle should have to retain it.
flags Parameter with the same meaning for an old cascade as in the function cvHaarDetectObjects. It is not used for a new cascade.
minSize Minimum possible object size. Objects smaller than that are ignored.
maxSize Maximum possible object size. Objects larger than that are ignored. If maxSize == minSize model is evaluated on single scale.

Code

#include "opencv2/objdetect.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
#include <vector>

using namespace std;
using namespace cv;

void detectAndDisplay(Mat frame);           //聲明 detectAndDisplay 函數

String face_cascade_name, eyes_cascade_name;
CascadeClassifier face_cascade;             //創造 face_cascade 對象,用於人臉檢測
CascadeClassifier eyes_cascade;             //創造 eyes_cascade 對象,用於眼睛檢測
String window_name = "Capture - Face detection";




int main(int argc, const char** argv)
{
	CommandLineParser parser(argc, argv,
		"{help h||}"
		"{face_cascade|D://opencv/opencv3.41/sources/data/lbpcascades/lbpcascade_frontalface_improved.xml|}"
		"{eyes_cascade|D://opencv/opencv3.41/sources/data/haarcascades/haarcascade_eye.xml|}");

	parser.about("\nThis program demonstrates using the cv::CascadeClassifier class to detect objects (Face + eyes) in a video stream.\n"
		"You can use Haar or LBP features.\n\n");
	parser.printMessage();
	 
	face_cascade_name = parser.get<String>("face_cascade");     //將人臉檢測文件保存到 face_cascade_name
	eyes_cascade_name = parser.get<String>("eyes_cascade");     //將眼睛檢測文件保存到 eyes_cascade_name
	VideoCapture capture;    
	Mat frame;

	//- 1. Load the cascades
	if (!face_cascade.load(face_cascade_name)) {                //如果沒有加載到人臉檢測文件,就報錯
		cerr << "--(!)Error loading face cascade" << endl;
		return -1;
	}                                                           

	if (!eyes_cascade.load(eyes_cascade_name)) {                //如果沒有加載到眼睛檢測文件,就報錯
		cerr << "--(!)Error loading eyes cascade" << endl;
		return -1;
	}

	//- 2. Read the video stream
	capture.open(0);           
	if (!capture.isOpened()) {                                  //如果攝像頭沒有打開,就報錯
		cerr << "--(!)Error opening video capture" << endl;
		return -1;
	}

	while (capture.read(frame)) { 
		if (frame.empty()) {                                    //如果沒有採集到 frame , 就報錯
			cerr << "--(!) No capture frame -- Break !" << endl;
			break;
		}

		//cout << frame.size() << endl;
		//- 3. Apply the classifier to the frame
		detectAndDisplay(frame);                                //detectAndDisplay                     

		if (waitKey(10) == 27)                                  //程序停止條件
			break;
	}
	return 0;
}


void detectAndDisplay(Mat frame)
{
	vector<Rect> faces;
	Mat frame_gray;
	
	
	cvtColor(frame, frame_gray, COLOR_BGR2GRAY);    //將BRG 轉換爲 灰度圖
	equalizeHist(frame_gray, frame_gray);           //直方圖均衡化

	double t = (double)cv::getTickCount();

	//- Detect faces
	face_cascade.detectMultiScale(frame_gray, faces, 1.8, 2, 0 | CASCADE_SCALE_IMAGE, Size(130, 130));

	t = ((double)getTickCount() - t) / getTickFrequency();
	printf("detection time = %g ms\n", t * 1000);


	for (size_t i = 0; i < faces.size(); i++)
	{
		//Point center(faces[i].x + faces[i].width / 2, faces[i].y + faces[i].height / 2);      //人臉中心點座標
		//ellipse(frame, center, Size(faces[i].width / 2, faces[i].height / 2), 0, 0, 360, Scalar(0, 255, 0), 4, 8, 0);
		Rect rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height);
		rectangle(frame, rect, Scalar(0, 255, 0), 4, 8, 0);

		Mat faceROI = frame_gray(faces[i]);        //將檢測出來的人臉保存到 faceROI
		vector<Rect> eyes;
		
		//- In each face, detect eyes
		eyes_cascade.detectMultiScale(faceROI, eyes, 1.3, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));

		for (size_t j = 0; j < eyes.size(); j++) {
			Point eye_center(faces[i].x + eyes[j].x + eyes[j].width / 2, faces[i].y + eyes[j].y + eyes[j].height / 2);
			int radius = cvRound((eyes[j].width + eyes[j].height) * 0.25);
			circle(frame, eye_center, radius, Scalar(0, 0, 255), 4, 8, 0);
		}

	}
	//- Show what you got
	imshow(window_name, frame);

}

Over

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章