数学建模社区-数学中国
标题:
Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
[打印本页]
作者:
杨利霞
时间:
2022-9-14 17:07
标题:
Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
& W: n9 E S' X' F& y
: v; ]+ R) E4 R
1.安装包依赖
& P j- {% b! B- J
与上篇通过摄像头动态识别人脸一样,先下载好opencv-python、face-recognition,这里因为使用的是照片对比的方式,特意使用tkinter画了一个简单的GUI方便操作。
1 U% Y. ]2 ]0 o6 k: r
6 u. _1 z% p& ~1 Q7 w# I
在python 3以上版本tkinter是环境自带的,所以这里不需要安装
8 g8 C0 s- d8 e2 A8 u( M; k
& M% l% C9 ] L: U, [
2.代码示例
8 C3 @' v$ I) B1 V( s ?% Z
import os
7 |) [ n/ R% o
import cv2
/ `7 Z( o- Y& H& E) k8 I
import numpy as np
, X* k5 x+ ], { y4 j4 q7 s
import face_recognition
+ J8 o: j4 {( a5 e! `* S
import tkinter as tk
2 D6 y* c% h: |; T
import tkinter.filedialog
4 M$ _7 G/ }2 u! l$ f8 w+ t% e
from PIL import Image,ImageTk
0 e4 d6 q$ _1 g7 r
8 L# h6 k3 ?6 ]) {4 Y; }' ^* g
classNames=[]
+ I; C1 f2 V6 I( {2 i4 E$ H" c& Q
img_path='Picture'
6 L5 E& q5 }: s8 A+ u; }
img_recognition_path='Recognition'
/ {, X/ P- ^" P* q; l" ?
existsEncodeingList=[]
) K* \' a+ z* B/ t
#对人脸集合进行编码进行处理
4 ~9 z7 x/ O4 ]9 x
def findEncodeings(images):
* c! T/ J8 p8 n! v5 a- g
for img in images:
' O! t% r( Z* T0 M; w: ]
#灰度处理
- Y! B: J, t* P4 f
img=cv2.cvtColor(src=img,code=cv2.COLOR_BGR2RGB)
7 I& a* ~$ A! J/ U6 P* Y
#face_encodings对图片对象a_images进行编码并返回数组0位置编码结果
: G) n; [, x7 W, V+ l4 q
encode=face_recognition.face_encodings(img)[0]
6 p4 N$ d8 I7 n3 j
existsEncodeingList.append(encode)
" k! ~. }5 z) ^$ `* D# D
& j( P* J* ^& h8 {
#获取当前存储的人脸编码集合
8 ^+ [- p2 ]& s/ J) ]4 m; M
def findExistsEncodeingList(img_path):
; k5 @! Y: w8 {4 | J/ P
images=[]
3 k8 Z* P0 U: t
#列出已经上传的所有图片
% ^9 P8 ]5 H# U4 \* A% v$ U: M
imgList=os.listdir(img_path)
- @5 \; b+ G7 y! E5 W3 |
#处理存储的图片得到其人脸编码
1 I& [/ }" Z. I3 R
for pic in imgList:
2 J) {( C$ r6 M1 U) I! N) w5 K5 y
img=cv2.imread('{}/{}'.format(img_path,pic))
6 A+ w& _& d' j7 E
images.append(img)
3 T# ?5 T( ` }5 h- z. o
classNames.append(os.path.splitext(pic)[0])
& Q- M @9 b( e9 S% { N. \' @
findEncodeings(images)
$ q* ~7 U _6 G* K
6 p. v6 ~' a& T$ z
#选择并对比图片
. T2 u- ^9 t- O& N( \6 T0 u
def choosepic():
, L' g% U x, ?* F
choosepath = tkinter.filedialog.askopenfilename()
( K: m; K9 V- T' [0 Q2 K# L
path.set(choosepath)
/ e/ T. k: @' h3 K+ |5 U2 b' V) ?
img_open = Image.open(entry.get()).resize((530,750))
. M( D1 G! _, }8 C
img = ImageTk.PhotoImage(img_open)
! D z* Q! E3 |+ O+ e' h
lableShowImage.config(image=img)
$ `$ o" |4 q, c6 ^' k7 i' J
lableShowImage.image = img
- d1 n' r9 p8 e
lableShowImage.place(x=30, y=70, width=530, height=750)
( N: p( i% D5 K
faceRecognition(choosepath)
" g) l1 O3 b+ t i# O; k
) O2 G% q* u& [( z" _
def faceRecognition(choosepath):
+ C! C- F' T* A1 j5 w/ v
frame=cv2.imread(choosepath)
: g: O( |& p0 {
frameRGB=cv2.cvtColor(src=frame,code=cv2.COLOR_BGR2RGB)
: `+ t2 V* g5 B2 _
#对摄像头读取的检测人脸
+ z5 x- T% H* n# b9 [* ]
facesLocate=face_recognition.face_locations(frameRGB)
7 Z& b( K" x" I$ g; j# {, t# G3 p$ D' Y
#进行特征编码
6 ]* ^4 }) Z. U( V0 d) }9 l6 r0 E3 m
faceEncoded=face_recognition.face_encodings(frameRGB,facesLocate)
& [7 F) N8 B t/ I: t6 n
#遍历检测的人脸和库中读取的图片进行对比,计算其相似度
G6 O/ g6 z5 h! z8 X
name='unknow'
2 w. P. Y4 n9 m' f) {- Y8 Z) E6 j
for (top,right, bottom,left),face_encoding in zip(facesLocate,faceEncoded):
4 S0 u" h. Y& m# @+ t2 D9 O1 U
#进行匹配
; q! p5 u+ `. n' `
matchs=face_recognition.compare_faces(existsEncodeingList,face_encoding)
# X3 m5 p* `& X& T) K. Q& x' u
#计算相似度
5 c$ |. G+ C6 J" g
distance=face_recognition.face_distance(existsEncodeingList,face_encoding)
# ?0 Y# ?+ R* C2 _/ N J: @! S
lab='unknow'
* [6 J l, l( v8 q# p
for index, item in enumerate(distance):
0 B! a$ ]% D0 e& y2 B" {8 T
if item<0.5:
# b0 Z/ k" N# h1 P, R* m
if matchs[index]:
8 Q1 L/ G' J) r2 p
#得到匹配到的图片名称与相似度值
' w6 k, F6 n. c2 j# m( M% U0 z9 d
lab='name:{}; Similarity:{}'.format(classNames[index],item)
2 u' C V7 l2 ]# E
name=classNames[index]
5 Y a0 G( e h+ J
break
4 K( \4 @, a+ w
#初始化面部捕捉框显示绿色
1 x/ Q1 E# C- T/ ~, k" {, [
color1 =(0,255,0)
1 l3 T! v7 \( C% p, G
if name =='unknow':
6 H2 g7 U; m- s# g" c4 g! i, w5 M/ w) L H
#未能识别的时候显示蓝色
+ R- B. J# }. N7 A% l
color1 =(255,0,0)
, E( ?, [8 q0 E5 ]
#画面部捕捉框
- \4 @, z* m/ e9 A. G! l! {. g
cv2.rectangle(img=frame,pt1=(left,top),pt2=(right,bottom),color=color1,thickness=3)
& s1 Z, ?0 X$ C+ H" E( S0 e4 k
#在捕捉框上添加匹配到的图片信息
) {. V8 D* p" m- S0 f9 x; e- g$ ^& A+ u
cv2.putText(frame, lab, (left,top-8),cv2.FONT_HERSHEY_SIMPLEX, 0.7, color1, 2)
, W3 l. p: ~ x* _3 u
cv2.imwrite('{}/{}.png'.format(img_recognition_path,name),frame)
8 {: _; W% x0 B9 p" j% \( M$ j
img_Recognition = Image.open('{}/{}.png'.format(img_recognition_path,name)).resize((530,750))
6 ~3 \4 q! V, L7 i
img = ImageTk.PhotoImage(img_Recognition)
2 K6 M- d% @; C c- ?$ O5 i
lableShowImage2.config(image=img)
7 V, i& ~9 n5 n+ V1 r- Q2 c8 \$ s
lableShowImage2.image = img
8 H1 d3 f4 H$ ]4 I6 q- ^
lableShowImage2.place(x=630, y=70, width=530, height=750)
" P8 U" s# ~$ x& i; ?$ |
" f* [" S2 w9 p
if __name__ == '__main__':
* K4 t* J! w8 ~, @' c3 W a
findExistsEncodeingList(img_path)
v7 k+ Y2 {) ]6 `7 D; J' F/ X0 E
#生成tk界面 app即主窗口
2 K5 F0 P5 D. s. M Q) h
app = tk.Tk()
3 @! ~9 U1 I" G& r% R% x$ s( ~
#修改窗口titile
- t6 N5 v2 }6 H
app.title("show pictue")
* _* t* ?, X1 P6 g
#设置主窗口的大小和位置
7 x& d1 ~# `, h2 |
app.geometry("1200x900+200+50")
. D) F7 ]/ [" i. w, ~9 K3 b
#Entry widget which allows displaying simple text.
) `& j3 ~, `. u B6 s
path = tk.StringVar()
, B8 `( V B% \- k
entry = tk.Entry(app, state='readonly', text=path,width = 100)
: |' o. g, t1 k0 V& Q+ ^" r0 r
entry.pack()
6 G ]& U7 z8 u0 d
#使用Label显示图片
7 H# f& R$ C$ A3 ?
lableShowImage = tk.Label(app)
# O. c6 F9 k9 h* S
lableShowImage.pack()
3 |5 X5 ^& {6 f+ }% ^; A$ h
#使用Label2显示处理后的图片
6 C6 D$ ]5 G; F W, M
lableShowImage2 = tk.Label(app)
' U! D" d3 T. K7 z; i# x
lableShowImage2.pack()
8 r: y/ p1 A" m8 e
#选择图片的按钮
# G ?" E# g$ q7 W7 Y! K( l& m
buttonSelImage = tk.Button(app, text='choose picture', command=choosepic)
4 `% ]& M& w( t
buttonSelImage.pack()
3 N+ y6 Y) f9 j; ~1 f
app.mainloop()
, ~1 a0 q% J4 L2 p+ C
4 c$ H; V& O1 a& w
3.说明
9 Y. e8 j/ _3 @# {- x
首先我将需要被识别的人脸的照片预设到项目目录的Picture文件夹下,然后创建一个Recognition目录存放识别过的图片,这样方便在一个界面上展示对比结果照片。
/ {- F7 @9 E5 h' }' b K/ l
0 z9 \4 ?" U2 M/ b) |2 S/ R
0 I8 S5 v E+ J* X( f) M
- E- n8 o4 Y9 g. Z
其实对比结果也可以不用存,直接将处理后的图片缓存直接展示在界面上,这里需要改一下此处的代码,将上述代码注释掉,然后换成下面的那行,通过数组直接转成图片
3 _% }+ ?; k* M( e2 B( A" h% `, k
( a6 l, g) p/ J- t2 q
% ~+ F, ?) h( J$ @, E6 D( S
% h* f. F4 s( ]
但是效果会存在色彩的失真,效果如下:
3 Q' |9 z8 w: @- c. l- y
! E+ Z# G3 x, A6 }' S1 ~
, s8 A/ k# V0 {+ Y0 J$ V4 a1 t
6 d( w4 E" K8 b2 Y
也尝试了PIL的九种不同图片模式: 1,L,P,RGB,RGBA,CMYK,YCbCr,I,F,最终效果也没达到,大概与我resize((530,750))这个有关,也没继续纠结,有兴趣的同学可以尝试一下。
9 N- O- J: I. B2 t+ X
) c7 i6 y ~3 V; Q/ n( u
这里简单提下PIL的九种不同图片模式:
; v5 R; n, Y( _4 _7 a4 D# P
" Y# C2 k S- c% A- c5 u, g
modes 描述
% W" a8 Z7 F# \" }" T
1 1位像素,黑和白,存成8位的像素
# [. l8 }- [6 a+ |7 V5 z' n
L 8位像素,黑白
" E0 m0 p: ]/ M R
P 8位像素,使用调色板映射到任何其他模式
* Y- b' f4 b0 [3 h" ^$ l4 N" R2 ^ U$ D
RGB 3× 8位像素,真彩
7 f: U) X2 e. q! b4 N
RGBA 4×8位像素,真彩+透明通道
) ~, C) I, c7 }- p B" ^9 d
CMYK 4×8位像素,颜色隔离
/ J5 u" A- A- p4 I0 _
YCbCr 3×8位像素,彩色视频格式
/ y& c' H: `* X y8 O8 A
I 32位整型像素
; |! Y8 e& c$ k
F 32位浮点型像素
8 T. M% A+ A4 }. }8 I
4.实现效果
: e, [9 _& Q ]% [3 L: W' `6 l& q
# H, z# }: z. U# }6 h1 s) \0 {
0 S: o: j l% c5 j0 \0 p
# H- b9 z0 E# b$ @1 Z7 H
% f; C& J+ U2 e# N
可以实现简单的人脸对比,Similarity代表相似度值,值越小代表人脸与预设的图片越相似。
! l) w- u2 I7 l4 \% l Y* e# z5 \4 z
————————————————
, R' w: x) |$ s1 Q% w9 j! ?
版权声明:本文为CSDN博主「物联网_咸鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
/ _/ ?; ]1 B4 i& E# m+ B
原文链接:https://blog.csdn.net/qq_17486399/article/details/126629288
* I) {) |; G, i' g/ T& n/ M5 T5 w7 H
5 g+ C3 W! O. O' }: e2 L2 y3 s
0 M$ Y( B' P5 H" H) W
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5