数学建模社区-数学中国

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

作者: 杨利霞    时间: 2022-9-14 17:07
标题: Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
+ N/ N' G" O" b: q  J
6 b' n6 h3 \* E1 |  h% V1.安装包依赖
6 ~1 _9 B0 t" p9 W, y9 A! q+ j与上篇通过摄像头动态识别人脸一样,先下载好opencv-python、face-recognition,这里因为使用的是照片对比的方式,特意使用tkinter画了一个简单的GUI方便操作。
( X2 q9 `/ o9 h- c# j& O2 R# c" ]9 t/ S
在python 3以上版本tkinter是环境自带的,所以这里不需要安装
( A. y" B- W5 H: T
: }8 @& {9 A/ P3 Q) e# g% k/ A* I2.代码示例% ], {+ u2 o6 M; R9 a; H
import os
- ^9 e7 M- U$ G$ a3 Aimport cv2* t- f- o8 E1 U; U1 j4 ~) k, [7 `
import numpy as np
4 C2 Y. B! C. P) K6 Rimport face_recognition" `' [$ A3 V$ B1 H4 n1 ?$ s3 B
import tkinter as tk  1 g! s" w2 {' b- h, B
import tkinter.filedialog) _  l  ?6 B% k- {
from PIL import Image,ImageTk ' Q1 Z* Z4 \6 [6 n

% O- {+ f$ w5 D4 p; BclassNames=[]" [* m" R: ?+ Y0 d' C
img_path='Picture'& K: G+ g+ c% a* S
img_recognition_path='Recognition'2 a& g9 P2 m1 ^' f- u' x3 s  B
existsEncodeingList=[]( c* O6 S& A9 `- B* ?8 j
#对人脸集合进行编码进行处理
, r* O% P! `- E; S  J2 mdef findEncodeings(images):
! Y9 K, v, c. d# _    for img in images:
: d! x9 M& q4 C7 t4 B        #灰度处理
" R. q* Z8 a4 t% ]# `7 D& c8 V        img=cv2.cvtColor(src=img,code=cv2.COLOR_BGR2RGB); A- `- {, \% `0 L& C5 U7 n7 @: l
        #face_encodings对图片对象a_images进行编码并返回数组0位置编码结果: B" c8 |* E. U! E0 |  M
        encode=face_recognition.face_encodings(img)[0]0 i: k: ]9 w* j6 b1 @1 i, H  G/ |
        existsEncodeingList.append(encode)
6 u0 n) J6 b1 q5 o. W( z/ \0 ?
$ ^9 L* |: x! d" X#获取当前存储的人脸编码集合$ a% Q6 p4 P' j  N
def findExistsEncodeingList(img_path):
% B0 k5 N5 u, }. g    images=[]
7 g/ r  v' ?  Q    #列出已经上传的所有图片% N4 F: E! v2 A
    imgList=os.listdir(img_path)
% M9 E0 T0 \" F8 n    #处理存储的图片得到其人脸编码: Z( d  x/ z+ n+ X! S
    for pic in imgList:
( n4 U$ |, E* A" w$ l* s5 E9 s$ h5 S        img=cv2.imread('{}/{}'.format(img_path,pic))! c6 s) [  \2 b) D% S) u
        images.append(img)* M+ U! o4 Y  F7 W2 k6 l
        classNames.append(os.path.splitext(pic)[0])
- u3 Y- ]- V! {6 s    findEncodeings(images)
/ y+ l3 l0 W9 G  T  N
" r  C* ?0 D& l#选择并对比图片. q# u0 Y/ J, A4 E
def choosepic():  }1 Z+ g! k( V8 e  N7 K
    choosepath = tkinter.filedialog.askopenfilename()
1 [0 ?6 L( Z: A! J$ _# S: B. q    path.set(choosepath)% [" {( |' T( @
    img_open = Image.open(entry.get()).resize((530,750))% }5 v9 e2 h4 q/ b
    img = ImageTk.PhotoImage(img_open)
) m& q+ k: u1 l* L  o. U    lableShowImage.config(image=img)4 g* d1 ?0 G2 f, T, Q
    lableShowImage.image = img
* h8 P' ^; o) Y4 v2 b+ {    lableShowImage.place(x=30, y=70, width=530, height=750)6 V7 I) ], p+ f- |
    faceRecognition(choosepath)
/ p* e9 l- X4 m( x' x( ]4 ?# P
5 [% ~3 d  K! I" Adef faceRecognition(choosepath):
# U( w- i; i' `    frame=cv2.imread(choosepath)
* x: F! l" j( V; O5 i) x" g  n" j' N    frameRGB=cv2.cvtColor(src=frame,code=cv2.COLOR_BGR2RGB)
; m" e9 v/ O, \7 A    #对摄像头读取的检测人脸) k1 S  k/ F) t5 w) j) l" y
    facesLocate=face_recognition.face_locations(frameRGB)
" ?5 W8 W( A2 V1 W- L    #进行特征编码2 B: j" [. O/ E7 G
    faceEncoded=face_recognition.face_encodings(frameRGB,facesLocate)
. F* ?+ M+ l7 c        #遍历检测的人脸和库中读取的图片进行对比,计算其相似度! G' a, x5 y# K  a# o
    name='unknow'0 U0 V- C3 i% K% x
    for (top,right, bottom,left),face_encoding in zip(facesLocate,faceEncoded):. p0 t8 B4 w$ r4 K
        #进行匹配
, i& Y( [2 L7 S3 Z0 n' z! W        matchs=face_recognition.compare_faces(existsEncodeingList,face_encoding)
% p7 I1 J' F# T- w        #计算相似度
! P6 {9 A* R0 l6 A; H( O+ S0 T        distance=face_recognition.face_distance(existsEncodeingList,face_encoding)
- N( `; L5 U9 f, c/ p4 ?% _, }3 o        lab='unknow'- C* G9 S& E1 Z. T
        for index, item in enumerate(distance):
1 {4 q6 f! v9 P8 b9 x           if item<0.5:
& u% ^  Z* X  q- T. p6 a                if matchs[index]:
8 H! N/ I- d% |0 `! |; H1 c                    #得到匹配到的图片名称与相似度值4 S- z3 s3 |6 G& @) n7 u
                    lab='name:{}; Similarity:{}'.format(classNames[index],item)2 n  o) R5 u1 J+ ]4 b3 Y
                    name=classNames[index]
8 j# d- Y5 J2 n2 q0 E. T/ j                    break$ Y9 R  H; i' p5 L/ O
        #初始化面部捕捉框显示绿色; V! Y  E7 V) c2 Q# k4 B
        color1 =(0,255,0)6 y) f. x4 m* A8 J
        if name =='unknow':5 S2 Y# G: i  r
            #未能识别的时候显示蓝色
6 v3 `4 y% O4 v. E8 l            color1 =(255,0,0)5 P; Y" L% Q8 S$ Y+ W1 H: ]$ h" Q
        #画面部捕捉框
2 I  S' F( B/ S1 P& f. p7 F  q) d# b' P        cv2.rectangle(img=frame,pt1=(left,top),pt2=(right,bottom),color=color1,thickness=3)
9 X: G+ s5 V+ O& l        #在捕捉框上添加匹配到的图片信息7 S" ~/ ~4 r( [( Y" ^1 P7 I
        cv2.putText(frame, lab, (left,top-8),cv2.FONT_HERSHEY_SIMPLEX, 0.7, color1, 2)  ?. ?  H; T& g8 R  l$ j' G. x
        cv2.imwrite('{}/{}.png'.format(img_recognition_path,name),frame)
1 D/ x6 Q( J8 h* F    img_Recognition = Image.open('{}/{}.png'.format(img_recognition_path,name)).resize((530,750))! a& p( M" ?# }; _  ^5 @) {- ?
    img = ImageTk.PhotoImage(img_Recognition)
8 k9 U1 L3 K" `* n  k& e    lableShowImage2.config(image=img)0 T/ ?7 {; T! n2 p& s8 J- J2 W( v3 J
    lableShowImage2.image = img. \. {3 v/ d; [
    lableShowImage2.place(x=630, y=70, width=530, height=750). T: C* j  v' A

" y! n) U% O$ {% z  s% b  G. |if __name__ == '__main__':
4 _3 ^9 z- ?& Q- t! h: ^* H4 t/ c    findExistsEncodeingList(img_path)" z5 [/ r! F, `2 w+ N6 q
    #生成tk界面 app即主窗口8 }- T- L7 z; K/ \) U- [4 W
    app = tk.Tk()  
9 \3 ~/ {& L* C    #修改窗口titile7 L+ V% `5 O  O5 F5 }
    app.title("show pictue")  
; g' y7 u: @& p# V/ u* Y    #设置主窗口的大小和位置3 O3 V. l  d  O% N
    app.geometry("1200x900+200+50")( J/ K  T, h; R- t& p
    #Entry widget which allows displaying simple text.
) f. g" n* a& |, s9 z+ t    path = tk.StringVar()) R6 ^# ?6 O+ T' ^  Q( p+ z' O
    entry = tk.Entry(app, state='readonly', text=path,width = 100)8 X- n3 P% r5 T1 E
    entry.pack()! m, \' b6 `, e( T
    #使用Label显示图片
' T9 |% f) a. J% i, d9 L, [    lableShowImage = tk.Label(app). F3 a7 I( j* F  e# @, P; ~) B
    lableShowImage.pack()- c* [. s# |: {& M2 X
     #使用Label2显示处理后的图片
9 r8 w7 T" q- p" H) X' W' W" [    lableShowImage2 = tk.Label(app)
* w2 {  o4 }3 P( Y    lableShowImage2.pack()( g' }1 `2 X$ D( a
    #选择图片的按钮
% d5 |" O3 Z( o9 f    buttonSelImage = tk.Button(app, text='choose picture', command=choosepic)
: g% m  @! W/ @% \3 z( T    buttonSelImage.pack()
- u6 o: J0 o/ _+ G    app.mainloop()- _) s: L4 |0 B$ Y1 F' b
, O. `2 [- T, A6 y1 C
3.说明+ m/ N4 `3 x# U6 H( F7 }/ @4 g! G4 h
首先我将需要被识别的人脸的照片预设到项目目录的Picture文件夹下,然后创建一个Recognition目录存放识别过的图片,这样方便在一个界面上展示对比结果照片。( l) G" N  V$ m- n2 G
3 S, |' {# X7 u8 [; y7 L6 J) [6 C

7 L8 D2 d- M! |. ?+ }- K/ y8 s8 p. J5 B
其实对比结果也可以不用存,直接将处理后的图片缓存直接展示在界面上,这里需要改一下此处的代码,将上述代码注释掉,然后换成下面的那行,通过数组直接转成图片4 @* m+ Y# ~% k8 b& n

- p: P1 m7 k$ h; _$ }( {3 t
! w9 V  E, f( f- |( X4 G2 m' X# d& e* Q/ X! c8 v
但是效果会存在色彩的失真,效果如下:8 v. F+ z4 h2 v8 |/ C& _+ n

5 T" C' q. R: ?, _; ?7 V" A0 N! `3 C" @$ `; [1 W8 u: `

# W; U* Y) G' C* u) @' D: J" G也尝试了PIL的九种不同图片模式: 1,L,P,RGB,RGBA,CMYK,YCbCr,I,F,最终效果也没达到,大概与我resize((530,750))这个有关,也没继续纠结,有兴趣的同学可以尝试一下。
; V: \: E8 e+ Y* x. x+ D/ d' K  [
这里简单提下PIL的九种不同图片模式:7 g  @4 A  h% z9 Z. G' y- `! R  T) o
1 v, h) @' N# z: {0 i8 B  g
modes        描述# U( o! J% G+ l7 |6 C
1        1位像素,黑和白,存成8位的像素5 f4 G/ W7 }( X8 i  s4 o
L        8位像素,黑白
, j, j3 @- \( s+ B6 @* rP        8位像素,使用调色板映射到任何其他模式
. u( m/ M- s: U& p; Y/ W3 O$ y1 sRGB        3× 8位像素,真彩! o$ G- }, F; g7 n. S& `! M' ^
RGBA        4×8位像素,真彩+透明通道
. Y9 }0 {9 F4 d  tCMYK        4×8位像素,颜色隔离8 w6 C5 n4 v9 t2 `& @
YCbCr        3×8位像素,彩色视频格式! k( ^7 Y2 a6 B. g
I        32位整型像素  u6 H6 N/ q% s4 X* R
F        32位浮点型像素
3 Z( [0 x+ D$ o1 X2 \+ R* u* a4.实现效果
% `7 ]* V' O  L5 m! S- k5 D# v, h( O' M: D1 }4 \# Y: m& U
1 m3 s9 B9 z5 W, s. k, F; J! D9 i: s% _
% {2 g, n$ m/ s+ c. T1 }4 G1 [3 C, o

' S! v2 v" \! b4 [, b 可以实现简单的人脸对比,Similarity代表相似度值,值越小代表人脸与预设的图片越相似。
# R* K- G) ^5 j, t; K————————————————
: Q7 J& b1 G) T8 P% ~版权声明:本文为CSDN博主「物联网_咸鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
. Y6 \& ^! T2 S% _$ @6 k9 B原文链接:https://blog.csdn.net/qq_17486399/article/details/126629288( W$ b* s1 s) C" ?$ U

& h1 @5 K( o+ y: m: U1 {5 s
. Q& ]& J+ |. Q2 a  r* e! N8 c  x




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