数学建模社区-数学中国
标题:
Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
[打印本页]
作者:
杨利霞
时间:
2022-9-14 17:07
标题:
Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
+ N/ N' G" O" b: q J
6 b' n6 h3 \* E1 | h% V
1.安装包依赖
6 ~1 _9 B0 t" p9 W, y9 A! q+ j
与上篇通过摄像头动态识别人脸一样,先下载好opencv-python、face-recognition,这里因为使用的是照片对比的方式,特意使用tkinter画了一个简单的GUI方便操作。
( X2 q9 `/ o9 h
- c# j& O2 R# c" ]9 t/ S
在python 3以上版本tkinter是环境自带的,所以这里不需要安装
( A. y" B- W5 H: T
: }8 @& {9 A/ P3 Q) e# g% k/ A* I
2.代码示例
% ], {+ u2 o6 M; R9 a; H
import os
- ^9 e7 M- U$ G$ a3 A
import cv2
* t- f- o8 E1 U; U1 j4 ~) k, [7 `
import numpy as np
4 C2 Y. B! C. P) K6 R
import face_recognition
" `' [$ A3 V$ B1 H4 n1 ?$ s3 B
import tkinter as tk
1 g! s" w2 {' b- h, B
import tkinter.filedialog
) _ l ?6 B% k- {
from PIL import Image,ImageTk
' Q1 Z* Z4 \6 [6 n
% O- {+ f$ w5 D4 p; B
classNames=[]
" [* m" R: ?+ Y0 d' C
img_path='Picture'
& K: G+ g+ c% a* S
img_recognition_path='Recognition'
2 a& g9 P2 m1 ^' f- u' x3 s B
existsEncodeingList=[]
( c* O6 S& A9 `- B* ?8 j
#对人脸集合进行编码进行处理
, r* O% P! `- E; S J2 m
def findEncodeings(images):
! Y9 K, v, c. d# _
for img in images:
: d! x9 M& q4 C7 t4 B
#灰度处理
" R. q* Z8 a4 t% ]# `7 D& c8 V
img=cv2.cvtColor(src=img,code=cv2.COLOR_BGR2RGB)
; A- `- {, \% `0 L& C5 U7 n7 @: l
#face_encodings对图片对象a_images进行编码并返回数组0位置编码结果
: B" c8 |* E. U! E0 | M
encode=face_recognition.face_encodings(img)[0]
0 i: k: ]9 w* j6 b1 @1 i, H G/ |
existsEncodeingList.append(encode)
6 u0 n) J6 b1 q5 o. W( z/ \0 ?
$ ^9 L* |: x! d" X
#获取当前存储的人脸编码集合
$ a% Q6 p4 P' j N
def findExistsEncodeingList(img_path):
% B0 k5 N5 u, }. g
images=[]
7 g/ r v' ? Q
#列出已经上传的所有图片
% N4 F: E! v2 A
imgList=os.listdir(img_path)
% M9 E0 T0 \" F8 n
#处理存储的图片得到其人脸编码
: Z( d x/ z+ n+ X! S
for pic in imgList:
( n4 U$ |, E* A" w$ l* s5 E9 s$ h5 S
img=cv2.imread('{}/{}'.format(img_path,pic))
! c6 s) [ \2 b) D% S) u
images.append(img)
* M+ U! o4 Y F7 W2 k6 l
classNames.append(os.path.splitext(pic)[0])
- u3 Y- ]- V! {6 s
findEncodeings(images)
/ y+ l3 l0 W9 G T N
" r C* ?0 D& l
#选择并对比图片
. q# u0 Y/ J, A4 E
def choosepic():
}1 Z+ g! k( V8 e N7 K
choosepath = tkinter.filedialog.askopenfilename()
1 [0 ?6 L( Z: A! J$ _# S: B. q
path.set(choosepath)
% [" {( |' T( @
img_open = Image.open(entry.get()).resize((530,750))
% }5 v9 e2 h4 q/ b
img = ImageTk.PhotoImage(img_open)
) m& q+ k: u1 l* L o. U
lableShowImage.config(image=img)
4 g* d1 ?0 G2 f, T, Q
lableShowImage.image = img
* h8 P' ^; o) Y4 v2 b+ {
lableShowImage.place(x=30, y=70, width=530, height=750)
6 V7 I) ], p+ f- |
faceRecognition(choosepath)
/ p* e9 l- X4 m( x' x( ]4 ?# P
5 [% ~3 d K! I" A
def faceRecognition(choosepath):
# U( w- i; i' `
frame=cv2.imread(choosepath)
* x: F! l" j( V; O5 i) x" g n" j' N
frameRGB=cv2.cvtColor(src=frame,code=cv2.COLOR_BGR2RGB)
; m" e9 v/ O, \7 A
#对摄像头读取的检测人脸
) k1 S k/ F) t5 w) j) l" y
facesLocate=face_recognition.face_locations(frameRGB)
" ?5 W8 W( A2 V1 W- L
#进行特征编码
2 B: j" [. O/ E7 G
faceEncoded=face_recognition.face_encodings(frameRGB,facesLocate)
. F* ?+ M+ l7 c
#遍历检测的人脸和库中读取的图片进行对比,计算其相似度
! G' a, x5 y# K a# o
name='unknow'
0 U0 V- C3 i% K% x
for (top,right, bottom,left),face_encoding in zip(facesLocate,faceEncoded):
. p0 t8 B4 w$ r4 K
#进行匹配
, i& Y( [2 L7 S3 Z0 n' z! W
matchs=face_recognition.compare_faces(existsEncodeingList,face_encoding)
% p7 I1 J' F# T- w
#计算相似度
! P6 {9 A* R0 l6 A; H( O+ S0 T
distance=face_recognition.face_distance(existsEncodeingList,face_encoding)
- N( `; L5 U9 f, c/ p4 ?% _, }3 o
lab='unknow'
- C* G9 S& E1 Z. T
for index, item in enumerate(distance):
1 {4 q6 f! v9 P8 b9 x
if item<0.5:
& u% ^ Z* X q- T. p6 a
if matchs[index]:
8 H! N/ I- d% |0 `! |; H1 c
#得到匹配到的图片名称与相似度值
4 S- z3 s3 |6 G& @) n7 u
lab='name:{}; Similarity:{}'.format(classNames[index],item)
2 n o) R5 u1 J+ ]4 b3 Y
name=classNames[index]
8 j# d- Y5 J2 n2 q0 E. T/ j
break
$ Y9 R H; i' p5 L/ O
#初始化面部捕捉框显示绿色
; V! Y E7 V) c2 Q# k4 B
color1 =(0,255,0)
6 y) f. x4 m* A8 J
if name =='unknow':
5 S2 Y# G: i r
#未能识别的时候显示蓝色
6 v3 `4 y% O4 v. E8 l
color1 =(255,0,0)
5 P; Y" L% Q8 S$ Y+ W1 H: ]$ h" Q
#画面部捕捉框
2 I S' F( B/ S1 P& f. p7 F q) d# b' P
cv2.rectangle(img=frame,pt1=(left,top),pt2=(right,bottom),color=color1,thickness=3)
9 X: G+ s5 V+ O& l
#在捕捉框上添加匹配到的图片信息
7 S" ~/ ~4 r( [( Y" ^1 P7 I
cv2.putText(frame, lab, (left,top-8),cv2.FONT_HERSHEY_SIMPLEX, 0.7, color1, 2)
?. ? H; T& g8 R l$ j' G. x
cv2.imwrite('{}/{}.png'.format(img_recognition_path,name),frame)
1 D/ x6 Q( J8 h* F
img_Recognition = Image.open('{}/{}.png'.format(img_recognition_path,name)).resize((530,750))
! a& p( M" ?# }; _ ^5 @) {- ?
img = ImageTk.PhotoImage(img_Recognition)
8 k9 U1 L3 K" `* n k& e
lableShowImage2.config(image=img)
0 T/ ?7 {; T! n2 p& s8 J- J2 W( v3 J
lableShowImage2.image = img
. \. {3 v/ d; [
lableShowImage2.place(x=630, y=70, width=530, height=750)
. T: C* j v' A
" y! n) U% O$ {% z s% b G. |
if __name__ == '__main__':
4 _3 ^9 z- ?& Q- t! h: ^* H4 t/ c
findExistsEncodeingList(img_path)
" z5 [/ r! F, `2 w+ N6 q
#生成tk界面 app即主窗口
8 }- T- L7 z; K/ \) U- [4 W
app = tk.Tk()
9 \3 ~/ {& L* C
#修改窗口titile
7 L+ V% `5 O O5 F5 }
app.title("show pictue")
; g' y7 u: @& p# V/ u* Y
#设置主窗口的大小和位置
3 O3 V. l d O% N
app.geometry("1200x900+200+50")
( J/ K T, h; R- t& p
#Entry widget which allows displaying simple text.
) f. g" n* a& |, s9 z+ t
path = tk.StringVar()
) R6 ^# ?6 O+ T' ^ Q( p+ z' O
entry = tk.Entry(app, state='readonly', text=path,width = 100)
8 X- n3 P% r5 T1 E
entry.pack()
! m, \' b6 `, e( T
#使用Label显示图片
' T9 |% f) a. J% i, d9 L, [
lableShowImage = tk.Label(app)
. F3 a7 I( j* F e# @, P; ~) B
lableShowImage.pack()
- c* [. s# |: {& M2 X
#使用Label2显示处理后的图片
9 r8 w7 T" q- p" H) X' W' W" [
lableShowImage2 = tk.Label(app)
* w2 { o4 }3 P( Y
lableShowImage2.pack()
( g' }1 `2 X$ D( a
#选择图片的按钮
% d5 |" O3 Z( o9 f
buttonSelImage = tk.Button(app, text='choose picture', command=choosepic)
: g% m @! W/ @% \3 z( T
buttonSelImage.pack()
- u6 o: J0 o/ _+ G
app.mainloop()
- _) s: L4 |0 B$ Y1 F' b
, O. `2 [- T, A6 y1 C
3.说明
+ m/ N4 `3 x# U6 H( F7 }/ @4 g! G4 h
首先我将需要被识别的人脸的照片预设到项目目录的Picture文件夹下,然后创建一个Recognition目录存放识别过的图片,这样方便在一个界面上展示对比结果照片。
( l) G" N V$ m- n2 G
3 S, |' {# X7 u8 [; y7 L6 J) [6 C
7 L8 D2 d- M! |. ?+ }
- K/ y8 s8 p. J5 B
其实对比结果也可以不用存,直接将处理后的图片缓存直接展示在界面上,这里需要改一下此处的代码,将上述代码注释掉,然后换成下面的那行,通过数组直接转成图片
4 @* m+ Y# ~% k8 b& n
- p: P1 m7 k$ h; _$ }( {3 t
! w9 V E, f( f- |
( X4 G2 m' X# d& e* Q/ X! c8 v
但是效果会存在色彩的失真,效果如下:
8 v. F+ z4 h2 v8 |/ C& _+ n
5 T" C' q. R: ?, _; ?7 V" A
0 N! `3 C" @$ `; [1 W8 u: `
# W; U* Y) G' C* u) @' D: J" G
也尝试了PIL的九种不同图片模式: 1,L,P,RGB,RGBA,CMYK,YCbCr,I,F,最终效果也没达到,大概与我resize((530,750))这个有关,也没继续纠结,有兴趣的同学可以尝试一下。
; V: \: E8 e+ Y* x
. x+ D/ d' K [
这里简单提下PIL的九种不同图片模式:
7 g @4 A h% z9 Z. G' y- `! R T) o
1 v, h) @' N# z: {0 i8 B g
modes 描述
# U( o! J% G+ l7 |6 C
1 1位像素,黑和白,存成8位的像素
5 f4 G/ W7 }( X8 i s4 o
L 8位像素,黑白
, j, j3 @- \( s+ B6 @* r
P 8位像素,使用调色板映射到任何其他模式
. u( m/ M- s: U& p; Y/ W3 O$ y1 s
RGB 3× 8位像素,真彩
! o$ G- }, F; g7 n. S& `! M' ^
RGBA 4×8位像素,真彩+透明通道
. Y9 }0 {9 F4 d t
CMYK 4×8位像素,颜色隔离
8 w6 C5 n4 v9 t2 `& @
YCbCr 3×8位像素,彩色视频格式
! k( ^7 Y2 a6 B. g
I 32位整型像素
u6 H6 N/ q% s4 X* R
F 32位浮点型像素
3 Z( [0 x+ D$ o1 X2 \+ R* u* a
4.实现效果
% `7 ]* V' O L5 m! S- k5 D# v
, h( O' M: D1 }4 \# Y: m& U
1 m3 s9 B9 z5 W, s. k, F; J! D9 i: s% _
% {2 g, n$ m/ s+ c. T1 }4 G1 [3 C, o
' S! v2 v" \! b4 [, b
可以实现简单的人脸对比,Similarity代表相似度值,值越小代表人脸与预设的图片越相似。
# R* K- G) ^5 j, t; K
————————————————
: Q7 J& b1 G) T8 P% ~
版权声明:本文为CSDN博主「物联网_咸鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
. Y6 \& ^! T2 S% _$ @6 k9 B
原文链接:https://blog.csdn.net/qq_17486399/article/details/126629288
( W$ b* s1 s) C" ?$ U
& h1 @5 K( o+ y: m: U1 {5 s
. Q& ]& J+ |. Q2 a r* e! N8 c x
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5