数学建模社区-数学中国
标题:
Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
[打印本页]
作者:
杨利霞
时间:
2022-9-14 17:07
标题:
Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
3 ^3 W7 d* I4 a/ r# k
/ }# P4 d# O& @
1.安装包依赖
5 u1 p4 `% K! `2 K! y
与上篇通过摄像头动态识别人脸一样,先下载好opencv-python、face-recognition,这里因为使用的是照片对比的方式,特意使用tkinter画了一个简单的GUI方便操作。
+ [4 B2 j7 `; N/ ~4 x( N V, D4 [: N
3 b2 i" b% p% }# N, L
在python 3以上版本tkinter是环境自带的,所以这里不需要安装
# f4 R; l" r, Z4 ?; G3 }6 U( E
$ b6 i/ R# J# ]3 q: c
2.代码示例
+ | a. Q, x4 O# h# ]; b
import os
" B* m9 g0 {, O
import cv2
6 a0 b; Z V: T1 J# F
import numpy as np
& ?& o3 C& O8 W: Q9 C* h/ |$ @
import face_recognition
% ^! C# P0 v, g% X! f
import tkinter as tk
' o' O: a( M& g9 I
import tkinter.filedialog
: [; _) L$ N* H! a5 F
from PIL import Image,ImageTk
3 a" g" Z5 y$ N5 Q8 B
; ?8 i/ l) F: ~
classNames=[]
7 Z) D6 L, y0 v( l1 u2 v
img_path='Picture'
5 E/ M" R3 I& C) S6 k
img_recognition_path='Recognition'
. l, N$ H! }: D* h( A1 P& `" j6 M( ]
existsEncodeingList=[]
% d: L3 ], Z' z% p. n0 y
#对人脸集合进行编码进行处理
/ B* v) Y5 X' N9 q, X
def findEncodeings(images):
x3 T+ m$ ]- A: n! C& U/ H7 [* i
for img in images:
* ?; j4 A5 Y1 }6 K1 Z
#灰度处理
) A, o1 G$ G- p8 f/ W; {7 ^
img=cv2.cvtColor(src=img,code=cv2.COLOR_BGR2RGB)
4 ^0 ?5 S3 Z4 b' f( q8 s3 W. u
#face_encodings对图片对象a_images进行编码并返回数组0位置编码结果
F! `/ E: o% I7 R0 Z# U
encode=face_recognition.face_encodings(img)[0]
) A. I4 x; p$ q! N9 }
existsEncodeingList.append(encode)
$ Y& P1 g. [ K/ Y, Y% O: d$ d: Z
* u* \8 ?& w1 K0 z
#获取当前存储的人脸编码集合
4 O% ~- g/ f* o. g
def findExistsEncodeingList(img_path):
$ r* y# n9 I+ S; L* a1 b
images=[]
; ]# e1 o& V* L
#列出已经上传的所有图片
% ^2 a4 R; T. L
imgList=os.listdir(img_path)
6 J8 X3 d' K( L d9 |" Z2 ?/ Y4 |
#处理存储的图片得到其人脸编码
/ b7 d& a5 \% {) m: g) g; r; L
for pic in imgList:
* f" M0 \, [9 a/ w
img=cv2.imread('{}/{}'.format(img_path,pic))
2 U) g/ [5 ^9 z3 B
images.append(img)
5 {8 ?2 l+ [3 q" _+ [/ o4 {
classNames.append(os.path.splitext(pic)[0])
* J; L3 L9 d/ ]. h! L! [, n3 N
findEncodeings(images)
7 A, L9 P: d5 T
% l% _# K2 ?0 `& m; B; h4 [
#选择并对比图片
: X9 F$ Z6 S. ]% }& w! l, n" w
def choosepic():
7 d: h$ Q# }8 R4 G+ s7 W2 N- L
choosepath = tkinter.filedialog.askopenfilename()
! B, ~5 p) O ?6 z3 D
path.set(choosepath)
5 _2 B7 x3 ]* s. i) j5 _9 o8 e; Z9 m
img_open = Image.open(entry.get()).resize((530,750))
$ c1 ?9 s/ S. p; r3 X
img = ImageTk.PhotoImage(img_open)
9 U2 I+ x: g* B3 L
lableShowImage.config(image=img)
5 l7 @4 a% U) Q& ^# k# X
lableShowImage.image = img
* G6 o& ~) B; n" P* ]( D- A+ ]7 j
lableShowImage.place(x=30, y=70, width=530, height=750)
" d# `5 f0 Y% |/ C2 t% t i# z
faceRecognition(choosepath)
9 g/ w1 e4 Z F, I
. e4 T6 e8 p/ s2 r5 M g' b
def faceRecognition(choosepath):
4 ^) T8 P& k+ q' N. F9 P/ X. y
frame=cv2.imread(choosepath)
* y6 K$ m0 p1 B. K, M) W7 B
frameRGB=cv2.cvtColor(src=frame,code=cv2.COLOR_BGR2RGB)
, {6 R6 T& o2 C- u
#对摄像头读取的检测人脸
. Z9 C) I2 P. Q
facesLocate=face_recognition.face_locations(frameRGB)
, R- x6 ]4 M# Q0 J# o' r" @* V
#进行特征编码
2 O5 f6 _0 \+ P4 I4 v' U
faceEncoded=face_recognition.face_encodings(frameRGB,facesLocate)
; b, D( Q- T1 G r+ C
#遍历检测的人脸和库中读取的图片进行对比,计算其相似度
+ \( }5 t' m, h; f) N" r% O
name='unknow'
# M+ E6 K" v1 \* `6 |
for (top,right, bottom,left),face_encoding in zip(facesLocate,faceEncoded):
0 x8 Q1 j: b( a. A
#进行匹配
! r! O2 y: J7 h8 l* Y
matchs=face_recognition.compare_faces(existsEncodeingList,face_encoding)
( M1 _( K2 E/ X* k ?- a; T/ X$ L
#计算相似度
+ R" H6 S$ i& W# |* C. U' |2 T# v
distance=face_recognition.face_distance(existsEncodeingList,face_encoding)
$ P7 \! h% `+ Z6 E
lab='unknow'
# M! S. Y& V9 [9 I7 t v
for index, item in enumerate(distance):
0 G$ E7 H0 ^ S& w
if item<0.5:
; t; w9 H2 F/ S% w/ ?3 @7 \
if matchs[index]:
; ?$ o2 `0 W! d: \! E
#得到匹配到的图片名称与相似度值
5 o6 s e) K3 n6 G1 A6 |/ q! U
lab='name:{}; Similarity:{}'.format(classNames[index],item)
5 B6 \& x( x0 z3 R
name=classNames[index]
% V* c8 S% E- A- k5 V
break
- S2 ^, O5 N: p
#初始化面部捕捉框显示绿色
) b" n9 ^) c& e8 y( l; E: W' W- x
color1 =(0,255,0)
$ v: K* E9 N2 I7 I8 ]
if name =='unknow':
# N5 `2 A3 f+ X2 k& Z/ s; A- l
#未能识别的时候显示蓝色
& u! F! j7 F# S) l+ a7 ]3 C( Q& M
color1 =(255,0,0)
% v& z) Y, G1 {% C+ [7 E
#画面部捕捉框
7 y' F8 k) T/ y! \4 d
cv2.rectangle(img=frame,pt1=(left,top),pt2=(right,bottom),color=color1,thickness=3)
% j5 X; h3 Y$ x1 j& q( D. s4 J3 b- ]9 q
#在捕捉框上添加匹配到的图片信息
* O9 I. L# o% O; z6 g$ S; Z l/ E7 I
cv2.putText(frame, lab, (left,top-8),cv2.FONT_HERSHEY_SIMPLEX, 0.7, color1, 2)
/ [" [' w6 Z2 D* I
cv2.imwrite('{}/{}.png'.format(img_recognition_path,name),frame)
: l1 P* { X2 B4 L+ p0 N0 Q
img_Recognition = Image.open('{}/{}.png'.format(img_recognition_path,name)).resize((530,750))
" P2 t( f0 m$ ^: L; r+ H' I) j
img = ImageTk.PhotoImage(img_Recognition)
! Y8 d9 f7 a: q7 H1 p7 b( H
lableShowImage2.config(image=img)
; I+ W3 h+ W0 I1 n6 R7 W, S [
lableShowImage2.image = img
# Z9 g3 n; N6 V/ L; c) V# j9 D* M3 g
lableShowImage2.place(x=630, y=70, width=530, height=750)
4 S1 Q5 z& L4 j+ m3 } ]
+ S, r3 u. f# D0 K& k$ O# F3 s
if __name__ == '__main__':
( y# }1 M8 N+ \; O5 p
findExistsEncodeingList(img_path)
; c: O, |& S* E4 n- j
#生成tk界面 app即主窗口
6 U2 L( p. b% K; {9 z
app = tk.Tk()
! `0 m! `+ [5 P$ D, m
#修改窗口titile
8 ^- k& t. u* l3 M4 O7 I0 n+ S4 c5 o
app.title("show pictue")
- O# D% ~& p7 W3 |2 P
#设置主窗口的大小和位置
) ?& v) R- @7 `1 y7 p
app.geometry("1200x900+200+50")
) H& y; x0 g6 R0 B9 a% q' S
#Entry widget which allows displaying simple text.
7 L- I! P+ \% _3 B& ?
path = tk.StringVar()
1 e* J7 n3 E# F" n% @
entry = tk.Entry(app, state='readonly', text=path,width = 100)
# |( o! P H( \0 R& D
entry.pack()
% }$ @5 M; c7 p0 F6 r8 ? r2 c
#使用Label显示图片
0 r; T% r/ N6 d9 o
lableShowImage = tk.Label(app)
* G3 `, \' P( ?* O9 F0 O
lableShowImage.pack()
+ `" X9 `, ~6 ]+ C- \# O: f
#使用Label2显示处理后的图片
) B; w4 n9 { c+ j0 j. A
lableShowImage2 = tk.Label(app)
, J5 J- |) V: N0 ~
lableShowImage2.pack()
9 A$ n1 l. g$ \9 H, F
#选择图片的按钮
- O% T. T! K4 p5 }/ ?/ u
buttonSelImage = tk.Button(app, text='choose picture', command=choosepic)
e; _8 M. O/ D. r4 L8 V
buttonSelImage.pack()
/ t+ J5 _9 D3 r4 J+ s" m, a+ Y
app.mainloop()
. A! V8 R% l/ q% M% k4 Y) ]
" h; q7 s; x( ^. C8 ]7 a8 D9 x+ j
3.说明
8 { A/ D4 |- h; K1 v; a0 L9 k" _# d
首先我将需要被识别的人脸的照片预设到项目目录的Picture文件夹下,然后创建一个Recognition目录存放识别过的图片,这样方便在一个界面上展示对比结果照片。
2 F3 N0 S+ |+ a. P
- D- U0 D1 d8 l* n7 S j% U
8 f7 i" z8 k" _; a1 ^
9 x P& b$ m" g2 z* o" J0 r) K3 O
其实对比结果也可以不用存,直接将处理后的图片缓存直接展示在界面上,这里需要改一下此处的代码,将上述代码注释掉,然后换成下面的那行,通过数组直接转成图片
: m# r* P4 w- a1 O6 U: n& o
) D( a8 c* A* i9 i! a2 l5 u
8 l6 T( {2 C1 G
- R4 A4 x2 q# i( t$ H' v" q6 o
但是效果会存在色彩的失真,效果如下:
% O. n: S8 {& S) _. `8 y5 v
& R6 f0 O. n2 J5 \
7 M4 U# ?: X6 f# ^% a0 u
6 u) {4 ]) z1 s9 {+ Q
也尝试了PIL的九种不同图片模式: 1,L,P,RGB,RGBA,CMYK,YCbCr,I,F,最终效果也没达到,大概与我resize((530,750))这个有关,也没继续纠结,有兴趣的同学可以尝试一下。
9 i4 ?6 e& k6 O! _8 U5 {2 d0 m$ |
0 J( x- Q) i8 h# U0 b
这里简单提下PIL的九种不同图片模式:
/ r7 }; M7 R* ^ x
% X* y& F9 j& @$ V# G
modes 描述
" l/ |0 A: Y3 i7 D' W( ~. M, h! w% }
1 1位像素,黑和白,存成8位的像素
# |, E R) }8 Y
L 8位像素,黑白
0 H# e& s3 H8 z, P9 \% M
P 8位像素,使用调色板映射到任何其他模式
2 D6 `* r! k7 i0 S5 `1 o
RGB 3× 8位像素,真彩
" f0 Y% @2 _! }5 u
RGBA 4×8位像素,真彩+透明通道
, U4 y3 e3 s+ j& D
CMYK 4×8位像素,颜色隔离
8 Q% B9 ~" t. ~! {' I4 x
YCbCr 3×8位像素,彩色视频格式
, `. `0 r" d+ m/ Y5 F2 f
I 32位整型像素
, D x$ e* n9 K
F 32位浮点型像素
+ W v8 P3 o4 K. A+ I
4.实现效果
" }% V: a: y/ W0 B {3 }
9 _, u8 ^7 ^( _( a9 a D0 W
+ O1 R, x7 T/ N' w0 d0 ~
1 P8 ^; W+ m* @5 @6 ~
6 O t" c1 }2 I# ^& o9 m
可以实现简单的人脸对比,Similarity代表相似度值,值越小代表人脸与预设的图片越相似。
9 ^9 V$ V7 H0 O$ o# w# T1 p
————————————————
9 Y% X# l0 M; M i1 M8 j" T
版权声明:本文为CSDN博主「物联网_咸鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
* u: q$ _' f8 t' C0 w
原文链接:https://blog.csdn.net/qq_17486399/article/details/126629288
4 a) g, G9 T( l9 @/ m
1 `/ R1 N; L* x% h6 x
2 o4 [. s, |: R- y/ o7 D6 t' _; y
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5