数学建模社区-数学中国
标题:
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 L
import numpy as np
1 A+ }! p* F7 p7 d
import 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 A
existsEncodeingList=[]
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 o
def 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 C
def 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 = img
6 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 p
def 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 F
3 R3 V+ r {7 J) r% L* d
modes 描述
+ D1 S o5 O4 B1 K! V
1 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# Z
RGBA 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 j
I 32位整型像素
0 z: J. n- t* i7 j' B
F 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