Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比) 0 D+ V8 p4 R3 d x( I+ P/ t! n) B4 i% f C. X
1.安装包依赖, d! A" @* `) J& s
与上篇通过摄像头动态识别人脸一样,先下载好opencv-python、face-recognition,这里因为使用的是照片对比的方式,特意使用tkinter画了一个简单的GUI方便操作。 5 Y A6 d+ h$ x v9 ~( y: G8 ~0 W1 P6 j$ p/ U- \在python 3以上版本tkinter是环境自带的,所以这里不需要安装* l# `8 x# F# b
q3 L) m8 V. i3 M9 w
2.代码示例 ( j8 a. s- x8 T" D3 [3 a9 Gimport os, {; c# Y6 h6 U/ u
import cv20 I9 H9 g3 L9 A9 I |2 {
import numpy as np ) x( b6 e- t- U5 q6 s8 Iimport face_recognition , H; n1 A6 e* C6 {( dimport tkinter as tk $ v: i5 w: j& V3 O9 v2 l! vimport tkinter.filedialog $ {3 n' [$ d# }7 a. c yfrom PIL import Image,ImageTk " B$ H; s5 Y8 o$ R9 y/ [. Z# J* P, }. i9 Z; p/ f& `
classNames=[] `2 P7 f( `! `/ Iimg_path='Picture' + S& J: ~% p+ o" @; o. Yimg_recognition_path='Recognition' $ a1 h9 C( T( B0 b1 aexistsEncodeingList=[] + @$ o/ v1 C- P#对人脸集合进行编码进行处理 . |. V- \. l( }$ Ydef findEncodeings(images): 1 b- O* X& \/ h4 [: f for img in images: + P. R' s, A4 k( o/ I8 S' m9 u #灰度处理( D( z+ k- ]2 y, S' ^( c
img=cv2.cvtColor(src=img,code=cv2.COLOR_BGR2RGB) 4 ]+ b# o7 d! Y, i #face_encodings对图片对象a_images进行编码并返回数组0位置编码结果 6 ~" {% O1 w- P3 | encode=face_recognition.face_encodings(img)[0] 8 q: Y* o; A( Q9 D3 i existsEncodeingList.append(encode) + H8 _3 f. w; W' d; k0 \9 C 7 T' ?1 s( z2 \' W#获取当前存储的人脸编码集合 % Y5 R& w$ ^" `, Ndef findExistsEncodeingList(img_path): / C4 x8 G) ~# A) V- d images=[] o9 s- z# D" u" G9 f
#列出已经上传的所有图片0 `, a$ ?9 Z" x8 a7 K" B
imgList=os.listdir(img_path): z1 E. M; |) ]$ ~
#处理存储的图片得到其人脸编码 ) @7 H5 |* `/ b3 }5 ^ for pic in imgList: ' d: L* {4 a9 K, } img=cv2.imread('{}/{}'.format(img_path,pic))2 h* H, h3 k" g* t" d0 K
images.append(img)8 p5 C$ P$ L% x+ @
classNames.append(os.path.splitext(pic)[0])1 K4 @' J0 U# o; Y" f
findEncodeings(images) 2 W; k& I6 s M. Y( ^' @1 f; v4 z" ?% K! Q6 D
#选择并对比图片! O9 Q0 M b9 }3 g
def choosepic(): % e" }+ ~* e! ]/ u choosepath = tkinter.filedialog.askopenfilename()% \. ]7 K; m! k% d6 \: E0 P8 K! M+ g
path.set(choosepath) # Y7 f7 |9 ~5 n" T img_open = Image.open(entry.get()).resize((530,750)) - C8 ]( Q& P+ u, j0 {7 t img = ImageTk.PhotoImage(img_open)2 U1 `1 K9 H3 n5 L: V- y' m6 S4 E
lableShowImage.config(image=img) ! a# P6 A5 n. l2 C' u8 D0 n lableShowImage.image = img 2 g& C/ v3 t* d$ u/ Y# ~4 Y: N lableShowImage.place(x=30, y=70, width=530, height=750) 2 r- {6 Y, g5 Q% V" S9 ~ faceRecognition(choosepath) 1 N2 o' ?5 Y/ C' @5 Y. P; _4 x: L2 @7 M1 v1 u5 H
def faceRecognition(choosepath):: r2 r' G3 E% W, O6 V
frame=cv2.imread(choosepath) - D9 \# p: }! T9 W4 K frameRGB=cv2.cvtColor(src=frame,code=cv2.COLOR_BGR2RGB)0 t1 g7 s$ b. @6 ~: ?# s
#对摄像头读取的检测人脸 2 U5 P( d9 q) }$ g6 a5 C" L# } facesLocate=face_recognition.face_locations(frameRGB)% w9 M/ I- X1 g1 b
#进行特征编码% k2 B1 N" k' V0 O1 L
faceEncoded=face_recognition.face_encodings(frameRGB,facesLocate) E; M% W( K9 `5 w# s3 Z #遍历检测的人脸和库中读取的图片进行对比,计算其相似度 . r2 N+ g2 Y8 G( u1 J s1 b- u name='unknow'5 q, A1 G, h; J- Y
for (top,right, bottom,left),face_encoding in zip(facesLocate,faceEncoded):# V/ l- R* j N
#进行匹配 & W7 o' i* f& c1 Z$ c6 T+ y* l) }9 i; B matchs=face_recognition.compare_faces(existsEncodeingList,face_encoding)$ G; x: E! D' c9 Y. i5 G- k/ [- Q
#计算相似度 ' H, \- ]! T9 D1 N# m( q- N/ s+ h; U distance=face_recognition.face_distance(existsEncodeingList,face_encoding)- H! R9 n8 x$ |
lab='unknow', q$ V+ x6 k+ q0 Q0 E' N
for index, item in enumerate(distance):! k) W' s6 {$ i4 M2 H& ]
if item<0.5:* ^8 D+ N- `+ U9 O$ a" j) `4 ^
if matchs[index]: : \7 U" w: O. C, L G$ q! M& K #得到匹配到的图片名称与相似度值! H- p& F; T$ y; e
lab='name:{}; Similarity:{}'.format(classNames[index],item) . u. v; m; t' ^. C1 ~ name=classNames[index]5 }% [2 s* Z) g3 V
break + N+ [, C, G* P2 v: } #初始化面部捕捉框显示绿色 3 s! a0 X+ c3 ^: Z5 N; N. s color1 =(0,255,0) % l* {, F% t! D" i if name =='unknow':; T) C% W% }. L
#未能识别的时候显示蓝色0 z9 f, I1 U5 `2 z1 ]( x
color1 =(255,0,0)0 N$ S8 I# t8 |. W
#画面部捕捉框 - b: x$ J* e6 n A! P cv2.rectangle(img=frame,pt1=(left,top),pt2=(right,bottom),color=color1,thickness=3) # q8 h3 G# u* q( t #在捕捉框上添加匹配到的图片信息& z$ ]/ s& ]$ Y) d/ |& U" i
cv2.putText(frame, lab, (left,top-8),cv2.FONT_HERSHEY_SIMPLEX, 0.7, color1, 2)6 E- Z9 o6 G5 R1 o- C4 ]
cv2.imwrite('{}/{}.png'.format(img_recognition_path,name),frame) 6 p8 O9 ~% W0 W1 a( r, w img_Recognition = Image.open('{}/{}.png'.format(img_recognition_path,name)).resize((530,750)) " ~% l( h# H: [1 w img = ImageTk.PhotoImage(img_Recognition)* `- a. \0 [: \# ~# X/ P9 z
lableShowImage2.config(image=img) + {7 K. W. p9 j' F5 u' o/ g1 C, Q( T9 ~ lableShowImage2.image = img % }. D( U( U I' z& ^! q) s1 D& ] C lableShowImage2.place(x=630, y=70, width=530, height=750)8 @1 _, r" l' @" A* p
/ N" ] [ l) f1 W/ b* Mif __name__ == '__main__':# P* `& a' J. L' t3 g7 H
findExistsEncodeingList(img_path)- T5 m+ s/ e) } x, n, U) p3 W
#生成tk界面 app即主窗口 2 R( i3 I( [8 h' f& g app = tk.Tk() 2 N- S# ~% b" v, Z4 N K #修改窗口titile( ^/ {2 c. U- V4 X0 H4 K e
app.title("show pictue") - t* ?- K3 `; h5 d/ h& r: q #设置主窗口的大小和位置* H6 P# L: r3 ~5 j- E5 s$ A8 | i) \
app.geometry("1200x900+200+50")# T9 I. {- p' U* S) q
#Entry widget which allows displaying simple text. 7 l5 n# C! X1 ^ path = tk.StringVar()8 X: P4 x1 s, F# o, r: F# Y6 ]
entry = tk.Entry(app, state='readonly', text=path,width = 100) 4 ]2 `4 v, x! T entry.pack()* `* } M3 V9 H9 b' v$ _
#使用Label显示图片 ?" t9 l p9 }/ j, ? t) @# \ lableShowImage = tk.Label(app) / ?: W' ^& w- r, o- o lableShowImage.pack() ; w- H( q2 c* H6 ? #使用Label2显示处理后的图片8 L4 V- b) i$ O* }( P; A$ c3 t+ M
lableShowImage2 = tk.Label(app)0 O5 k* x3 m! Z! N3 F, q2 ^
lableShowImage2.pack()% i7 ^, H; w+ Q' s7 {
#选择图片的按钮 9 Q! G8 I. s) \6 d8 E7 i buttonSelImage = tk.Button(app, text='choose picture', command=choosepic) 8 H* A" t$ p" k- g% C; d buttonSelImage.pack() - }- M5 c4 {! } app.mainloop() , P+ | ]$ {- a( O( g0 Q+ P: [0 v; n
3.说明 % f: i+ B7 E* v首先我将需要被识别的人脸的照片预设到项目目录的Picture文件夹下,然后创建一个Recognition目录存放识别过的图片,这样方便在一个界面上展示对比结果照片。/ F: h$ W$ D2 G/ q
; J; i1 a q! T) q7 |" {' x1 R 5 e/ }: [7 g5 k' x6 N. Z+ E3 X2 e$ C
其实对比结果也可以不用存,直接将处理后的图片缓存直接展示在界面上,这里需要改一下此处的代码,将上述代码注释掉,然后换成下面的那行,通过数组直接转成图片% z/ b e+ w, X% X& I
1 O( ?( q; b4 q9 m1 b * ?( k! J6 C" @+ z5 {' q ' J) h% l# [6 ]+ w 但是效果会存在色彩的失真,效果如下:$ I3 m* e% W6 B
2 q% o- p: o/ L* a. d8 D3 q- F. }9 K F" U" v
+ [& B# U% o+ I8 L/ d8 J' F
也尝试了PIL的九种不同图片模式: 1,L,P,RGB,RGBA,CMYK,YCbCr,I,F,最终效果也没达到,大概与我resize((530,750))这个有关,也没继续纠结,有兴趣的同学可以尝试一下。' z- e* M& J: }
; K) u8 P# r9 N) k9 A0 [# R- i
这里简单提下PIL的九种不同图片模式: ) x( S% a9 c% p y {9 x ' ~( a+ F! \; @modes 描述- M' ~" M# }7 K3 _% ]5 t3 d
1 1位像素,黑和白,存成8位的像素 " @' T$ e7 t1 O" E1 |) \/ YL 8位像素,黑白 % x4 o# j" i O2 ?" D3 l2 m/ pP 8位像素,使用调色板映射到任何其他模式: V8 N ~$ J. w6 c
RGB 3× 8位像素,真彩4 }. g% k u* X" M
RGBA 4×8位像素,真彩+透明通道 6 S- ~+ j" }% z* R5 m" x" eCMYK 4×8位像素,颜色隔离' I6 D3 K. [( z' [! W3 q5 j. j
YCbCr 3×8位像素,彩色视频格式 / j' s3 {* D+ pI 32位整型像素 - J+ ]8 X" X2 Z4 E9 mF 32位浮点型像素* ?, ^0 _" K* Y4 y1 S
4.实现效果 2 f: `6 V0 ]( @/ h, _ $ y$ W) K/ y! N- F. Q % w) X+ H1 [: E 2 W8 d$ }" T w# ~% _8 R- Y5 ]& G, w S; O4 w y: P, E3 ?
可以实现简单的人脸对比,Similarity代表相似度值,值越小代表人脸与预设的图片越相似。 $ g6 P5 Y( @. G2 v% a7 N" w————————————————; u- J) p8 x ?* o0 S
版权声明:本文为CSDN博主「物联网_咸鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 7 [% ]# m8 @: C原文链接:https://blog.csdn.net/qq_17486399/article/details/126629288; s. f/ p* |9 B7 L