QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3665|回复: 0
打印 上一主题 下一主题

[其他资源] Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)

[复制链接]
字体大小: 正常 放大
杨利霞        

5273

主题

82

听众

17万

积分

  • TA的每日心情
    开心
    2021-8-11 17:59
  • 签到天数: 17 天

    [LV.4]偶尔看看III

    网络挑战赛参赛者

    网络挑战赛参赛者

    自我介绍
    本人女,毕业于内蒙古科技大学,担任文职专业,毕业专业英语。

    群组2018美赛大象算法课程

    群组2018美赛护航培训课程

    群组2019年 数学中国站长建

    群组2019年数据分析师课程

    群组2018年大象老师国赛优

    跳转到指定楼层
    1#
    发表于 2022-9-14 17:07 |只看该作者 |倒序浏览
    |招呼Ta 关注Ta
    Python 基于OpenCV+face_recognition实现人脸捕捉与人脸识别(照片对比)* Q2 G' r0 C+ Y9 r' h6 M

    ) ^' ?, ~7 ^1 y* B4 |, |1.安装包依赖- `0 n& v! N5 l% V/ s" \0 Y5 f
    与上篇通过摄像头动态识别人脸一样,先下载好opencv-python、face-recognition,这里因为使用的是照片对比的方式,特意使用tkinter画了一个简单的GUI方便操作。
    * L6 Y: K1 q2 S* q) O
    ; L# d* u& R& h在python 3以上版本tkinter是环境自带的,所以这里不需要安装' T) u% K/ L5 u4 \! Y: K

    7 }$ u  B4 v3 t7 m, u2.代码示例
    0 i! f8 n3 L3 H) }2 @+ T8 cimport os: u8 _( t- S- O, {8 ~5 x4 B' K; ]
    import cv2
    - G5 W2 o: K" c- a) T! q2 bimport numpy as np
    3 k( A* P! ^  K+ g. uimport face_recognition
    / ?+ I! n. T& C# |import tkinter as tk  
    ; v4 z- ]& \; P9 G# T$ f! f9 C+ rimport tkinter.filedialog8 @7 H5 Z! o" Z8 d! l
    from PIL import Image,ImageTk
    $ p3 j6 ^; `% o0 m) \/ q/ d& [! T  q3 \6 a- S% v: Q8 X/ X
    classNames=[]
    8 z+ E1 E8 n) A/ vimg_path='Picture'
    $ P3 O# j0 ]! a4 V. eimg_recognition_path='Recognition'7 A6 M7 A# U* T9 X
    existsEncodeingList=[]% A- r  x$ a* ~$ l- n5 S" w. ?+ g
    #对人脸集合进行编码进行处理
    ( m) \: c  Q- {! H# H( I2 D% L# Odef findEncodeings(images):
    4 I) n2 ]2 h! n: f8 ^    for img in images:4 s, v0 ~5 g. A; W* j3 Q& a: @
            #灰度处理/ {/ t: ]+ Z2 i7 a/ }
            img=cv2.cvtColor(src=img,code=cv2.COLOR_BGR2RGB)
    1 K0 Y3 r, A3 x" x5 A$ y        #face_encodings对图片对象a_images进行编码并返回数组0位置编码结果2 D) _2 Q; ]+ x7 m5 Y; M8 A) h2 e
            encode=face_recognition.face_encodings(img)[0]* l; ^8 L8 n* a! [" O8 {
            existsEncodeingList.append(encode)
    ! m1 r; D: d- d
    ) f# s4 {& ^& c5 H" S- R; ]#获取当前存储的人脸编码集合4 E, S- w: o1 `3 \
    def findExistsEncodeingList(img_path):" ^7 i2 T/ |7 z& k
        images=[]
    ( M" |5 ^4 a; c9 }& R' _; T! T" H    #列出已经上传的所有图片
    0 n* }5 G/ {6 l" ~; E  t+ P    imgList=os.listdir(img_path)
    : `- n( R( ^$ J3 P8 [/ S    #处理存储的图片得到其人脸编码3 E  I7 F9 h/ u1 X' B% f
        for pic in imgList:$ ?- E3 |2 Z( e- @6 F8 [
            img=cv2.imread('{}/{}'.format(img_path,pic))" l  q& C$ V3 z$ t" E$ ]
            images.append(img): ]  k) e0 k" [- F
            classNames.append(os.path.splitext(pic)[0]), R1 X8 Q* X$ D1 \; H. z: E9 p
        findEncodeings(images)
    8 E# q. g* U! x8 _1 l
    % f% b7 T# X" N+ z8 S- ]" L& g#选择并对比图片
    4 w) C4 y0 Q( G+ A0 F5 Xdef choosepic():
    1 Q. x1 ~; V2 P: m    choosepath = tkinter.filedialog.askopenfilename(). B! o1 t: r; |. ~* |% n
        path.set(choosepath). i( C& B- R: d
        img_open = Image.open(entry.get()).resize((530,750))
    : G3 [$ j6 k! v    img = ImageTk.PhotoImage(img_open)
    . Q: Q& z" K3 G0 g6 d) P    lableShowImage.config(image=img)/ Y- V5 {) d( d& e
        lableShowImage.image = img7 \6 [4 |2 ~" i  g* @
        lableShowImage.place(x=30, y=70, width=530, height=750)# ~, g* C+ M" J$ g' {9 V; {8 n
        faceRecognition(choosepath)
    ! \4 }4 M" g5 ?1 R! L8 M1 L! S5 N: o: X
    def faceRecognition(choosepath):# ]; U3 L7 [) I1 y; L+ {3 v1 Q
        frame=cv2.imread(choosepath)
    8 b$ ^( w  K5 y    frameRGB=cv2.cvtColor(src=frame,code=cv2.COLOR_BGR2RGB)
    ' u$ K# l( o. l/ p% i) S0 v    #对摄像头读取的检测人脸. B" B; P6 c+ h+ E) w1 h
        facesLocate=face_recognition.face_locations(frameRGB)# I4 ~: \  n3 O. V
        #进行特征编码
    $ Q6 Q: A& e# c( D6 J3 c2 V* {+ p    faceEncoded=face_recognition.face_encodings(frameRGB,facesLocate)
    3 |8 c% S$ g4 J" w        #遍历检测的人脸和库中读取的图片进行对比,计算其相似度5 _& [4 f$ h! Y! j/ M: H
        name='unknow'; y( P: M. v# O8 p1 n4 C
        for (top,right, bottom,left),face_encoding in zip(facesLocate,faceEncoded):+ _+ p& L! x9 }- g) b* |$ @. R
            #进行匹配) S0 E. u- B, l: d3 ?% i3 J3 F
            matchs=face_recognition.compare_faces(existsEncodeingList,face_encoding)
    ) v6 C+ n8 J( l7 h; I/ f+ o' `  i% P0 ^        #计算相似度
      w, v: n+ z) J, [% `        distance=face_recognition.face_distance(existsEncodeingList,face_encoding)
    2 v" P' B, z6 f% U; D. k* @        lab='unknow'7 b3 y# P4 J1 k/ M/ {) I6 N
            for index, item in enumerate(distance):- G+ B, [% e! I' {& m' w
               if item<0.5:/ I3 @3 X: I) H9 f) V2 G
                    if matchs[index]:% x2 c/ f% \* d# k9 [2 b
                        #得到匹配到的图片名称与相似度值, I1 o- b- P' {7 n, M4 X
                        lab='name:{}; Similarity:{}'.format(classNames[index],item). o4 v* t- y9 {, Y: V
                        name=classNames[index]
    3 _5 Q4 Q9 u$ f2 g' k                    break
    6 p6 F; q2 H5 n7 S5 M" `        #初始化面部捕捉框显示绿色
    2 o2 y* J8 I% `6 p        color1 =(0,255,0)8 s# R* ]4 R4 ?$ ^6 f2 g
            if name =='unknow':5 F, a& [6 Y8 e3 m. Z! v( x
                #未能识别的时候显示蓝色
    : i& ]) S3 \9 A' ]( c            color1 =(255,0,0)
    8 T5 N2 t6 [% w! z1 W" A5 l; i        #画面部捕捉框: c1 W, y8 h$ U) t9 Q
            cv2.rectangle(img=frame,pt1=(left,top),pt2=(right,bottom),color=color1,thickness=3)! G: h! L5 x7 z
            #在捕捉框上添加匹配到的图片信息1 m' s9 k6 \9 t* F
            cv2.putText(frame, lab, (left,top-8),cv2.FONT_HERSHEY_SIMPLEX, 0.7, color1, 2)
    # @! _1 F6 E' Q- G: d0 L, f        cv2.imwrite('{}/{}.png'.format(img_recognition_path,name),frame)' _, v$ f; X6 `; Z" @8 E2 `2 x" h
        img_Recognition = Image.open('{}/{}.png'.format(img_recognition_path,name)).resize((530,750))
    ; {, l4 R" {% N" _9 l    img = ImageTk.PhotoImage(img_Recognition)6 \' ^3 E* Q' ]
        lableShowImage2.config(image=img)4 D3 Q( n# }' u% g8 v
        lableShowImage2.image = img- b- f; x& m3 F; q: i+ `
        lableShowImage2.place(x=630, y=70, width=530, height=750)* x9 V; D. M% S- F# I. z' A+ @

    5 e6 H# E! Y- W1 u7 l3 Vif __name__ == '__main__':
    ' x, o9 M4 C1 V. d    findExistsEncodeingList(img_path)
    / \% F8 R+ `' b    #生成tk界面 app即主窗口
    8 f+ [0 e+ p! }    app = tk.Tk()  
    9 i+ U! E; _7 W, Z- i    #修改窗口titile
    $ \2 T3 Z* E1 W' }4 z$ v    app.title("show pictue")  
    0 k! z/ p% H8 d    #设置主窗口的大小和位置6 Z+ S# N3 v- z/ M- u: p
        app.geometry("1200x900+200+50")
    , n1 |6 Z' x& X+ [8 O( G4 s    #Entry widget which allows displaying simple text.
    * @* Y# v6 N; v. `    path = tk.StringVar()
    7 J, E" A* E5 b& x8 @: r    entry = tk.Entry(app, state='readonly', text=path,width = 100)
    3 N$ `- \6 t' W! z7 I$ c! F6 o    entry.pack()
    0 B8 K+ S4 }$ e9 [    #使用Label显示图片
    ! x# |7 V" a9 M# x6 {# T. D& ?' k    lableShowImage = tk.Label(app)+ P7 e6 [  I4 O* [2 T- r
        lableShowImage.pack()3 d& [9 {( M0 k0 P
         #使用Label2显示处理后的图片* l3 B& d/ c& s9 n- }& Z
        lableShowImage2 = tk.Label(app)
    / W% d6 x* ~8 F/ e8 d, V% W$ B    lableShowImage2.pack()
    : }2 D' ], x/ E1 g) s    #选择图片的按钮0 w2 y  Y2 \) P5 p7 h
        buttonSelImage = tk.Button(app, text='choose picture', command=choosepic). I" C- u8 A* k1 S+ r. e
        buttonSelImage.pack()+ m: h. H$ @, R. S
        app.mainloop()
    # Z1 }& q% U* h, g9 d3 R0 S8 v( [# I0 d* @: E, {- B
    3.说明
    ! f  W+ V" h2 K$ I1 `+ X首先我将需要被识别的人脸的照片预设到项目目录的Picture文件夹下,然后创建一个Recognition目录存放识别过的图片,这样方便在一个界面上展示对比结果照片。
    $ q2 k7 I% Q9 A& p, W/ C9 n/ G; m9 a3 ]/ s9 E, K% c& U

    ( a6 ^; V" U+ g, q" s
    * V# Q7 M8 f. H2 r* t6 s  v- L6 f 其实对比结果也可以不用存,直接将处理后的图片缓存直接展示在界面上,这里需要改一下此处的代码,将上述代码注释掉,然后换成下面的那行,通过数组直接转成图片
    0 s& B( x% I) I2 ?, G( [" E* G6 ]6 S: k' C0 a

    " i7 ^1 I- V% I# }
    / q1 @1 W! G/ G2 E) p) f$ @5 P 但是效果会存在色彩的失真,效果如下:
    6 P0 n; K( [  f! ?) h( }# _7 D- r  p7 I; m
    " o+ @  k) H, V

    " @( u9 U  f; d也尝试了PIL的九种不同图片模式: 1,L,P,RGB,RGBA,CMYK,YCbCr,I,F,最终效果也没达到,大概与我resize((530,750))这个有关,也没继续纠结,有兴趣的同学可以尝试一下。
    9 ]; p4 ]8 j: c. `( F* ]
    2 p& N. R( p6 X5 E& S- k3 L+ i! \) H这里简单提下PIL的九种不同图片模式:
    3 v$ ?' z+ a% `3 i2 [8 K" z2 W' ?
    " r; y* t; J$ ^! q  l+ \modes        描述
    2 o6 l/ s0 I. A* {( U- T$ D! t9 n1        1位像素,黑和白,存成8位的像素
      x: ^% t' H# G, `' NL        8位像素,黑白$ J9 ?- f: z- e9 V
    P        8位像素,使用调色板映射到任何其他模式
    9 p2 C: q, n" n8 fRGB        3× 8位像素,真彩
    ; |, m/ D2 Y7 D) R/ U; Z, ^9 B' WRGBA        4×8位像素,真彩+透明通道
    * F8 L( Y5 g9 N  K9 X( wCMYK        4×8位像素,颜色隔离
    * L: |+ t& D( p6 l! _6 Y  BYCbCr        3×8位像素,彩色视频格式
    / U6 p( j* p$ c. n* y, m( ?- E9 ^I        32位整型像素8 ]  r4 Z2 v. l9 L+ |
    F        32位浮点型像素
    ) ^: p4 F2 i5 e6 I4.实现效果1 @! Y' P$ R. b4 n3 c6 x0 e* O

    4 y9 ], z$ n" C) |* t
    ' w4 l+ F3 {- O! m: w
    & [3 q; s8 q% B8 _7 ]+ z8 k. M" P8 {# p1 f; o# d& p
    可以实现简单的人脸对比,Similarity代表相似度值,值越小代表人脸与预设的图片越相似。/ W1 m2 y; x5 w" W8 |
    ————————————————% P& e) y$ F9 D9 g7 k5 [1 b
    版权声明:本文为CSDN博主「物联网_咸鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    4 R& G3 z+ ?! J* u原文链接:https://blog.csdn.net/qq_17486399/article/details/126629288
    / {! J3 U- R( t0 O% u$ e4 J) f, l& u& Q- o
    ) P% A7 y7 W% E, v# R' v
    zan
    转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
    您需要登录后才可以回帖 登录 | 注册地址

    qq
    收缩
    • 电话咨询

    • 04714969085
    fastpost

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2025-10-23 01:06 , Processed in 1.035792 second(s), 50 queries .

    回顶部