实时视频中面具覆盖的实现

Overview

OpenCV By Example第七章中的一个例子,识别算法是直接加载的给定的级联文件(书中的代码给提供了一份,OpenCV官方应该也能找的到)。检测到人脸之后就是面具的覆盖,这个过程类似之前的logo添加,就是logo(此处是facemask)和背景(此处是人脸ROI)的对称的操作,之后将两者直接合并即可。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

#include <iostream>
#include <opencv/cv.h>
#include <opencv/cv.hpp>
using namespace std;
using namespace cv;

int main() {
string faceCascadeName = "/home/shensir/Documents/MyPrograming/Cpp/books/CV/2-ing/9781785280948_Code/B04283_07_code/code/cascadeFiles/haarcascade_frontalface_alt.xml";
CascadeClassifier faceCascade;

if( !faceCascade.load(faceCascadeName) )
{
cerr << "Error loading cascade file. Exiting!" << endl;
return -1;
}

Mat faceMask = imread("/home/shensir/Documents/MyPrograming/Cpp/Clions/data/mask2.jpeg");

if ( !faceMask.data )
{
cerr << "Error loading mask image. Exiting!" << endl;
}

// Current frame
Mat frame, frameGray;
Mat frameROI, faceMaskSmall;
Mat grayMaskSmall, grayMaskSmallThresh, grayMaskSmallThreshInv;
Mat maskedFace, maskedFrame;

char ch;

// Create the capture object
// 0 -> input arg that specifies it should take the input from the webcam
VideoCapture cap(0);

// If you cannot open the webcam, stop the execution!
if( !cap.isOpened() )
return -1;

//create GUI windows
namedWindow("Frame");

// Scaling factor to resize the input frames from the webcam
float scalingFactor = 0.75;

vector<Rect> faces;

// Iterate until the user presses the Esc key
while(true)
{
// Capture the current frame
cap >> frame;

// Resize the frame
resize(frame, frame, Size(), scalingFactor, scalingFactor, INTER_AREA);

// Convert to grayscale
cvtColor(frame, frameGray, CV_BGR2GRAY);

// Equalize the histogram
equalizeHist(frameGray, frameGray);

// Detect faces
faceCascade.detectMultiScale(frameGray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );

// Draw green rectangle around the face
for(int i = 0; i < faces.size(); i++)
{
Rect faceRect(faces[i].x, faces[i].y, faces[i].width, faces[i].height);
rectangle(frame, faceRect, Scalar(0,255,0),2);

// Custom parameters to make the mask fit your face. You may have to play around with them to make sure it works.
int x = faces[i].x - int(0.1*faces[i].width);
int y = faces[i].y - int(0.0*faces[i].height);
int w = int(1.3 * faces[i].width);
int h = int(1.3 * faces[i].height);

// Extract region of interest (ROI) covering your face
frameROI = frame(Rect(x,y,w,h));

// Resize the face mask image based on the dimensions of the above ROI
resize(faceMask, faceMaskSmall, Size(w,h));

// Convert the above image to grayscale
// 灰度化
cvtColor(faceMaskSmall, grayMaskSmall, CV_BGR2GRAY);

// Threshold the above image to isolate the pixels associated only with the face mask
// 二值化,grayMaskSmallThresh在面具主体为白,其余为黑色
threshold(grayMaskSmall, grayMaskSmallThresh, 230, 255, CV_THRESH_BINARY_INV);

// Create mask by inverting the above image (because we don't want the background to affect the overlay)
// grayMaskSmallThreshInv在面具主体为黑色,其余为白色
bitwise_not(grayMaskSmallThresh, grayMaskSmallThreshInv);

// Use bitwise "AND" operator to extract precise boundary of face mask
// 扣取面具主体,周围为黑色
bitwise_and(faceMaskSmall, faceMaskSmall, maskedFace, grayMaskSmallThresh);
imshow("maskedFace", maskedFace);

// Use bitwise "AND" operator to overlay face mask
// 挖去ROI中的脸部图像,变为黑色,其余保持不变
bitwise_and(frameROI, frameROI, maskedFrame, grayMaskSmallThreshInv);
imshow("maskedFrame", maskedFrame);

// Add the above masked images and place it in the original frame ROI to create the final image
// 面具部分覆盖脸部主体,其余部分合成后保持不变
add(maskedFace, maskedFrame, frame(Rect(x,y,w,h)));
}

// Show the current frame
imshow("Frame", frame);

// Get the keyboard input and check if it's 'Esc'
// 27 -> ASCII value of 'Esc' key
ch = waitKey( 30 );
if (ch == 27) {
break;
}
}

// Release the video capture object
cap.release();

// Close all windows
destroyAllWindows();

return 0;
}


输出:

本文标题:实时视频中面具覆盖的实现

文章作者:不秩稚童

发布时间:2017年05月18日 - 23:44:17

最后更新:2017年05月18日 - 23:54:06

原始链接:http://datahonor.com/2017/05/18/实时视频中面具覆盖的实现/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

击蒙御寇