6 I. e- l# b1 C$ I4 n, n" M9 m2 t1.安装包依赖2 h. D: z' {% k# P- w# M
与上篇通过摄像头动态识别人脸一样,先下载好opencv-python、face-recognition,这里因为使用的是照片对比的方式,特意使用tkinter画了一个简单的GUI方便操作。 ?: u+ n0 Z. P$ r
8 J G6 ], \% e6 i, e在python 3以上版本tkinter是环境自带的,所以这里不需要安装" O+ j5 K1 u4 T) M" i' S
2 Z w, s- @/ M5 l9 g+ y* `2.代码示例$ V; N; G J) ]6 c
import os" a p% [0 [) n* ^
import cv2 5 D. Q, k3 L, P8 b# Wimport numpy as np D1 s4 l4 Z( g7 e7 A: p
import face_recognition8 _* y4 Q2 i1 M) z# O
import tkinter as tk 7 o8 i7 S: U! R
import tkinter.filedialog ; S ]& E5 E9 t9 t8 j+ Dfrom PIL import Image,ImageTk 2 s9 r! f. h7 G7 e) [# K
# p" c* o4 s" g! S; ?classNames=[] / |: q" P% C% Rimg_path='Picture' 8 f% d; ?: [4 t0 [& k) ^img_recognition_path='Recognition'( A$ j, S8 [4 J. W+ W, V1 q
existsEncodeingList=[]9 G8 `" x+ B3 H; x7 k
#对人脸集合进行编码进行处理 2 C. P; p- i/ X* edef findEncodeings(images): % ^8 A2 a: \* s0 A9 m% R$ u5 l% i/ o for img in images: : i6 \/ B6 U0 u. I) q, }1 V #灰度处理 5 @7 ~- i$ o; \" T% H img=cv2.cvtColor(src=img,code=cv2.COLOR_BGR2RGB) 9 K) J2 @) S y2 Q* ` #face_encodings对图片对象a_images进行编码并返回数组0位置编码结果, O! m' i/ @5 H$ N9 V3 N' P
encode=face_recognition.face_encodings(img)[0] 3 ?0 g8 d. C. l& y7 [2 S) i existsEncodeingList.append(encode) % g" E7 k' E9 @4 H w5 g# k0 b9 X" J, t4 C
#获取当前存储的人脸编码集合 ( k* X9 c! ^" ^ W$ G" g5 S! l. Ldef findExistsEncodeingList(img_path):4 z* t3 t8 X. G+ Y: V! m
images=[]: H; P* p. D) z9 |" Q& Y+ Z
#列出已经上传的所有图片 |$ X# A. `$ P' t) Z8 @5 N9 D' I imgList=os.listdir(img_path) + x% u2 s$ V- J2 G' `' f; y #处理存储的图片得到其人脸编码 " {! O9 o1 X: h: u7 @ for pic in imgList:: b( |8 i7 u- E
img=cv2.imread('{}/{}'.format(img_path,pic))7 R3 m$ Z9 v; l3 @/ C+ ?
images.append(img) ( k/ d7 U2 `& y8 ^+ c. ^2 u5 o classNames.append(os.path.splitext(pic)[0])8 g' I, R) Z$ D) A: w( j
findEncodeings(images) $ d& @7 T+ T# X' t9 V 9 [+ p4 l& `$ ], J1 v2 E#选择并对比图片 9 t& ~" j( R/ c% n) C$ Z tdef choosepic(): 7 } Q% e7 {+ ] choosepath = tkinter.filedialog.askopenfilename(); N, A! W7 b( o' J' O: ^6 Q
path.set(choosepath) ! s3 b+ p; Z- w% X+ k+ z( L5 H img_open = Image.open(entry.get()).resize((530,750)) ) f4 w, Y) i6 K3 e3 c/ P img = ImageTk.PhotoImage(img_open)! @+ f B& x1 d& C; p+ z; r
lableShowImage.config(image=img)2 l2 s! A6 S% G3 U/ C4 o- a. ^: o
lableShowImage.image = img ! @" z* c- Q3 t0 G/ e! b) O, R4 K0 ^ lableShowImage.place(x=30, y=70, width=530, height=750) 6 l7 g, I- k% J& O) f faceRecognition(choosepath)2 [2 A7 @9 H$ x! V! {
2 U5 K1 A, o0 \1 L3 q6 r* j
def faceRecognition(choosepath):9 x& Z1 m s Y ?
frame=cv2.imread(choosepath) 8 g C0 e1 o* w4 j; ~9 [$ c a% ]% J frameRGB=cv2.cvtColor(src=frame,code=cv2.COLOR_BGR2RGB). M. w% {4 T+ X/ U
#对摄像头读取的检测人脸+ U1 E7 ^$ s4 ]: R% [
facesLocate=face_recognition.face_locations(frameRGB)% Z2 a [% P. l8 g9 H
#进行特征编码5 K) I- l, Q n
faceEncoded=face_recognition.face_encodings(frameRGB,facesLocate) 1 ^. B" t! g9 |, X7 q #遍历检测的人脸和库中读取的图片进行对比,计算其相似度1 M7 a+ v) W2 f
name='unknow' & E2 P( Q+ w3 Y: k; p+ V for (top,right, bottom,left),face_encoding in zip(facesLocate,faceEncoded):! O2 \" m, Y* V! R& l$ C- o
#进行匹配 ! b$ N/ I9 H3 B. I matchs=face_recognition.compare_faces(existsEncodeingList,face_encoding) / Y( p: ^! `. W7 K1 l/ R #计算相似度9 u" }* i5 F: `' a/ \8 i
distance=face_recognition.face_distance(existsEncodeingList,face_encoding)) b* f! w1 f. s0 A& M$ \6 E, K% g7 F
lab='unknow'" ^, B z: M1 m8 @" _7 C& K
for index, item in enumerate(distance): 5 y6 U: H/ @5 o% f) {3 T4 d if item<0.5:) V) D( K5 `1 }2 y& e& }
if matchs[index]:! X; n2 C7 a3 L2 {' b @7 M/ r
#得到匹配到的图片名称与相似度值0 J# g2 Q p. w. D8 O( s
lab='name:{}; Similarity:{}'.format(classNames[index],item)5 K1 S! e8 |0 @% b* w6 U [
name=classNames[index]6 \4 L' e6 [8 n h8 |& \3 ~
break( r$ [0 M% [2 M. Q/ s; U
#初始化面部捕捉框显示绿色 1 P& U- p6 B& @6 ~( @: t, L color1 =(0,255,0) L# Z6 V o( L7 \* H9 U- o' P& ^( ?* V; L
if name =='unknow': . J: U9 z" Z7 G9 W& M #未能识别的时候显示蓝色 . [6 c4 @6 T: J4 [/ b1 h color1 =(255,0,0) 5 d8 @, }# o5 I #画面部捕捉框 2 ^- T+ ~1 }' c3 l. \% I* ^ cv2.rectangle(img=frame,pt1=(left,top),pt2=(right,bottom),color=color1,thickness=3) " C3 t$ H, ?: p" f* I #在捕捉框上添加匹配到的图片信息4 t1 Y b3 n) @) a
cv2.putText(frame, lab, (left,top-8),cv2.FONT_HERSHEY_SIMPLEX, 0.7, color1, 2)4 u8 k) {6 U7 j& T) w
cv2.imwrite('{}/{}.png'.format(img_recognition_path,name),frame) 5 ~+ u1 p& _+ R- G F* r9 T img_Recognition = Image.open('{}/{}.png'.format(img_recognition_path,name)).resize((530,750)) 4 m0 _& ]: ^6 ?7 }& U img = ImageTk.PhotoImage(img_Recognition). o" d) n( Z: o5 R0 b8 ]
lableShowImage2.config(image=img)* w# E$ Y5 H+ n& X
lableShowImage2.image = img" T, K+ n7 ~- S# g
lableShowImage2.place(x=630, y=70, width=530, height=750)$ l" F9 k' P1 U# i. J# f: U
4 \. \' q: Z0 N; Mif __name__ == '__main__': 1 x4 k" |" q7 n9 R* C w6 \2 P findExistsEncodeingList(img_path) : Z) ^5 y7 i& H0 ? #生成tk界面 app即主窗口 5 P w+ g( j* @ app = tk.Tk() ! S4 C' Y1 z. l3 L+ t5 _+ k4 v
#修改窗口titile) q3 {4 J6 d2 i0 L+ x6 T
app.title("show pictue") + i. v! B7 D8 x #设置主窗口的大小和位置: o6 i' Z' u9 ]3 B
app.geometry("1200x900+200+50") 2 f- n# j2 a6 P0 \ #Entry widget which allows displaying simple text.* j5 v+ S5 x; i3 ?( X; a; P
path = tk.StringVar() 3 X4 `) I7 J8 q, b8 n" Z entry = tk.Entry(app, state='readonly', text=path,width = 100)& D7 M( D) _. n: f2 u5 W
entry.pack() 2 h; ]9 W/ w$ [1 X4 R #使用Label显示图片 4 Y* |+ O$ f6 N2 E lableShowImage = tk.Label(app)2 `% b: m. a3 @
lableShowImage.pack() ! W. r( Q& R q2 u" }1 R #使用Label2显示处理后的图片6 k) R8 W2 o' G+ A* v5 C. S$ T& a) F7 W
lableShowImage2 = tk.Label(app) n# C8 k R) X9 E2 O& V lableShowImage2.pack() - K; y3 o% `6 K8 _; N, _ \, E. Q #选择图片的按钮% }9 p. G! V5 y8 U I3 P
buttonSelImage = tk.Button(app, text='choose picture', command=choosepic) $ n, X. ^& Y8 M" G: d3 z. G5 u buttonSelImage.pack()% z* k9 h- w/ s" ]7 ]
app.mainloop() % t& @+ V b$ K/ X; K. {9 d0 h 0 H; T! q4 H4 q9 I2 ?3.说明) D+ T' V2 R1 c5 i1 c# Y
首先我将需要被识别的人脸的照片预设到项目目录的Picture文件夹下,然后创建一个Recognition目录存放识别过的图片,这样方便在一个界面上展示对比结果照片。. L& Z ^% G' f" |4 U8 r& r
- R6 ^5 L& E8 k$ l+ h. g$ k) k/ I O8 w9 {) H& H
) e: H1 V3 ?# u9 ] 其实对比结果也可以不用存,直接将处理后的图片缓存直接展示在界面上,这里需要改一下此处的代码,将上述代码注释掉,然后换成下面的那行,通过数组直接转成图片 2 p" s9 h6 p; H - X4 E" a% H" U- j0 F1 b3 k$ K e9 l* w9 J- H0 c f9 ?. [" B
4 [8 i3 ^* G; c% t: } 但是效果会存在色彩的失真,效果如下:% L: _ ~5 F) L+ Y" v
1 _/ l6 U) F+ D% c
$ f: K0 i& R* Y* P
j3 j( h' j/ }8 {2 B也尝试了PIL的九种不同图片模式: 1,L,P,RGB,RGBA,CMYK,YCbCr,I,F,最终效果也没达到,大概与我resize((530,750))这个有关,也没继续纠结,有兴趣的同学可以尝试一下。 7 B3 g; U$ f. `% ` + P, X2 _. h/ D6 ~5 _" y% S+ E这里简单提下PIL的九种不同图片模式: ; s+ V, A& R R+ z+ M' ?5 q/ _ 0 A& J- T8 Y: e' E( `modes 描述 0 [7 I8 P& \0 D9 A# ?* F. W, p1 1位像素,黑和白,存成8位的像素. c% n2 {) y3 x* j0 X8 m0 K4 M3 X
L 8位像素,黑白 ( M. Z# r( t6 x& Z0 eP 8位像素,使用调色板映射到任何其他模式- w: N& u y' o' X$ a: t$ m4 y0 v. a5 O, [
RGB 3× 8位像素,真彩 0 A2 B# k5 d% KRGBA 4×8位像素,真彩+透明通道 " |* l6 ~& I$ {" d8 R2 D- }CMYK 4×8位像素,颜色隔离 0 s9 G1 A; l& E6 C/ o! T$ J# [YCbCr 3×8位像素,彩色视频格式 # k) x" t" Y+ P/ z" xI 32位整型像素& K, [0 D# H. \, h$ C% \6 m6 l$ }1 x
F 32位浮点型像素 ; d0 j6 P0 K4 B0 r$ y' m' h3 M4.实现效果" l2 _3 X: q5 J8 ]/ e/ e
3 B, |2 O% b; z M B5 r1 b1 R3 d# ?9 S+ H7 t
; \& p( _ @/ Q% k$ ~% N8 x$ X: H& f7 `1 z! m
可以实现简单的人脸对比,Similarity代表相似度值,值越小代表人脸与预设的图片越相似。) k( c% w1 ?( D
————————————————' @( ]/ C7 X( A# A& e
版权声明:本文为CSDN博主「物联网_咸鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。/ v6 C- G6 V, _! ?& N: R
原文链接:https://blog.csdn.net/qq_17486399/article/details/126629288 ) r( F; t; B6 A- m+ ], _% v. \1 z- V8 G" a0 i" n