数学建模社区-数学中国

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

作者: 杨利霞    时间: 2022-9-14 17:07
标题: Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
: ?" l5 q5 z5 d3 g1 `
# w6 m* D7 X$ I1 G  ^- ]1.安装包依赖& w2 J# R& e. q+ c3 Z" Y
与上篇通过摄像头动态识别人脸一样,先下载好opencv-python、face-recognition,这里因为使用的是照片对比的方式,特意使用tkinter画了一个简单的GUI方便操作。  R( \: t- f3 r

5 w. C) y! y5 ~4 V/ o在python 3以上版本tkinter是环境自带的,所以这里不需要安装/ r9 |: i5 f# Y" n& x9 U
1 l2 L  Q3 n6 @  {: I; F
2.代码示例8 j- {4 C5 v! ~: o' i# ~
import os) m! i, A( {) |
import cv2
8 X0 ^8 P- K. U3 f4 A9 Limport numpy as np
1 A+ }! p* F7 p7 dimport face_recognition
$ B9 E! X3 f" G$ ^import tkinter as tk  7 R, n$ ]% v' L
import tkinter.filedialog  F3 i3 N+ t" D; P0 z( E
from PIL import Image,ImageTk 1 p  F/ u  U3 A' p
& x+ |& b( c4 c
classNames=[]( h6 X% I9 [5 `9 ]1 g. d% F8 L: [: ]; ^
img_path='Picture'9 u3 {% V: `* W1 B* }: V2 x* q; k, }
img_recognition_path='Recognition'
: D* l" N2 `/ U8 AexistsEncodeingList=[]9 K1 Y' I) {/ b6 o
#对人脸集合进行编码进行处理! o  J6 q; P1 v1 h8 j
def findEncodeings(images):
$ l/ Q6 x; z% M0 q" f8 n/ u' V    for img in images:$ q; r' a8 S  S
        #灰度处理; |$ p) T* @6 w0 j4 \
        img=cv2.cvtColor(src=img,code=cv2.COLOR_BGR2RGB)
% F" G1 i8 i7 u8 D  ^+ t  x) e        #face_encodings对图片对象a_images进行编码并返回数组0位置编码结果' ~- d7 G+ Q( y' }' x& ]
        encode=face_recognition.face_encodings(img)[0]1 \% d; B0 K4 m1 q
        existsEncodeingList.append(encode); B3 ~1 {$ z& R  X+ Q

" H, N) u7 e  A& s8 M8 O6 a#获取当前存储的人脸编码集合
# F9 r* z: g% @. }# ]0 h0 odef findExistsEncodeingList(img_path):1 g! f) N. p  Z6 `; a  O
    images=[]
- U! x; O& t/ y+ F/ Y    #列出已经上传的所有图片
! D( F$ b* a% [" {; L    imgList=os.listdir(img_path)
0 T& h8 P1 K. o, K5 u; D6 ]    #处理存储的图片得到其人脸编码$ \2 A2 e9 R* U
    for pic in imgList:& r% |6 l0 e/ Z! y: u1 R$ L
        img=cv2.imread('{}/{}'.format(img_path,pic))
1 N0 i8 P9 t- w6 u& F+ u. Y        images.append(img)
; A% y: m: T- `" r6 b- O        classNames.append(os.path.splitext(pic)[0])
4 n1 @0 t. q" r1 I5 P5 @' {    findEncodeings(images): |$ z; R5 Z5 K0 n

4 i5 x5 P* @. Z1 k- b4 M2 `2 V#选择并对比图片
) ~- ?  |) X% K1 _" ^6 Cdef choosepic():  B, a+ n/ {+ j1 Y$ n) r
    choosepath = tkinter.filedialog.askopenfilename()9 z  Y+ F2 l9 W; h9 _+ x7 @
    path.set(choosepath)
/ K, ]/ {- ]6 n  Z( \2 v6 d" X    img_open = Image.open(entry.get()).resize((530,750))
! ]5 T$ c1 V' B4 \$ T7 Z    img = ImageTk.PhotoImage(img_open)- Q  p! ^, \4 w
    lableShowImage.config(image=img)- h" ~/ E6 I3 |, ^, u
    lableShowImage.image = img6 N4 |  }! F3 Y* @5 R/ y
    lableShowImage.place(x=30, y=70, width=530, height=750)
8 Y8 x5 I% V) _0 F# M+ t    faceRecognition(choosepath)  g( U1 w  r" G

; G6 a" v; ?6 o& P1 O. Z5 pdef faceRecognition(choosepath):( H# F4 ~9 d1 l+ U
    frame=cv2.imread(choosepath)
