数学建模社区-数学中国

标题: Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比) [打印本页]

作者: 杨利霞    时间: 2022-9-14 17:07
标题: Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)" r. w+ L" M3 g* V9 v
6 W! l  q" M+ w/ j1 _/ L
1.安装包依赖" u* I; K  q3 B' R: H0 w5 [; K. z
与上篇通过摄像头动态识别人脸一样,先下载好opencv-python、face-recognition,这里因为使用的是照片对比的方式,特意使用tkinter画了一个简单的GUI方便操作。. k& q" I) H( i2 x+ N/ y+ P) C

4 g2 V4 |5 L2 `  x' X在python 3以上版本tkinter是环境自带的,所以这里不需要安装
: i& A( X+ n" Q* g/ h; C+ V8 w' V* g& }- `7 n; K& x! m
2.代码示例  a: s! O* d% B% E8 _
import os) S8 @0 z( ?9 i% {4 g0 k4 I& ?
import cv24 J; }8 e% S, z5 S
import numpy as np. u1 U' X7 I6 M& e& q
import face_recognition
6 F, o& a9 r' eimport tkinter as tk  
; {6 I, x. ^. o2 x/ Cimport tkinter.filedialog
: y; E, w" F1 W0 afrom PIL import Image,ImageTk
6 d1 I; R5 V6 ?3 _  _! o( q( e% u7 B& a+ ~+ u5 }# A$ H$ y1 P' m
classNames=[]
1 G, a* s% Q# q( L% nimg_path='Picture': q5 {' `; `* k9 M
img_recognition_path='Recognition'
7 a4 y+ B4 w' H# rexistsEncodeingList=[]
1 D9 A! o- z% s& d) d#对人脸集合进行编码进行处理& m% n& s6 {  W" X$ E; Z. f
def findEncodeings(images):
) }" o; D  F' u) G    for img in images:  B1 _" P# m% _- N- \" M
        #灰度处理
; r- D: f$ C& e# ^        img=cv2.cvtColor(src=img,code=cv2.COLOR_BGR2RGB)
) y8 d/ k# S8 \6 [1 P4 H' V        #face_encodings对图片对象a_images进行编码并返回数组0位置编码结果( [/ r0 F& d8 B" e: ~6 R
        encode=face_recognition.face_encodings(img)[0]
2 T; ~6 o6 O) \$ P, N        existsEncodeingList.append(encode)$ Q/ ]+ H( v- B! `3 J0 |
/ A8 U7 g( V5 e& w( X
#获取当前存储的人脸编码集合
1 I% {2 _  M8 L& Vdef findExistsEncodeingList(img_path):; k5 l7 `: [" j' U
    images=[]
$ {4 u* {1 m! {2 j2 B    #列出已经上传的所有图片
+ z+ [7 I! B! P6 t    imgList=os.listdir(img_path)
4 r+ y; m/ k" ^8 D$ H    #处理存储的图片得到其人脸编码! {( B3 B, X2 B; {- H' [
    for pic in imgList:1 r2 J$ I' s( ]  d
        img=cv2.imread('{}/{}'.format(img_path,pic))- _: F. P) h/ E2 k1 |0 ^1 \1 q
        images.append(img)
% q. }- ]9 }- X7 K- g        classNames.append(os.path.splitext(pic)[0])
% R3 c9 j! G5 j. }1 K4 R    findEncodeings(images)4 w- w! X+ F9 K

! Z  U1 r+ f: g#选择并对比图片
. a1 t9 P) l' P1 [def choosepic():
2 D4 u  F8 t, T2 H! S9 C5 G2 r    choosepath = tkinter.filedialog.askopenfilename()" u  e7 Z& Z. b& G
    path.set(choosepath)
- \" J- Q6 _9 i) q! z    img_open = Image.open(entry.get()).resize((530,750))! U5 T1 W0 [' w6 d# m8 x
    img = ImageTk.PhotoImage(img_open)
