- 在线时间
- 1630 小时
- 最后登录
- 2024-1-29
- 注册时间
- 2017-5-16
- 听众数
- 82
- 收听数
- 1
- 能力
- 120 分
- 体力
- 563012 点
- 威望
- 12 点
- 阅读权限
- 255
- 积分
- 174276
- 相册
- 1
- 日志
- 0
- 记录
- 0
- 帖子
- 5313
- 主题
- 5273
- 精华
- 18
- 分享
- 0
- 好友
- 163
TA的每日心情 | 开心 2021-8-11 17:59 |
|---|
签到天数: 17 天 [LV.4]偶尔看看III 网络挑战赛参赛者 网络挑战赛参赛者 - 自我介绍
- 本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。
 群组: 2018美赛大象算法课程 群组: 2018美赛护航培训课程 群组: 2019年 数学中国站长建 群组: 2019年数据分析师课程 群组: 2018年大象老师国赛优 |
Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)
4 U* V+ K3 k2 m8 V) }! z( U8 }& w6 t/ V5 a$ g
1.安装包依赖
) x' U) b/ `5 f" H! e/ y1 ?与上篇通过摄像头动态识别人脸一样,先下载好opencv-python、face-recognition,这里因为使用的是照片对比的方式,特意使用tkinter画了一个简单的GUI方便操作。% ~1 D1 e, t0 Y+ F5 {! Y" l5 ~
" l9 V+ b) @$ Z2 d* }& d* d在python 3以上版本tkinter是环境自带的,所以这里不需要安装
1 ]9 w3 K ^$ J
9 n/ |( K' e* Q2 R+ s" u9 y2.代码示例
$ d( a6 P0 J0 O% Y! n2 rimport os$ M3 \' n- x. z
import cv2: ]$ m* ^- _5 L3 G" z8 b
import numpy as np
: u1 C4 @/ M3 P A9 zimport face_recognition9 I0 c. b( W# T. F0 o% F9 G! L" ~
import tkinter as tk
: [+ E2 o/ i9 A( k( G% Pimport tkinter.filedialog
0 e1 Z1 v4 R9 r2 Vfrom PIL import Image,ImageTk , h0 g# M2 {1 a& z5 o9 G; S
% K" V: \# p( D. tclassNames=[]
5 W' z4 U' r: k* y7 v) Q9 Gimg_path='Picture'! a- ~8 U/ `5 `3 I. y8 b& l- ]
img_recognition_path='Recognition'
W) Y( J' t4 e# ?: c1 [/ \% b- rexistsEncodeingList=[]
, [) V5 b; U( G( i4 C5 J+ l" j#对人脸集合进行编码进行处理/ J$ A; j2 B4 `. T
def findEncodeings(images):6 p) X6 e) O" n; W
for img in images:2 F7 @# ]* D" W! H) ?. S( F
#灰度处理. @/ e3 D9 r6 R" T, v0 i2 p0 V
img=cv2.cvtColor(src=img,code=cv2.COLOR_BGR2RGB), O: k; L* ~" A0 M
#face_encodings对图片对象a_images进行编码并返回数组0位置编码结果
# W+ h8 C- ?: H. g encode=face_recognition.face_encodings(img)[0]5 b8 k6 {% i! T0 u, d; @4 s$ j
existsEncodeingList.append(encode)
: [! N" T8 c' p0 t" e: z: P* ^! i7 ^8 e+ i3 T, d8 | B
#获取当前存储的人脸编码集合2 c) c0 P/ r$ ~8 ~4 S
def findExistsEncodeingList(img_path):
# \2 ]% [. V) m: m- D F6 V w images=[]& ^5 M5 F, {& ]5 R$ M
#列出已经上传的所有图片
. s% g; ?( M( \5 t imgList=os.listdir(img_path)
' z8 F6 x! M9 v( k) s, J9 O" O #处理存储的图片得到其人脸编码
; \/ I e- Q7 v for pic in imgList:* g2 c H' x& w2 I" u3 k
img=cv2.imread('{}/{}'.format(img_path,pic))0 c% Z3 ^/ |9 a K6 X9 `- j- l
images.append(img)7 p7 I) x, ~0 j9 O
classNames.append(os.path.splitext(pic)[0])3 {. b4 }4 M, {, o, X' b
findEncodeings(images)
3 Q S9 L& v2 a( `0 ?7 m" l; N7 `4 S) @( \7 j1 l5 x
#选择并对比图片
5 }( s- T0 B) `def choosepic():% ~% m: z. D, X' n0 z5 A# y
choosepath = tkinter.filedialog.askopenfilename()
7 ]- Q4 |+ l1 N P path.set(choosepath)
) h2 Q# C+ ?/ ]( ?4 r img_open = Image.open(entry.get()).resize((530,750))& ? e8 v; S' L$ }/ ~* `! R
img = ImageTk.PhotoImage(img_open)
- b, S1 R% v' U$ A. z6 x lableShowImage.config(image=img). p+ ?$ A6 `% }- x
lableShowImage.image = img
4 q# u2 g6 ?/ t8 Z5 y- B0 f lableShowImage.place(x=30, y=70, width=530, height=750)
/ X: K% f% R* Y; d8 z& [" a faceRecognition(choosepath)/ o& H2 }& ?1 Q. ]
& h% q. t" q% n! V1 A: Q5 `5 f
def faceRecognition(choosepath):
/ b+ _3 ~( P/ N ] frame=cv2.imread(choosepath)1 j: T5 b, {. S/ T H8 O1 r E
frameRGB=cv2.cvtColor(src=frame,code=cv2.COLOR_BGR2RGB)
, d$ L5 ]( I) ]/ f/ T6 m #对摄像头读取的检测人脸, n4 n% w- @8 ?4 A" h1 M4 i2 G
facesLocate=face_recognition.face_locations(frameRGB), I7 ]* Q: x# _+ ] B+ ?
#进行特征编码1 T! |7 b9 D1 @, l& D: D5 G5 m0 h& D
faceEncoded=face_recognition.face_encodings(frameRGB,facesLocate)
4 D& c! c9 f2 @ #遍历检测的人脸和库中读取的图片进行对比,计算其相似度
F0 j- T6 {( F: z8 N3 p5 y8 `' z0 L3 W name='unknow' @+ z: \$ h7 H2 A
for (top,right, bottom,left),face_encoding in zip(facesLocate,faceEncoded):( Y' ^$ P! Q# R
#进行匹配) G! n) E+ _+ H+ u" k) }
matchs=face_recognition.compare_faces(existsEncodeingList,face_encoding)
% V1 q7 ]9 `; e% [* y #计算相似度
+ B2 l, a* O! G" _% o+ F, } distance=face_recognition.face_distance(existsEncodeingList,face_encoding)# i$ {% W$ r" u8 y# ]
lab='unknow'
; _; ^0 k" D: |/ j5 P for index, item in enumerate(distance):1 N/ E1 l- h9 B6 p0 c6 H
if item<0.5:/ M9 J5 w- w8 W: c
if matchs[index]:
) Q9 \/ n/ m4 C: ] #得到匹配到的图片名称与相似度值: Z- R0 ?' {4 i5 t* v6 }, l
lab='name:{}; Similarity:{}'.format(classNames[index],item)
' ?& j9 o: B: t: x+ E" ~ O name=classNames[index]
. q2 Q4 S* r$ f! M) }% C+ v* A break
1 h8 }# ]6 i0 R0 Q* C, h* p #初始化面部捕捉框显示绿色
1 v/ I( h) q+ R( B) ?# c color1 =(0,255,0)4 d F6 B9 w7 L9 M# }; v; y* F
if name =='unknow':' \8 |* V _6 z' p/ \' s) N: M! q, S$ ^
#未能识别的时候显示蓝色
" Y$ H9 r0 l2 f& W6 I color1 =(255,0,0)7 ~- m' J% l! `8 ^* i J
#画面部捕捉框( e1 b, V4 W1 P& A. r
cv2.rectangle(img=frame,pt1=(left,top),pt2=(right,bottom),color=color1,thickness=3)
9 R" N5 ]% [4 _1 K, E/ g #在捕捉框上添加匹配到的图片信息
4 w6 d* N' S* Q9 e+ q cv2.putText(frame, lab, (left,top-8),cv2.FONT_HERSHEY_SIMPLEX, 0.7, color1, 2)+ `4 O: ^! m7 i& [! ^, }$ N0 V" |
cv2.imwrite('{}/{}.png'.format(img_recognition_path,name),frame)
# k5 ~0 `% b2 u( t img_Recognition = Image.open('{}/{}.png'.format(img_recognition_path,name)).resize((530,750))9 h6 I! Y0 H2 b$ b
img = ImageTk.PhotoImage(img_Recognition)
: W _7 o K& J lableShowImage2.config(image=img)/ a' c$ Y! V1 {
lableShowImage2.image = img
" k$ g \9 t+ G9 t lableShowImage2.place(x=630, y=70, width=530, height=750)
- X( I. a# n" z& O
! b- v$ R' ~8 y0 B0 Y, ^/ Bif __name__ == '__main__':
& I/ T3 c7 V, m: G$ H- D findExistsEncodeingList(img_path)
1 L9 d8 c2 t+ m #生成tk界面 app即主窗口
0 k) `* b+ N$ ` app = tk.Tk() 7 _6 p$ @3 P% h$ L% {
#修改窗口titile
' ] U, |$ A9 J" I! q1 k1 u app.title("show pictue") 1 j) n# ^" U+ m4 n+ N' V
#设置主窗口的大小和位置
* b |9 `6 _) T- m- F app.geometry("1200x900+200+50")
+ {7 `5 F! S* f" k& q: Y #Entry widget which allows displaying simple text.4 l4 |- y5 \) n5 K+ M
path = tk.StringVar()8 U1 r) I; U$ {
entry = tk.Entry(app, state='readonly', text=path,width = 100)* u0 T3 r2 m9 G& B5 W
entry.pack(): R3 R. M. q. K' E1 N: b2 M& p0 A
#使用Label显示图片' A. f" l. R) w, R6 z/ d
lableShowImage = tk.Label(app); h& b: P- Z: S' C1 D
lableShowImage.pack()
! X% K: l1 K* [ #使用Label2显示处理后的图片
5 t4 e0 B7 z* G* R lableShowImage2 = tk.Label(app)
( a1 X' ]4 M# T, Z& }+ j lableShowImage2.pack()
3 H! o9 b$ O p/ `) t" I #选择图片的按钮1 { y: k; B6 t, O* D$ |
buttonSelImage = tk.Button(app, text='choose picture', command=choosepic): V H; }' `( d p; C F
buttonSelImage.pack()" n/ b9 H2 a4 |1 i8 b
app.mainloop()+ ]! Q* r2 H8 X7 ?
, J5 z0 }5 A, S& [4 Q6 j
3.说明$ F, h0 P+ x L9 j8 b
首先我将需要被识别的人脸的照片预设到项目目录的Picture文件夹下,然后创建一个Recognition目录存放识别过的图片,这样方便在一个界面上展示对比结果照片。# f* |! Y' w, Q& M
* f: y, O: e! v- @4 r+ a! C5 i ]" i+ A7 ]+ V
4 E. h2 o8 k1 g 其实对比结果也可以不用存,直接将处理后的图片缓存直接展示在界面上,这里需要改一下此处的代码,将上述代码注释掉,然后换成下面的那行,通过数组直接转成图片9 ?4 r" V+ M; o- M
2 P1 u8 q1 f$ J$ s l3 C/ b3 u
1 m" D2 H* Y4 R) H& j
( Q2 W& ~7 G- `( C 但是效果会存在色彩的失真,效果如下:
$ l G0 l2 C% B- ^' l; w9 M
0 e3 b5 q1 h! @+ y
% V5 Y! k, e: g3 |3 P. z o: k @- _* b5 w2 J
也尝试了PIL的九种不同图片模式: 1,L,P,RGB,RGBA,CMYK,YCbCr,I,F,最终效果也没达到,大概与我resize((530,750))这个有关,也没继续纠结,有兴趣的同学可以尝试一下。; n& l' q! ]! b1 Q' S- f
$ ~) g: Q0 i; J: s8 f; k
这里简单提下PIL的九种不同图片模式:! |4 I6 x1 M9 e6 x2 \7 E
: N5 Q" R# h9 H3 f7 v
modes 描述3 \& `8 V3 F5 Z% J* w: I% i, ]
1 1位像素,黑和白,存成8位的像素
3 U9 U: J& X3 G/ a# V& f' fL 8位像素,黑白' Y m' ]" s+ d" u7 f
P 8位像素,使用调色板映射到任何其他模式
! ^! \5 _9 G6 K- d D8 C' WRGB 3× 8位像素,真彩6 H% J1 v' x' f6 k6 l' j; B T( \
RGBA 4×8位像素,真彩+透明通道' Q3 D) g" U* k
CMYK 4×8位像素,颜色隔离
7 y9 N' @4 Q& ]- _: Y" p: k) gYCbCr 3×8位像素,彩色视频格式, I2 w" [1 t2 I! k# [# v# v* {
I 32位整型像素; N" V" }$ ~ X2 L+ _9 G' x; q( b
F 32位浮点型像素
" q H; w% u+ u/ c4.实现效果+ q, n C/ F& `$ Q
0 F. P5 H+ E( Z u2 i, {' V8 a
1 [/ D& q. D. T/ w0 D8 u/ u$ ]
* t! d3 Z" Y+ W& Z6 `' h- E) o. M, \/ q9 [
可以实现简单的人脸对比,Similarity代表相似度值,值越小代表人脸与预设的图片越相似。
1 t1 d- P- i# Y- U————————————————
* |2 N* r! u) H& m3 d/ s2 ~版权声明:本文为CSDN博主「物联网_咸鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
( q: d' a& m+ V/ j4 B2 a/ F, p7 `原文链接:https://blog.csdn.net/qq_17486399/article/details/1266292888 u1 C5 z# j0 Q# c
3 @1 L8 I" N) g, t; R" }5 ]% z- a
1 w9 w3 h7 Z4 U- {0 A5 A( a |
zan
|