数学建模社区-数学中国
标题:
Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
[打印本页]
作者:
杨利霞
时间:
2022-9-14 17:07
标题:
Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
5 p# t* A- y, v! ]/ z
- t1 Q9 D. N5 ]- D; j; U0 U
1.安装包依赖
/ D9 d2 G0 E, b- i0 C
与上篇通过摄像头动态识别人脸一样,先下载好opencv-python、face-recognition,这里因为使用的是照片对比的方式,特意使用tkinter画了一个简单的GUI方便操作。
* m4 a; S0 R. m+ W
! [( z) O% S- t" @5 K
在python 3以上版本tkinter是环境自带的,所以这里不需要安装
% H) {+ h1 E& I1 c
8 w5 w3 a+ x0 a
2.代码示例
3 v6 ~( z3 s$ h. C/ R5 B
import os
( | T8 n. m* w$ n; W5 @/ c0 N
import cv2
: g6 _# w" K+ P9 u) D/ u- h
import numpy as np
) g, I9 r( S2 J7 f! y% m( z
import face_recognition
h. ~& R" V. _3 T& H+ |
import tkinter as tk
$ Z( Q) Y" t2 O& q$ C
import tkinter.filedialog
( \7 S% \8 I; l/ W' N. X
from PIL import Image,ImageTk
! ]$ @6 a: o0 H7 |2 O4 d
- h& e& s e" Q# J
classNames=[]
2 f/ `% \. X* R! c/ E
img_path='Picture'
: G: a _9 y8 n3 U/ H! p
img_recognition_path='Recognition'
$ n. t5 D" y* _* ~1 ?, @
existsEncodeingList=[]
/ D& x# _- @2 q4 T. R
#对人脸集合进行编码进行处理
8 U; l% {: D. Q+ f3 C5 E) e4 n* a( Q
def findEncodeings(images):
% ]9 Z+ a" ^% u
for img in images:
* ]* R6 u- x9 Y& T# [% P2 I+ _
#灰度处理
1 H Y' C- d( g8 ]" A" D- ?. P
img=cv2.cvtColor(src=img,code=cv2.COLOR_BGR2RGB)
6 Q# |: N- R5 t$ M: T. v
#face_encodings对图片对象a_images进行编码并返回数组0位置编码结果
( P2 u" _) ^) q* _: l# R9 F( s
encode=face_recognition.face_encodings(img)[0]
3 P$ Z/ t8 ^; N* i+ o, m. V
existsEncodeingList.append(encode)
; l( F+ Z5 Q) v j" G& \
) d9 }2 ^1 j) m* f) D
#获取当前存储的人脸编码集合
# G2 |; i3 \5 w2 F. H' v; @
def findExistsEncodeingList(img_path):
* n. l/ l: Z" ^: Y6 p
images=[]
7 D2 N7 [3 R+ l5 i! W+ x7 m% P
#列出已经上传的所有图片
# d$ t* f- t% @. V5 |$ u
imgList=os.listdir(img_path)
4 p6 V/ m! k7 Z4 t5 s
#处理存储的图片得到其人脸编码
, ~! r5 I' c) O
for pic in imgList:
0 q5 o" h/ I7 v: r; C" d
img=cv2.imread('{}/{}'.format(img_path,pic))
- E( G+ i6 r l8 Q( ?5 g9 T# t
images.append(img)
2 p- C* K" B! ~. g$ n! D9 W
classNames.append(os.path.splitext(pic)[0])
: _7 y Y; c, x. @1 G9 x C9 \
findEncodeings(images)
- v9 o; C# n, }" ^
" N8 X" X& D2 }) }4 j8 M4 P# j
#选择并对比图片
# m A4 L1 K6 v9 Y2 v
def choosepic():
3 d" N- Z! g9 C
choosepath = tkinter.filedialog.askopenfilename()
* b) W4 N1 w' \& }* U; ~
path.set(choosepath)
6 A, i' ^2 i) S
img_open = Image.open(entry.get()).resize((530,750))
$ Q% X& {1 x- \9 ^" G
img = ImageTk.PhotoImage(img_open)
' y9 r2 M3 k% `% p* m) x* U9 V
lableShowImage.config(image=img)
3 Y1 j* D! r: W) Q4 G
lableShowImage.image = img
6 H: Z& q" S' C) z5 T
lableShowImage.place(x=30, y=70, width=530, height=750)
4 x+ ^/ ~" e4 K) Z/ D# n
faceRecognition(choosepath)
! N& m% X% T8 M6 q1 ?5 D0 N
- M! U5 ]9 Z- c! b4 F# N# T
def faceRecognition(choosepath):
8 W# y, W0 `( N
frame=cv2.imread(choosepath)
6 j, `; M3 r) ?. Y: b0 p& m
frameRGB=cv2.cvtColor(src=frame,code=cv2.COLOR_BGR2RGB)
X! G* _! d& Z, X
#对摄像头读取的检测人脸
3 S1 P5 W7 E: @5 E, k7 U2 H% X
facesLocate=face_recognition.face_locations(frameRGB)
o+ E2 y" i0 {$ r5 a# Q. Y7 Q
#进行特征编码
4 ]: c( Z" L8 l( ]4 I6 C
faceEncoded=face_recognition.face_encodings(frameRGB,facesLocate)
3 a: m8 y6 n9 h" n# w' p
#遍历检测的人脸和库中读取的图片进行对比,计算其相似度
P7 ?' f8 U4 |6 o0 q c4 R
name='unknow'
# t) E: h4 z/ W2 M3 |9 z
for (top,right, bottom,left),face_encoding in zip(facesLocate,faceEncoded):
3 I9 m. P3 e9 L# f
#进行匹配
+ l$ A. ?* S" c! z9 c
matchs=face_recognition.compare_faces(existsEncodeingList,face_encoding)
7 l, g+ G" e2 H4 a, ~/ ^+ z
#计算相似度
+ S) Z8 D/ F5 ~& Q- e; @
distance=face_recognition.face_distance(existsEncodeingList,face_encoding)
9 u1 s$ J( H2 X* w" b
lab='unknow'
# C% G! w8 S6 C9 ~3 y
for index, item in enumerate(distance):
) V8 r* H2 D1 \# T) w4 N8 a
if item<0.5:
4 j# f. o* q+ w; A# @6 \7 s
if matchs[index]:
5 i k7 f3 k X/ C# h% ^6 H
#得到匹配到的图片名称与相似度值
! X: e* X( A! w( ^3 [' `
lab='name:{}; Similarity:{}'.format(classNames[index],item)
2 X3 V. A! D/ u l' ~$ q: C8 {+ g
name=classNames[index]
/ ?2 x+ Z- V8 a- g# v
break
/ [! x: j2 ?+ s P @5 f3 j
#初始化面部捕捉框显示绿色
; I ^0 K, h4 z" [; z: X1 G# C# [
color1 =(0,255,0)
" H9 L& X4 o; W0 V2 `8 g5 F8 A; c! O
if name =='unknow':
7 C: f! F4 g( g' K D3 ^
#未能识别的时候显示蓝色
6 c, t0 {# z Q6 f# a6 a+ [
color1 =(255,0,0)
! I6 K: {4 J1 `9 o
#画面部捕捉框
- D$ P5 H% a% T4 L) Y/ d0 b
cv2.rectangle(img=frame,pt1=(left,top),pt2=(right,bottom),color=color1,thickness=3)
8 ]/ s9 t. @; W9 @
#在捕捉框上添加匹配到的图片信息
# r) o: ?) y: N" J/ J
cv2.putText(frame, lab, (left,top-8),cv2.FONT_HERSHEY_SIMPLEX, 0.7, color1, 2)
4 |2 e5 I8 Z) h0 s4 g
cv2.imwrite('{}/{}.png'.format(img_recognition_path,name),frame)
3 c( t ]1 g( c
img_Recognition = Image.open('{}/{}.png'.format(img_recognition_path,name)).resize((530,750))
& z( \; s0 J9 s& i" H
img = ImageTk.PhotoImage(img_Recognition)
. x0 ?7 [' ?9 v* V
lableShowImage2.config(image=img)
6 {% h" E5 |& T/ C Y
lableShowImage2.image = img
- S! H. n4 z# D$ r- z1 @6 P% L& d
lableShowImage2.place(x=630, y=70, width=530, height=750)
* f9 R' u* ~# B7 Q0 q* t
2 T% J; c6 Z8 O
if __name__ == '__main__':
4 W: p$ o9 o: |
findExistsEncodeingList(img_path)
0 a* V' h) L) ~8 j6 J% N( b
#生成tk界面 app即主窗口
) a- [) e9 F0 O5 Z8 M: H. _: q
app = tk.Tk()
. _6 ^0 O8 g. M3 d- ?. b4 h* J& N6 b
#修改窗口titile
0 ^3 l( v- n l; R* N6 |
app.title("show pictue")
7 Y! U( S T3 S
#设置主窗口的大小和位置
4 G# [4 \) w8 l
app.geometry("1200x900+200+50")
( h3 J2 c- F" e% W% k) Z1 @
#Entry widget which allows displaying simple text.
% J1 h [1 P- [- ?6 o0 t
path = tk.StringVar()
: S v) C6 S/ |; M3 ~. @4 _
entry = tk.Entry(app, state='readonly', text=path,width = 100)
& V9 U1 V' Q' O# K" U- u) D2 q
entry.pack()
; ^7 g4 {% A0 \% d/ D L7 t
#使用Label显示图片
# f3 b, V& K' x, k
lableShowImage = tk.Label(app)
5 m4 W$ b% W _1 x, @& @) H- Q
lableShowImage.pack()
4 p x5 L$ q5 @5 V
#使用Label2显示处理后的图片
* B$ ?' c) _5 W! N( R
lableShowImage2 = tk.Label(app)
% ?) Z8 U& Y# G2 g" y
lableShowImage2.pack()
4 ]) I0 X. Q9 p; [) Q* s+ U. S. i* H
#选择图片的按钮
/ k% C( q7 ?! j0 n: r( v+ i h, q
buttonSelImage = tk.Button(app, text='choose picture', command=choosepic)
5 t- \& R. |$ E' l: L+ }# P K
buttonSelImage.pack()
5 O0 _9 L2 ]- I- q6 W7 E5 U
app.mainloop()
8 s8 C$ l4 C4 R- ?; [) A5 j
- t3 M- r5 X1 f+ d8 ]2 ]2 N
3.说明
8 r/ N9 F$ c5 M6 |
首先我将需要被识别的人脸的照片预设到项目目录的Picture文件夹下,然后创建一个Recognition目录存放识别过的图片,这样方便在一个界面上展示对比结果照片。
! P& g. D+ z, l8 J. N& Y
, B/ j' o/ C$ h! m8 Z: _4 w) {
3 B3 d/ j. Z, f* `+ H2 S
. i7 S1 Y' o% j3 |4 a
其实对比结果也可以不用存,直接将处理后的图片缓存直接展示在界面上,这里需要改一下此处的代码,将上述代码注释掉,然后换成下面的那行,通过数组直接转成图片
; j3 s- l8 h5 b8 H3 H% q a
( S6 ]$ O1 a; s \
2 }0 ~+ X @5 J+ Q$ F! O( y; N
[6 L( M4 g$ h* t% {( L
但是效果会存在色彩的失真,效果如下:
5 E9 J0 o( e4 l" m- n. J
& V$ [1 A% d+ D* K
' x2 r% A+ Y9 {7 {
8 @" e. e# Q3 K2 M' U9 S! E
也尝试了PIL的九种不同图片模式: 1,L,P,RGB,RGBA,CMYK,YCbCr,I,F,最终效果也没达到,大概与我resize((530,750))这个有关,也没继续纠结,有兴趣的同学可以尝试一下。
% \9 `, ?" e/ {3 z4 n4 O
& U! X1 m1 W$ S# W7 Y! A
这里简单提下PIL的九种不同图片模式:
8 `7 H; H$ i3 L1 k0 n3 |) y* u
+ X" k. I! J$ T) P |
modes 描述
4 U$ G; p+ m# I$ V
1 1位像素,黑和白,存成8位的像素
$ A* k5 R ^7 G6 ^( s( E
L 8位像素,黑白
) p3 h+ ~$ G B+ b8 v6 v
P 8位像素,使用调色板映射到任何其他模式
$ N* ], B% }9 Z; k& K1 \# P
RGB 3× 8位像素,真彩
V3 _+ F; _ O \- d
RGBA 4×8位像素,真彩+透明通道
! p7 V- F8 G D% U, V7 j
CMYK 4×8位像素,颜色隔离
6 G5 g6 C6 s4 {1 g/ x6 ^4 w
YCbCr 3×8位像素,彩色视频格式
9 R# }8 A- G8 n
I 32位整型像素
* b8 T0 {, I; }& q0 {& ]2 h
F 32位浮点型像素
! n. p' u( x$ e* v3 B3 x
4.实现效果
' k# k" _% l: q% x) q7 q$ c, ~
( j5 ^. H0 W' p% |: b
9 H7 b- |1 F) o' n
" o# f4 c( t7 L* j
7 s% W) j* o% ?' [
可以实现简单的人脸对比,Similarity代表相似度值,值越小代表人脸与预设的图片越相似。
$ G8 K$ _. N- X* B( W1 p' o" Z
————————————————
/ A9 f2 X1 w, V- }0 P+ r- E- g+ e
版权声明:本文为CSDN博主「物联网_咸鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
4 i; D6 Z+ J4 i1 N
原文链接:https://blog.csdn.net/qq_17486399/article/details/126629288
( E* f. ` f) V
* t2 G: V' R! O! A9 U
) x3 s. l) U- ]/ L2 { U2 M
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5