& [! i: H" F3 t' Y5 q: J, z, w    lableShowImage.config(image=img)
4 x- ?2 L/ Y% l+ N3 [& B4 V+ X    lableShowImage.image = img
. ?3 E) o4 l. m$ w  p2 k1 s    lableShowImage.place(x=30, y=70, width=530, height=750)- y( l* ^" O4 S5 `6 T
    faceRecognition(choosepath)* M$ S# ?1 F% a8 f: F
$ D6 P% s8 x, Q* x
def faceRecognition(choosepath):
, p+ E. J4 _2 u; H# |    frame=cv2.imread(choosepath)- z3 A2 ]* W  r: a4 \& \) M
    frameRGB=cv2.cvtColor(src=frame,code=cv2.COLOR_BGR2RGB)+ P& ^1 M% H6 w9 ?  Q
    #对摄像头读取的检测人脸
) B( ]7 s+ A; O" h( b% Q    facesLocate=face_recognition.face_locations(frameRGB). M& N3 {: ]4 h0 z6 {8 S
    #进行特征编码
( O/ X0 H5 ?2 W  V9 I* N    faceEncoded=face_recognition.face_encodings(frameRGB,facesLocate)% m* }- T/ I& s, p: H4 A8 N/ W
        #遍历检测的人脸和库中读取的图片进行对比,计算其相似度
: q' t. ~' [9 q* i    name='unknow'
' M' C' C7 p- k( u- Q+ _3 i# ?    for (top,right, bottom,left),face_encoding in zip(facesLocate,faceEncoded):" t8 Q/ C. D1 j! V/ t
        #进行匹配
) f7 v+ Y% Q: n+ t7 j3 J$ P3 K9 \        matchs=face_recognition.compare_faces(existsEncodeingList,face_encoding), z! H" g, O$ r' \
        #计算相似度* D% k- F+ R9 Z3 H8 v( S; p
        distance=face_recognition.face_distance(existsEncodeingList,face_encoding)
! z4 N* F7 a) w        lab='unknow'
; h: r) n2 o: |9 Z: b        for index, item in enumerate(distance):
0 k" b/ x( L: K  r' [           if item<0.5:# T; h9 u; u% J) H  N3 I- M+ n6 e
                if matchs[index]:- f! u8 r2 d6 I$ a- Y$ k
                    #得到匹配到的图片名称与相似度值
& f8 V, K# }- H$ U, f% f0 r9 W6 V                    lab='name:{}; Similarity:{}'.format(classNames[index],item)* {8 [( V% b4 q$ r: M9 V
                    name=classNames[index]
0 D0 D, [. ]1 g. c& C                    break. m) v, \6 W! l7 }) s7 Y
        #初始化面部捕捉框显示绿色3 m1 t) [/ P9 q$ N
        color1 =(0,255,0)
, ~! A# J. p4 u        if name =='unknow':
* b2 z3 Q' q7 y' C' r            #未能识别的时候显示蓝色% @. P' P: }" e+ |0 R
            color1 =(255,0,0)& P( D. Q6 ]2 p7 l* ~# w
        #画面部捕捉框
  n0 j6 R3 r9 D1 \4 i' g# R2 p        cv2.rectangle(img=frame,pt1=(left,top),pt2=(right,bottom),color=color1,thickness=3)" ?: [) ?  r2 C
        #在捕捉框上添加匹配到的图片信息
, @2 ~# H' _7 N2 n        cv2.putText(frame, lab, (left,top-8),cv2.FONT_HERSHEY_SIMPLEX, 0.7, color1, 2)
7 O) A+ v0 X' g8 i4 X& S        cv2.imwrite('{}/{}.png'.format(img_recognition_path,name),frame)2 z. w( b# }# c& ]! N$ _9 k" M' P
    img_Recognition = Image.open('{}/{}.png'.format(img_recognition_path,name)).resize((530,750))
% y0 X" v9 \' m! }/ O7 S. U( ^    img = ImageTk.PhotoImage(img_Recognition)7 H5 s6 M8 [# H$ b0 I
    lableShowImage2.config(image=img)6 @; N8 }; r9 w) K& n
    lableShowImage2.image = img
8 d2 n) h" k. u3 a1 O' M. X$ e    lableShowImage2.place(x=630, y=70, width=530, height=750)& \% z- u0 c+ K% k' ~" R7 P0 ~

$ Y7 y  m0 g. u$ ?8 r& U' zif __name__ == '__main__':. B. o; u2 N8 h3 E
    findExistsEncodeingList(img_path)
& _! @! D% \1 n7 d2 T' d    #生成tk界面 app即主窗口/ i* M9 r/ Q! Y% y: f
    app = tk.Tk()  
9 L/ W- E1 }" d; m7 M+ v    #修改窗口titile. |; t5 a: j" K: s# |
    app.title("show pictue")  2 c1 w& o% x' N9 h
    #设置主窗口的大小和位置0 K5 B0 n! S3 O
    app.geometry("1200x900+200+50")
+ _# w1 M3 g0 |% x5 Y8 U3 N    #Entry widget which allows displaying simple text.& S2 s7 |. k1 C, t, ^( R& Q3 \4 r
    path = tk.StringVar()
