数学建模社区-数学中国
标题:
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 cv2
4 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' e
import tkinter as tk
; {6 I, x. ^. o2 x/ C
import tkinter.filedialog
: y; E, w" F1 W0 a
from 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% n
img_path='Picture'
: q5 {' `; `* k9 M
img_recognition_path='Recognition'
7 a4 y+ B4 w' H# r
existsEncodeingList=[]
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& V
def 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' z
if __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 ?; y
3.说明
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' L
3 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 n
modes 描述
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' G
P 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 w
8 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