数学建模社区-数学中国
标题:
Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
[打印本页]
作者:
杨利霞
时间:
2022-9-14 17:07
标题:
Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
) c2 D1 e) n: _% n* ]. ~; L d3 u$ N
, H H. F! u- r" L( G, r: F
1.安装包依赖
& u: S) b9 T6 I2 Y( X$ ^
与上篇通过摄像头动态识别人脸一样,先下载好opencv-python、face-recognition,这里因为使用的是照片对比的方式,特意使用tkinter画了一个简单的GUI方便操作。
) W7 A( k1 W& V( g$ [3 ^/ i! h
+ s, S$ N, T6 I' z+ M% A* e; [
在python 3以上版本tkinter是环境自带的,所以这里不需要安装
7 @1 q$ F3 s) V: x
0 x7 I- @$ I: b" I) A
2.代码示例
% o$ L* k' }* T# E$ ^7 d( B7 H ?7 T6 W
import os
! m( y! ]0 [* }5 D
import cv2
K$ d8 ~8 w3 O- j' D
import numpy as np
2 ?$ g! i1 j* |! l# z7 F! ]
import face_recognition
/ B- T1 i4 b& R6 H# z. u! @. q
import tkinter as tk
, J; S o& Q2 ~9 c ?/ P' S4 R
import tkinter.filedialog
) |5 w# {" N0 T7 v
from PIL import Image,ImageTk
- m' O! E7 Q& q, J
. C, k, ] c2 K! N2 h! Q) i
classNames=[]
% j* J3 f. C: ], r) e
img_path='Picture'
3 l$ S1 _2 W0 ~2 _8 I+ [
img_recognition_path='Recognition'
- w7 E$ {" a5 Q3 L
existsEncodeingList=[]
" ?0 o% u0 t1 A% m5 b
#对人脸集合进行编码进行处理
3 [1 \6 o6 G. r, F4 Q
def findEncodeings(images):
' ]) T( J1 f R" R
for img in images:
, T" C$ @2 w' O: l5 V0 j* k) _
#灰度处理
) ]2 J9 {; P2 \ k* {8 U7 z5 L
img=cv2.cvtColor(src=img,code=cv2.COLOR_BGR2RGB)
- C/ W+ U( S) X2 [, e: t% A
#face_encodings对图片对象a_images进行编码并返回数组0位置编码结果
1 E( s6 x, d& F
encode=face_recognition.face_encodings(img)[0]
0 |' [! g8 i$ V M
existsEncodeingList.append(encode)
) Z% f4 d* c- e0 G5 S% f( l A& W0 Y
+ ?% l; v6 n0 q4 Z$ K' F+ N! d
#获取当前存储的人脸编码集合
1 S* C6 y& Q5 S
def findExistsEncodeingList(img_path):
* y8 X6 s4 I$ w# U* _! [ r" b
images=[]
9 S* e) T2 G3 F. G
#列出已经上传的所有图片
9 K5 H( E8 m! L1 i) E# L
imgList=os.listdir(img_path)
$ {# `% Y& T1 {9 S* |4 g, g2 p
#处理存储的图片得到其人脸编码
7 ^9 [* o4 x# f; m
for pic in imgList:
0 V3 e- @( y# X- U3 A- I
img=cv2.imread('{}/{}'.format(img_path,pic))
9 i. r! X* Q, w; a1 j, M; z
images.append(img)
# g( K3 ]$ \ b9 I
classNames.append(os.path.splitext(pic)[0])
- a' f0 S+ g, g- T
findEncodeings(images)
. m* B7 G% P0 V! A9 L: t8 M8 c, T3 y
7 }+ C( c% z; W# F; M
#选择并对比图片
: p& v) l% p3 O; F& Y- Y
def choosepic():
( E" Z$ z8 b6 I) l
choosepath = tkinter.filedialog.askopenfilename()
! F: @. d* G3 w5 I
path.set(choosepath)
! a2 H' Q) \9 ]* M. B
img_open = Image.open(entry.get()).resize((530,750))
; `, O. E! r2 p8 ^5 {! K6 t, B. r
img = ImageTk.PhotoImage(img_open)
0 Q8 b3 V: @% t( C" U# }
lableShowImage.config(image=img)
# e# Q( v( d* d
lableShowImage.image = img
! i9 ^' b* O+ C, [9 K. c
lableShowImage.place(x=30, y=70, width=530, height=750)
) X: z" K7 d2 R: D' H
faceRecognition(choosepath)
2 g) v2 Q8 f, B% S8 C8 ^7 }4 p1 E
# u$ L- Q0 `( {8 f2 t' @
def faceRecognition(choosepath):
' O! q& Y0 k2 l- Z& Z* C ~" f
frame=cv2.imread(choosepath)
% Y2 M+ T5 m2 |4 j
frameRGB=cv2.cvtColor(src=frame,code=cv2.COLOR_BGR2RGB)
& I5 h. P3 Y1 S4 ^ `4 Q
#对摄像头读取的检测人脸
! W' T# F+ M0 {$ B; R
facesLocate=face_recognition.face_locations(frameRGB)
3 p+ o4 P4 _" @5 f& ]
#进行特征编码
; g8 U- y/ p+ Z2 ^- p* [
faceEncoded=face_recognition.face_encodings(frameRGB,facesLocate)
+ M3 c* m O2 z! b
#遍历检测的人脸和库中读取的图片进行对比,计算其相似度
5 T9 g9 W, |6 J ^' t* d8 U
name='unknow'
6 f( e7 [! z4 @% z# Q' }- p [
for (top,right, bottom,left),face_encoding in zip(facesLocate,faceEncoded):
5 N; V8 A6 U& k) i+ e8 n
#进行匹配
) C4 U2 G& y0 n3 c' @
matchs=face_recognition.compare_faces(existsEncodeingList,face_encoding)
) l3 x( g# e& f9 d# R, [+ v! G% ^
#计算相似度
8 F/ D4 R5 b- O5 L) a* `$ R
distance=face_recognition.face_distance(existsEncodeingList,face_encoding)
( o5 {! ~" E& L0 |6 W
lab='unknow'
5 ]6 _5 C' a5 G8 D+ R* g4 ~
for index, item in enumerate(distance):
4 a3 f- b+ h. x5 n5 k; t
if item<0.5:
0 D8 b) k! P; V; H; d
if matchs[index]:
" n. A0 C- S* e5 L# w/ k
#得到匹配到的图片名称与相似度值
2 {2 F* j4 {" n3 f+ b! p& W9 }. i
lab='name:{}; Similarity:{}'.format(classNames[index],item)
( }7 q3 G3 }$ N( l9 ?( Q
name=classNames[index]
! l0 N$ J: r2 ?. h' l' U; R. B7 O
break
+ h+ a9 ]4 k. V8 [' e
#初始化面部捕捉框显示绿色
0 D0 o8 |& Y( I4 N
color1 =(0,255,0)
3 ]: S4 u0 v: E
if name =='unknow':
6 d) j" n% {0 R" V) e. J
#未能识别的时候显示蓝色
+ P5 H7 V' A7 }( J$ ?, B: ~: v& P
color1 =(255,0,0)
* |2 q) [- K2 F; `7 a
#画面部捕捉框
0 u: P# v" L1 S$ \5 v$ I/ u
cv2.rectangle(img=frame,pt1=(left,top),pt2=(right,bottom),color=color1,thickness=3)
. E. [* f& q/ E8 L1 [" C) L- ]
#在捕捉框上添加匹配到的图片信息
: I3 e3 w1 e& z* r; W
cv2.putText(frame, lab, (left,top-8),cv2.FONT_HERSHEY_SIMPLEX, 0.7, color1, 2)
$ T$ y. @, K8 F2 M* r; B! \
cv2.imwrite('{}/{}.png'.format(img_recognition_path,name),frame)
/ ?' Q1 k: `- c5 a" i# d
img_Recognition = Image.open('{}/{}.png'.format(img_recognition_path,name)).resize((530,750))
U, |: j3 Q* Y; h
img = ImageTk.PhotoImage(img_Recognition)
# z" F) F$ I' s; b U
lableShowImage2.config(image=img)
1 s6 D' F: e7 l' p9 Z7 I
lableShowImage2.image = img
% H4 V5 h3 g) s0 @# V
lableShowImage2.place(x=630, y=70, width=530, height=750)
& {! L* S2 A/ u
9 i5 M' h. z* H. h0 x
if __name__ == '__main__':
9 k% z Q# H7 J: J
findExistsEncodeingList(img_path)
/ N. Q$ M4 R; l- g4 @8 C; `/ e
#生成tk界面 app即主窗口
2 w$ M! j7 G" [8 O0 k, n$ W
app = tk.Tk()
, G5 y, J2 l- p. F, Q( G4 p) i
#修改窗口titile
7 } n" I8 t( g# z% X
app.title("show pictue")
; c7 i2 k1 \0 e K/ R: {2 m
#设置主窗口的大小和位置
0 ?; i" a# y" l0 l5 l! ?1 U6 e: w
app.geometry("1200x900+200+50")
! c) t: C4 ]8 O( b8 \
#Entry widget which allows displaying simple text.
3 j$ V( R" W- Y
path = tk.StringVar()
/ W" e& h2 O0 W0 T
entry = tk.Entry(app, state='readonly', text=path,width = 100)
" ^" z# m1 v' T# x" R! A6 G* F
entry.pack()
$ \3 Y' S0 M4 D3 B; @ O
#使用Label显示图片
5 d9 T: I9 M" I' h s5 B2 @1 z1 ^
lableShowImage = tk.Label(app)
$ U: {) z8 Y3 k1 R6 x+ r! M b
lableShowImage.pack()
, h7 @( G1 ~ f5 h' {
#使用Label2显示处理后的图片
# d/ ]3 a- S1 p: Z3 x
lableShowImage2 = tk.Label(app)
, G8 u5 w" I. S3 c1 ?2 w+ F! m$ q8 }; z5 H
lableShowImage2.pack()
, u! X5 e6 @9 m0 t% B+ |
#选择图片的按钮
* y& R2 @. ~5 X! z/ a: V
buttonSelImage = tk.Button(app, text='choose picture', command=choosepic)
# s1 l& u* M+ c! c1 t
buttonSelImage.pack()
; N0 y9 z0 P2 s( {7 N7 e! [
app.mainloop()
; G, d' c* |+ E' u7 P1 Z
. W- f' n( Y2 P. m* B' {) E
3.说明
1 B. J9 Z' L& L3 \( K
首先我将需要被识别的人脸的照片预设到项目目录的Picture文件夹下,然后创建一个Recognition目录存放识别过的图片,这样方便在一个界面上展示对比结果照片。
1 P2 G, p" i& p* f" p3 t+ D& ~
3 I2 z. }# G! t- H+ ~3 r# H0 N
3 D: b3 E3 O/ y3 w! W( p
+ ?; O( M' ?7 i. F) {
其实对比结果也可以不用存,直接将处理后的图片缓存直接展示在界面上,这里需要改一下此处的代码,将上述代码注释掉,然后换成下面的那行,通过数组直接转成图片
* k9 H; P+ S+ W7 w
( |: `8 ~: X; v8 i+ U/ I* ]" k
1 X" O: q/ |- Q( c& y2 u4 t
( _& O" {2 Z% ]& e# g: \6 y4 S, [
但是效果会存在色彩的失真,效果如下:
, ~; ~; b4 ^: Z/ k; x2 d# ]/ i
9 s8 M& t# \# ^5 q
7 J- K5 i' k# C7 t) L) K0 u
' @; b& T, [3 f; ?' g, m
也尝试了PIL的九种不同图片模式: 1,L,P,RGB,RGBA,CMYK,YCbCr,I,F,最终效果也没达到,大概与我resize((530,750))这个有关,也没继续纠结,有兴趣的同学可以尝试一下。
( S9 c" C+ ?# _! C! L. H6 X
) T& }- w' R! x q
这里简单提下PIL的九种不同图片模式:
! u& J0 G& ^1 V+ _
* r: ] [3 v& n
modes 描述
m; t- s% c: Q) V) ~0 N
1 1位像素,黑和白,存成8位的像素
. ^% r8 o- l! C% u! N- w/ [9 b& _9 N
L 8位像素,黑白
! N2 j5 N, ?; E) y
P 8位像素,使用调色板映射到任何其他模式
2 k+ S5 `8 E6 {! K! B# x! `) Y' ]
RGB 3× 8位像素,真彩
& u- y! c+ B- P* V
RGBA 4×8位像素,真彩+透明通道
?" Q, L# F, `( }
CMYK 4×8位像素,颜色隔离
+ c3 f2 x2 [3 G1 s; W9 P% _. ?4 z
YCbCr 3×8位像素,彩色视频格式
" z/ i7 I: k, m/ p) D Z
I 32位整型像素
' E6 R( K9 L: F3 t
F 32位浮点型像素
% C- r1 H. n, p ^" S
4.实现效果
4 a& v3 Q, J. M# p; }* b+ ?
+ l3 v4 s8 M4 j
( ^! L" m; w! ~2 z+ o
+ N6 ~* O, U+ B* X0 m, A2 {" B- k) @
" e2 X1 L) v/ U* g
可以实现简单的人脸对比,Similarity代表相似度值,值越小代表人脸与预设的图片越相似。
8 W% j' W0 Q8 u. u# n2 H8 }& ^
————————————————
$ Z4 ~& \5 X' ]4 p6 M! z. V2 I
版权声明:本文为CSDN博主「物联网_咸鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
" @! d) C' n/ B3 \. w5 j
原文链接:https://blog.csdn.net/qq_17486399/article/details/126629288
. |0 b# e, i- |- `9 [/ X
2 o8 z3 }5 Q: S: q: f
/ h u0 _. c! G6 f% O6 O& ^
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5