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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值