学习记录
记录人脸识别过程
环境
- OpenCV 4.3.0
- 树莓派4B(在Windows系统下也可以)
功能
默认状态下为人脸检测,可以进行人脸训练和识别
代码
/* > File Name: main.cpp > Author: admin > Mail: > Created Time: Fri 24 Apr 2020 09:46:00 CST > Modified Time:2020年07月01日 星期三 15时13分11秒 > Note: No */ #include
#include
#include
#include
#include
#include
using namespace std; // OpenCV includes #include "opencv2/core.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/highgui.hpp" #include "opencv2/ml.hpp" #include "opencv2/objdetect/objdetect.hpp" #include "opencv2/face.hpp" using namespace cv; using namespace cv::ml; cv::Ptr<cv::face::FaceRecognizer> recognizer; CascadeClassifier faceCascade; char g_moduleFlag = 0; vector<string> g_ids; Mat preProcessImage(Mat input); Mat extractFace(Mat input, vector<Rect> *faces); bool detection(void); void init(void); int videoProcess(void); Mat testvideo(Mat img); int trainOnce(Mat img); int updateLabels(void); //输出灰度图像,直方图均衡,长宽缩小0.5倍 Mat preProcessImage(Mat input) {
//cout<<"-->>function preprocessImage"<
Mat result
;
resize
(input
, input
,
Size
(
)
,
0.5
,
0.5
, INTER_AREA
)
;
cvtColor
(input
, result
, COLOR_BGR2GRAY
)
;
// Equalize the histogram
equalizeHist
(result
, result
)
;
return result
;
}
//仅支持单脸
//未检测到脸时返回纯黑
//返回灰度脸图,缩小了1.1倍 Mat
extractFace
(Mat input
, vector
<Rect
>
*faces
)
{
//cout<<"-->>function extractFace"<
Mat result
=
preProcessImage
(input
)
; Mat zero
= Mat
::
zeros
(result
.rows
, result
.cols
, CV_8UC1
)
; faceCascade
.
detectMultiScale
(result
,
*faces
, \
1.1
,
2
,
0
|CV_HAL_CMP_GE
,
Size
(
100
,
100
)
,
Size
(
200
,
200
)
)
;
if
(
(
*faces
)
.
size
(
)
==
0
)
return zero
; Mat grayc
= result
.
clone
(
)
; grayc
=
grayc
(
(
*faces
)
[
0
]
)
;
//
return grayc
;
}
//检测人脸 Mat
detection
(Mat img
)
{
//cout<<"-->>function detection"<
vector
<Rect
> faces
; Mat grayt
=
extractFace
(img
,
&faces
)
; Scalar he
=
sum
(grayt
)
;
if
(he
[
0
]
==
0
)
{
resize
(img
, img
,
Size
(
)
,
0.5
,
0.5
, INTER_AREA
)
;
return img
;
}
resize
(img
, img
,
Size
(
)
,
0.5
,
0.5
, INTER_AREA
)
;
rectangle
(img
, faces
[
0
]
,
Scalar
(
255
,
255
,
255
)
,
2
)
;
return img
;
}
int
updateLabels
(
void
)
{
cout
<<
"-->>function updateLabels"
<<endl
;
int inputlabel
; cout
<<
"请输入标签号:"
<<endl
; cin
>>inputlabel
; cin
.
ignore
(
)
;
//g_ids.push_back(to_string(inputlabel)); cout
<<
"-->>function updateLabels end"
<<endl
;
return inputlabel
;
}
int
trainOnce
(Mat img
)
{
cout
<<
"-->>function trainOnce"
<<endl
; std
::vector
<cv
::Mat
> referenceImages
; std
::vector
<
int
> labels
;
// vectors of reference image and their labels vector
<Rect
> faces
; Mat frame
;
int inputlabel
; frame
=
extractFace
(img
,
&faces
)
; Scalar he
=
sum
(frame
)
;
if
(he
[
0
]
==
0
)
{
cout
<<
" No face"
<<endl
;
return
-
1
;
} inputlabel
=
updateLabels
(
)
; referenceImages
.
push_back
(frame
)
; labels
.
push_back
(inputlabel
)
;
if
(g_moduleFlag
==
0
)
//是否有模型
{
recognizer
->
train
(referenceImages
, labels
)
; cout
<<
"g_moduleFlag == 0!"
<<endl
; g_moduleFlag
=
1
;
}
else recognizer
->
update
(referenceImages
, labels
)
; cout
<<
"trained!"
<<endl
; recognizer
->
write
(
"../trainer.yml"
)
;
return
0
;
}
//摄像头测试 Mat
testvideo
(Mat img
)
{
//cout<<"-->>function testvideo"<
int predictedLabel
=
-
1
;
double confidence
=
0.0
; vector
<Rect
> faces
; Mat zero
= Mat
::
zeros
(img
.rows
, img
.cols
, CV_8UC1
)
;
if
(g_moduleFlag
==
0
)
{
cout
<<
"未训练,无法测试"
<<endl
;
return zero
;
} Mat grayt
=
extractFace
(img
,
&faces
)
; Scalar he
=
sum
(grayt
)
;
if
(he
[
0
]
==
0
)
{
//cout<<"图片中无人脸"<
resize
(img
, img
,
Size
(
)
,
0.5
,
0.5
, INTER_AREA
)
;
return img
;
}
resize
(img
, img
,
Size
(
)
,
0.5
,
0.5
, INTER_AREA
)
;
rectangle
(img
, faces
[
0
]
,
Scalar
(
255
,
255
,
255
)
,
2
)
;
// predict the label of this image recognizer
->
predict
(grayt
,
// face image predictedLabel
,
// predicted label of this image confidence
)
;
// confidence of the prediction string name
;
if
(confidence
<
80
)
{
name
=
to_string
(predictedLabel
)
;
}
else
{
name
= g_ids
[
0
]
; confidence
=
0
;
} stringstream ss
; ss
<<
(
int
)confidence
;
putText
(img
, ss
.
str
(
)
.
c_str
(
)
,
Point2d
(faces
[
0
]
.x
, faces
[
0
]
.y
+
30
)
, \ FONT_HERSHEY_SIMPLEX
,
1
,
Scalar
(
0
,
0
,
255
)
,
2
, LINE_AA
)
;
putText
(img
, name
,
Point2d
(faces
[
0
]
.x
, faces
[
0
]
.y
+faces
[
0
]
.height
)
, \ FONT_HERSHEY_SIMPLEX
,
1
,
Scalar
(
0
,
0
,
0
)
,
2
, LINE_AA
)
;
return img
;
}
int
videoProcess
(
void
)
{
cout
<<
"-->>function videoProcess"
<<endl
; Mat camera
; vector
<Rect
> faces
;
char ch
=
48
;
char sh
= ch
;
int count
=
0
; VideoCapture
cap
(
0
)
;
if
(
!cap
.
isOpened
(
)
)
{
cout
<<
"No video!"
<<endl
;
return
-
1
;
} cout
<<
"请在图片中选择摄像头模式:"
<<endl
; cout
<<
" 0 显示视频"
<<endl
; cout
<<
" 1 训练人脸"
<<endl
; cout
<<
" 2 持续测试人脸"
<<endl
;
while
(true
)
{
cap
>> camera
;
flip
(camera
,camera
,
1
)
;
if
(ch
==
48
)
{
//0 普通加载摄像头 camera
=
detection
(camera
)
;
//resize(camera, camera, Size(), 0.5, 0.5, INTER_AREA);
imshow
(
"Camera"
, camera
)
; sh
= ch
; ch
=
waitKey
(
1
)
;
}
else
if
( ch
==
48
+
1
)
{
//1 训练人脸
trainOnce
(camera
)
;
resize
(camera
, camera
,
Size
(
)
,
0.5
,
0.5
, INTER_AREA
)
;
imshow
(
"Camera"
, camera
)
; ch
=
48
+
2
;
}
else
if
(ch
==
48
+
2
)
{
//2 持续测试人脸 camera
=
testvideo
(camera
)
; Scalar he
=
sum
(camera
)
;
if
(he
[
0
]
==
0
)
//人脸未训练 ch
=
48
;
else
{
imshow
(
"Camera"
, camera
)
; sh
= ch
; ch
=
waitKey
(
1
)
;
}
}
else
if
(ch
==
27
)
//esc
break
;
else ch
= sh
;
} cap
.
release
(
)
;
return
0
;
}
void
init
(
void
)
{
cout
<<
"-->>function init"
<<endl
; string faceCascadeName
=
"../haar/haarcascade_frontalface_alt.xml"
;
if
(
!faceCascade
.
load
(faceCascadeName
)
)
{
cerr
<<
"Error loading cascade file. Exiting!"
<< endl
;
exit
(
0
)
;
} g_ids
.
push_back
(
"Unknown"
)
; recognizer
= cv
::face
::LBPHFaceRecognizer
::
create
(
1
,
8
,
8
,
8
,
200.
)
;
}
int
main
(
int argc
,
char
* argv
[
]
)
{
cout
<<
"-->>function main"
<<endl
; Mat camera
;
init
(
)
;
videoProcess
(
)
;
destroyAllWindows
(
)
; cout
<<
"End of program"
<<endl
;
return
0
;
}
都看到这儿了,点个赞吧!
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/228053.html原文链接:https://javaforall.net