& `/ ^* U$ n, D& B; y! ^0 m" ^    entry = tk.Entry(app, state='readonly', text=path,width = 100)0 s* p7 A3 ?5 t( g1 n
    entry.pack()
: R' v% D( t% Q% S- @    #使用Label显示图片
6 l+ y" }- `; o" n' `1 d, g    lableShowImage = tk.Label(app)
$ L! r# J3 M" d# t    lableShowImage.pack()
6 ^- H) e( L  _" F1 N( W- r/ t9 o     #使用Label2显示处理后的图片1 Q# Y4 x. q) @: G2 e# a
    lableShowImage2 = tk.Label(app)
6 ?1 m) A% j0 Z/ Y' |  v. z7 Z    lableShowImage2.pack(). u$ I) h9 E6 ?2 W$ f$ n
    #选择图片的按钮& E. g" E- i& k0 z/ s
    buttonSelImage = tk.Button(app, text='choose picture', command=choosepic)
  f3 K& Q$ g/ t# x8 H+ V    buttonSelImage.pack()0 _3 c/ a! ~' S6 H) \: J* \
    app.mainloop()
8 s5 u, X* w5 @5 n$ l0 p9 H6 i
, R* Y' E, m  ?; y3.说明  c% b) h# {) F6 d" y: k4 k' [
首先我将需要被识别的人脸的照片预设到项目目录的Picture文件夹下,然后创建一个Recognition目录存放识别过的图片,这样方便在一个界面上展示对比结果照片。
1 s2 u; r& V0 F/ Y  O" N- C! k0 o: A( l- m# H! b+ p

8 L2 |. i& f) q
( b8 _& Q/ d4 X9 [+ ? 其实对比结果也可以不用存,直接将处理后的图片缓存直接展示在界面上,这里需要改一下此处的代码,将上述代码注释掉,然后换成下面的那行,通过数组直接转成图片
; z% {& B) ]! M, |9 z4 Y, k2 ]2 f5 k% T9 x
. T8 H0 t' s% i# i1 L: h

; K: K, c. v9 X 但是效果会存在色彩的失真,效果如下:
: A9 H# J( Y; @! L! t
- Y! U3 ?5 G' k& b* f' L3 t- J, t& b8 `4 [
+ \  R' O) H- h* q* p
也尝试了PIL的九种不同图片模式: 1,L,P,RGB,RGBA,CMYK,YCbCr,I,F,最终效果也没达到,大概与我resize((530,750))这个有关,也没继续纠结,有兴趣的同学可以尝试一下。
$ X* [8 ^& [* v( u+ F  P
  r2 D" y- ^: _& h( O1 F4 s这里简单提下PIL的九种不同图片模式:
/ _3 W: D5 T) o3 k- G2 F
+ T8 ]5 a* l' l0 nmodes        描述8 Q, v5 @4 Y/ J0 U( E- j
1        1位像素,黑和白,存成8位的像素6 ~( i- D# W1 r* f. _- D3 D3 u% Y. \
L        8位像素,黑白
$ S, L( ~$ d, S; D1 i  X' GP        8位像素,使用调色板映射到任何其他模式0 i) r0 }/ K) a& o' o
RGB        3× 8位像素,真彩! B* w# K7 `" ?2 w1 i* T
RGBA        4×8位像素,真彩+透明通道. X) D* I5 W3 h
CMYK        4×8位像素,颜色隔离" q' E5 _# u# N% G- @3 F! _
YCbCr        3×8位像素,彩色视频格式' R& Q9 V" b: f+ r: A  u1 W
I        32位整型像素: n, l- ^( Q- \6 F) ~, S0 h' U
F        32位浮点型像素( J8 q; ]0 ^6 U! d/ D# y" g
4.实现效果
' I, f# Y) ~" b; Y; P
+ E8 a* _  X: m5 c, |4 w8 h5 K4 e% q* W3 l" {& M, L

9 V: D  |2 a: \' F+ ]" H: O) e! }1 V, x" d2 y. p% a( L
可以实现简单的人脸对比,Similarity代表相似度值,值越小代表人脸与预设的图片越相似。6 g- E  ]6 ]" \+ y, }
————————————————
9 p8 q, v1 R  m! ^3 n版权声明:本文为CSDN博主「物联网_咸鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
3 F0 e$ ]: A# D$ o4 o' q原文链接:https://blog.csdn.net/qq_17486399/article/details/126629288
$ b  d& S8 [( e- z! f; A! J( E3 D
% Z6 d1 D5 E$ y) s! D% K
" l% I/ s2 L5 @' H( \8 ~2 A




欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5