+ g/ h- q$ V! O6 G( k8 P$ O' J    frameRGB=cv2.cvtColor(src=frame,code=cv2.COLOR_BGR2RGB)$ i7 n# v9 R3 i
    #对摄像头读取的检测人脸" }: Y( P8 C) `1 r8 Y
    facesLocate=face_recognition.face_locations(frameRGB)
' L6 b6 j* F' u  x( d+ t( O3 h. s    #进行特征编码
$ a5 g3 ]4 r+ x5 @    faceEncoded=face_recognition.face_encodings(frameRGB,facesLocate)
7 I3 u- m3 e& s" `+ q! t) j( ?        #遍历检测的人脸和库中读取的图片进行对比,计算其相似度
6 Y; H% U/ ?" F! {; N    name='unknow'+ E8 `! `4 [# C2 {: v5 L
    for (top,right, bottom,left),face_encoding in zip(facesLocate,faceEncoded):. V$ `+ M; B- `. ]0 o
        #进行匹配3 P8 e4 }9 H) I0 Y) T0 b9 C, L2 D
        matchs=face_recognition.compare_faces(existsEncodeingList,face_encoding)
; {$ i; h, W- Y, a$ R; e% [3 s        #计算相似度9 ^* O2 b+ v- R6 u3 F+ L0 V
        distance=face_recognition.face_distance(existsEncodeingList,face_encoding)! u! {$ {  J: s$ O/ N# b, a1 j
        lab='unknow'
6 g( l& X1 o8 l0 u/ }7 L        for index, item in enumerate(distance):2 Z: C% {) D: V2 H1 {5 p
           if item<0.5:& `* j6 G' M& T" j, c2 Z
                if matchs[index]:
) I) M: e3 R, A; m( s' ]. M                    #得到匹配到的图片名称与相似度值/ i1 x1 P& ^1 v
                    lab='name:{}; Similarity:{}'.format(classNames[index],item)
; D9 r- f8 [& o5 z                    name=classNames[index]
6 I4 R+ N! ~: g. R                    break% S$ l) V5 j7 ?) d- b# S* H8 z# S
        #初始化面部捕捉框显示绿色
  L8 T' K" C7 [8 p/ x7 ^) k$ R, }        color1 =(0,255,0)
+ h1 S, ~1 `$ f% L6 r6 z; n        if name =='unknow':
, {" q; P6 h$ b9 Y3 v) e  z            #未能识别的时候显示蓝色
+ e2 `; V, Y4 w2 e, m0 C+ |            color1 =(255,0,0)
; X; u! i: Y" {. }5 h0 \% D- U7 N        #画面部捕捉框) _8 u$ Q; R9 y8 Q+ o& W2 b
        cv2.rectangle(img=frame,pt1=(left,top),pt2=(right,bottom),color=color1,thickness=3)$ x7 @& {- m) m
        #在捕捉框上添加匹配到的图片信息0 ^2 {5 [2 a+ h# o' L; a3 \
        cv2.putText(frame, lab, (left,top-8),cv2.FONT_HERSHEY_SIMPLEX, 0.7, color1, 2)
8 ~) M; |# _9 d/ R# _7 d        cv2.imwrite('{}/{}.png'.format(img_recognition_path,name),frame)
/ B% O2 s. X5 F1 [4 m    img_Recognition = Image.open('{}/{}.png'.format(img_recognition_path,name)).resize((530,750)); x  S0 N- F" W  H! P
    img = ImageTk.PhotoImage(img_Recognition)# v, @# T* U3 U$ E) s
    lableShowImage2.config(image=img)& Q1 n( @6 S" a
    lableShowImage2.image = img
8 o* N5 r9 @! k% O( b$ \    lableShowImage2.place(x=630, y=70, width=530, height=750)1 r8 b4 p0 H9 C
( ?1 U% v; J1 B3 ?1 n  X
if __name__ == '__main__':6 I. F% [3 s1 l
    findExistsEncodeingList(img_path)# r& P' `( Q* _. D) A, V, e
    #生成tk界面 app即主窗口+ h2 k/ E. z2 U
    app = tk.Tk()  
, \8 [8 h$ Z5 W7 a6 e- C# E+ v& w    #修改窗口titile
' k8 H3 n7 N' v1 W; [/ h; c    app.title("show pictue")  
+ `* s+ }$ p  n) V6 N% p3 D    #设置主窗口的大小和位置' s" r6 ?9 e7 P  x7 t1 f
    app.geometry("1200x900+200+50")
7 D, O3 f( T) l; e- k    #Entry widget which allows displaying simple text.
0 a' |* T; S2 P  X    path = tk.StringVar()! ]& `$ P: n5 F! ?- q" n6 v7 ~
    entry = tk.Entry(app, state='readonly', text=path,width = 100)$ w& x. q' s) T
    entry.pack()
" q3 v3 R; A8 x) w2 S    #使用Label显示图片6 a/ j7 e4 P2 s) L- s
    lableShowImage = tk.Label(app)
5 _" r- Y7 }3 X3 h- p    lableShowImage.pack()
0 j/ d% A" h+ Y6 @# S2 \7 F     #使用Label2显示处理后的图片
5 d  V$ a$ m4 B$ X& C    lableShowImage2 = tk.Label(app)$ {) Y. O- Q( X6 E
    lableShowImage2.pack()/ k$ {7 x! z: |
    #选择图片的按钮
& v) K; F# J* h/ K0 C& m# _( \6 j    buttonSelImage = tk.Button(app, text='choose picture', command=choosepic)
. L- U3 v+ E) A* u    buttonSelImage.pack()
8 r- S6 G" H) K" T5 ]. b/ _9 G, E    app.mainloop()5 u$ ~4 s+ P/ t9 |. }, f2 j4 B1 f. a
- Q: L/ X* J& j( P1 s3 a8 d4 S
3.说明8 J! V) S5 g! n  w
首先我将需要被识别的人脸的照片预设到项目目录的Picture文件夹下,然后创建一个Recognition目录存放识别过的图片,这样方便在一个界面上展示对比结果照片。& H8 O2 b5 F) C4 _2 u
0 x) f, h+ t; [! d- H4 V

2 z# M8 i8 f: N8 \( J8 P* `# b1 P& U! H' T  F* J& e& x" l( @! J
其实对比结果也可以不用存,直接将处理后的图片缓存直接展示在界面上,这里需要改一下此处的代码,将上述代码注释掉,然后换成下面的那行,通过数组直接转成图片
6 `! u; y7 X7 ^
% ^: H! u4 Y% s% u+ Z% q4 N  A
5 Z1 i; ~5 h* [4 Q2 [4 v6 G
8 n6 Y- t" _# E" G8 W$ Z 但是效果会存在色彩的失真,效果如下:! ^- `( E; H, x7 c
: B  V! o; A1 k+ j' `& s

1 N2 _4 T+ y( ?+ `: b& n* i4 O3 V+ ^
/ g* X) I: O! f也尝试了PIL的九种不同图片模式: 1,L,P,RGB,RGBA,CMYK,YCbCr,I,F,最终效果也没达到,大概与我resize((530,750))这个有关,也没继续纠结,有兴趣的同学可以尝试一下。
, q! ?3 g; Y0 m' I1 y2 o" b( R  K- d8 m, Y' j# e
这里简单提下PIL的九种不同图片模式:
* J6 i5 O' f! y! y3 U1 F3 R3 V+ r  {7 J) r% L* d
modes        描述
+ D1 S  o5 O4 B1 K! V1        1位像素,黑和白,存成8位的像素# c! S5 |/ U8 N- o1 q( G0 d: P
L        8位像素,黑白$ s; I. |" Z& f2 k9 R2 C3 g
P        8位像素,使用调色板映射到任何其他模式/ ?+ ?' _  v; w' n( b
RGB        3× 8位像素,真彩
; D& [8 _% f5 J, s- o* P# ZRGBA        4×8位像素,真彩+透明通道
/ V0 u/ a0 r& y1 d- i8 C+ ?CMYK        4×8位像素,颜色隔离9 s# [2 J. h0 \+ s
YCbCr        3×8位像素,彩色视频格式
$ d0 Z' i& N. d: `* S1 jI        32位整型像素
0 z: J. n- t* i7 j' BF        32位浮点型像素2 U$ r% |7 e9 [% D+ v
4.实现效果5 }6 P  t* f' ?2 ?3 g
& e4 w( ^1 p0 h

$ z/ K- y7 T( O( E1 C5 A; P6 P# e. `7 Z2 o9 a. b$ g
# R% D) p$ ]$ l2 {$ c7 `0 r) D
可以实现简单的人脸对比,Similarity代表相似度值,值越小代表人脸与预设的图片越相似。
8 u! c; [' |  x0 n  p$ c, ?————————————————
9 j  |3 i: y' v) Z版权声明:本文为CSDN博主「物联网_咸鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
2 M! p  Q% C( R3 p原文链接:https://blog.csdn.net/qq_17486399/article/details/126629288
0 I: r  H, _. v2 `/ G# J
+ D; F& L1 j6 ~
  F4 u, a- C$ U' i# u4 f




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