Opencv performs face recognition on video-use the videoCapture class

Preface

Using the libfacedetection library, we can perform face recognition on an image, then can we recognize multiple images, that is the next thing to say, face recognition on a video.

1. Configuration and basic introduction of libfacedetection:

We gave a detailed introduction in this article: https://blog.csdn.net/ivan_9/article/details/113336452

Two, VideoCapture class:

1. Constructor type:

2.1.1、VideoCapture();

Introduction: VideoCapture(); is the default constructor of the VideoCapture class;

2.1.2、VideoCapture(const String& filename, int apiPreference = CAP_ANY);

Brief analysis: Open the video file or capture device or IP video stream to use the API preferences for video capture.
filename This parameter can be:

  • The name of the video file (for example 视频.avi)
  • Image sequence (for example "img\uu02d.jpg", it will read "img\u 00.jpg, img\u 01.jpg, img\u 02.jpg,...")
  • URL of the video stream (for example 协议://主机:端口/脚本名称?脚本|参数| auth)
  • GStreamer pipeline string in gst startup tool format, in case GStreamer is used as a backend, each video stream or IP camera feed has its own URL scheme
  • The capture API backend to be used is preferred. Can be used to force specific readers

2.1.3、VideoCapture(int index, int apiPreference = CAP_ANY);

Brief analysis: turn on the camera for video capture

  • The parameter index id of the video capture device to be opened.
  • To open the default camera with the default backend, just pass 0. For other external cameras or other cameras, just pass 1.
  • apippreference preferred capture API backend to be used. Can be used to force specific readers
  • If there are multiple implementations available: eg cv::CAP_DSHOW or cv::CAP_MSMF or cv::CAP_V4L.

2. The specific definition of the constructor:

class CV_EXPORTS_W VideoCapture{
    
    
public:
    CV_WRAP VideoCapture();
    CV_WRAP explicit VideoCapture(const String& filename, int apiPreference = CAP_ANY)
    CV_WRAP explicit VideoCapture(int index, int apiPreference = CAP_ANY);
}

3. Functions of the VideoCapture class:

1, open(); function

Introduction: Open the video file, capture device or IP video stream used for video capture.

3.1.1. The first use:

VideoCapture capture;
captrue.open("有趣的灵魂.mp4");//可以是avi,可以是mp4格式的视频文件

3.1.2. The second use:

VideoCapture capture("有趣的灵魂.mp4");//利用构造函数直接获取

2. isOpened() function:

Brief analysis: If the video capture has been initialized, return true to judge whether the reading is successful

if (cap.isOpened()) {
    
    
	cout << "恭喜你打开视频文件了!" << endl;
}
else {
    
    
	cout << "对不起你没打开视频文件!" << endl;
	return -1;
}

3. The release() function:

Brief analysis: closing the video file or capture device corresponds to the open() function, it is best not to miss the release() function

VideoCapture capture;
captrue.open("有趣的灵魂.mp4");
cap.release();

4. grab() function and retrieve() function:

Brief analysis: grab() function gets the next frame from the video file or camera, and returns true (successful example).

This function calls VideoCapture::grab() for each camera, and then calls the slower method VideoCapture::retrieve() to decode and get frames from each camera. This method eliminates the overhead of demosaicing or motion jpeg decompression, and restores the frames from different cameras to be closer in time.

Analysis: The retrieve() function decodes and returns the captured video frame.

This method decodes and returns the frame just grabbed. If no frame is captured (the camera is disconnected, or there are no more frames in the video file), the method returns false. The function returns an empty image (use %cv::Mat, use Mat::empty() to test it)

//这两个函数一般一起使用
cap.grab();
cap.retrieve(src);//src是每帧的图像对象

5. The read() function:

Brief analysis: get, decode and return to the next video frame

cap.read(src);

6. Set() function:

Brief analysis: set the properties in VideoCapture

cap.set(3, 480)
//把视频流的帧(图片)的高度调成480帧的,宽度为5

6. get() function:

Brief analysis: return the specified VideoCapture property

cap.get(0)
//视频文件的当前位置(播放)以毫秒为单位

Four, video face recognition

Code block:

//视频的人脸识别
#include <iostream>
#include <opencv2/opencv.hpp>
#include <facedetectcnn.h>
#include <stdlib.h>
#define DETECT_BUFFER_SIZE 0x20000 //定义缓冲区大小
#define FACEDETECTION_EXPORT

using namespace std;
using namespace cv;
int main() {
    
    
	Mat src, dst, image;
	VideoCapture cap;
	int count = 1;
	cap.open("D:\\Myfile\\素材照片\\视频图像截取\\视频1.avi");
	if (cap.isOpened()) {
    
    
		//pBuffer用来检测人脸
		unsigned char* pBuffer = new unsigned char[DETECT_BUFFER_SIZE];  //multiple threads
		//是多线程时,要分配内存空间
		if (!pBuffer) {
    
     //如果无法分配内存,就返回could not alloc buffer!
			cout << "could not alloc buffer!" << endl;
			return 0;
		}
		system("cls");  //清屏
		while (true)
		{
    
    
			cap >> src;// cap.read(src);
			if (!src.data) {
    
    	//若不存在就返回 could not load your image!
				cout << "could not load your image!" << endl;
				return 0;
			}

			dst = src.clone();	//将src原图像复制给dst
			TickMeter myClock;	//计时器
			myClock.start();
			int* pResults = NULL; //用来检测人脸
			pResults = facedetect_cnn(pBuffer, (unsigned char*)(src.ptr(0)), src.cols, src.rows, src.step);
			//利用facedetect_cnn函数来获取人脸,用于存储人脸检测结果的缓冲存储器!其大小必须为0x20000字节
			//facedetect_cnn函数识别的图像必须为BGR三通道的图像,而非rgb图像
			myClock.stop();
			cout << "这帧图像的耗费时长:" << myClock.getTimeSec() << "s" ;	//输出检测人脸耗费时长
			for (int i = 0; i < (pResults ? (*pResults) : 0); i++) {
    
    
				//如果pResult为NULL,即pResult没有检测到人脸,就返回0,for循环结束
				short* p = ((short*)(pResults + 1)) + (142 * i);
				//p指针用来指向
				int confidence = p[0];
				if (confidence < 88) {
    
    
					cout << "------这帧图像没有人脸!!!\n\n";
					continue;
				}
				else cout << "--这帧图像有人脸!!!\n";
				int x = p[1];
				int y = p[2];
				int w = p[3];
				int h = p[4];
				//显示脸的分数。其范围为[0-100]
				char sScore[256];
				snprintf(sScore, 256, "%d", confidence);
				/*从给定位置加载数据,转换为字符串等价版本,并将结果写入各种池。
					1) 写结果到 stdout 。2) 写结果到文件流 stream 。3) 写结果到字符串 buffer 。
					4) 写结果到字符串 buffer 。至多写 buf_size - 1 个字符。产生的字符串会以空字符终止,除非 buf_size 为零。
					若buf_size为零,则不写入任何内容,且buffer可以是空指针,然而依旧计算返回值(会写入的字符数,不包含空终止符)并返回。
					若调用 sprintf 或 snprintf 导致在重叠的对象间发生复制,则行为未定义。
					(例如 sprintf(buf, "%s text", buf); )*/
				putText(dst, sScore, Point(x, y - 3), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 1);
				//计算文本字符串的宽度和高度
				//把脸用矩形画出来
				rectangle(dst, Rect(x, y, w, h), Scalar(0, 255, 0), 2);
				image = dst(Rect(x, y, w, h));
				//画五个不同颜色的面部标志
				circle(dst, Point(p[5], p[5 + 1]), 1, Scalar(255, 0, 0), 2);
				circle(dst, Point(p[5 + 2], p[5 + 3]), 1, Scalar(0, 0, 255), 2);
				circle(dst, Point(p[5 + 4], p[5 + 5]), 1, Scalar(0, 255, 0), 2);
				circle(dst, Point(p[5 + 6], p[5 + 7]), 1, Scalar(255, 0, 255), 2);
				circle(dst, Point(p[5 + 8], p[5 + 9]), 1, Scalar(0, 255, 255), 2);
				//circle()绘制简单或粗椭圆弧或填充椭圆扇区。
				/*
				Point类的实例可以与C结构、CvPoint和CvPoint2D32f互换。
				还有一个cast操作符将点坐标转换为指定的类型。
				从浮点坐标到整数坐标的转换是通过舍入完成的。
				通常,转换对每个坐标都使用此操作。
				*/
				printf("face %d: confidence=%d, [%d, %d, %d, %d] (%d,%d) (%d,%d) (%d,%d) (%d,%d) (%d,%d)\n\n",
					i, confidence, x, y, w, h, p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[14]);
				namedWindow("output_detect_image", WINDOW_AUTOSIZE);
				imshow("output_detect_image", dst);	//输出识别后的图像
				string str = "D:\\Myfile\\素材照片\\视频图像截取\\" + to_string(count) + ".jpg"; //制定保存的命名规则
				imwrite(str, image); //将人脸截取出来并保存起来

				count++;

				waitKey(4000); //让每一张图片停留4s
			}
		}
		//release the buffer
		delete pBuffer; 
	}
	else cout << "could not load video!" << endl;
	cap.release();
	return 0;
}

operation result:
Insert picture description here
Insert picture description here

to sum up

This article briefly describes the use of the videoCapture class, and performs video facial recognition

Reference source

https://github.com/ShiqiYu/libfacedetection#cnn-based-face-detection-on-windows

If you have any questions, please leave a message!
If there is an error, please advise!

Guess you like

Origin blog.csdn.net/ivan_9/article/details/113803831