树莓派3B+ 人脸识别(OpenCV)

2023-05-16

树莓派3B+ 人脸识别(OpenCV)


相信大家都看了前面的OpenCV安装人脸检测教程,已经跃跃欲试,想要进行人脸识别了,现在我们正式进入重头戏——人脸识别 的教程。
注意:该教程面向python2.7+OpenCV2.4.9(官方源)
其它版本需进行一些小的修改,文中会具体注明。

1.生成人脸识别数据

目录结构
./data 数据根目录
./data/generate 自动生成的人脸数据
./data/datamap.csv 人脸数据对应数据
./data/Mengcheng 人物一文件夹
./data/Kaixin 人物二文件夹
./data/Mengying 人物三文件夹
(这里三个人物可自行修改,文件夹为人物名,里面存放图片)

dir

// python脚本,请保存为genrate.py
#!/usr/bin/env python
#coding=utf-8
import cv2
import os  
import sys

face_cascade=cv2.CascadeClassifier('/usr/share/opencv/haarcascades/haarcascade_frontalface_default.xml')

def makedir(path):
    path=path.strip().rstrip('/')
    if os.path.exists(path) is False:
        os.makedirs( path );

def generate(root_argv,dirname):
    subject_dir_path = os.path.join(root_argv, dirname)
    print 'seek:'+subject_dir_path
    count=0
    for filename in os.listdir(subject_dir_path): 
        if filename == ".directory":
            continue
        imgPath = os.path.join(subject_dir_path, filename)
        try:
            print 'read:'+imgPath
            img = cv2.imread(imgPath)
            gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            outdir=os.path.join(root_argv,'generate',dirname)
            makedir(outdir)
            faces=face_cascade.detectMultiScale(gray,1.3,5)
            for x,y,w,h in faces:
                f=cv2.resize(gray[y:y+h,x:x+w],(200,200))
                outPath=os.path.join(root_argv,'generate',dirname,'%s.pgm' % str(count))
                print 'write:'+ outPath
                cv2.imwrite(outPath, f)
                count+=1

        except:
            pass


if __name__ == '__main__':
    if len(sys.argv)==1:
        print ("USAGE: generate.py <人脸图片存放路径>")
        exit(0)

    root_argv=sys.argv[1]
    for dirname in os.listdir(root_argv):
        file_path = os.path.join(root_argv, dirname)  
        if os.path.isdir(file_path): 
            if dirname == 'generate':
                continue
            generate(root_argv,dirname)

在控制台执行python generate.py ./data即可自动生成人脸识别数据
生成后,请自行打开./data/generate/下生成人脸数据是否正常,如果不正常的,请清理掉,防止后续有干扰。如图:

这里写图片描述

2.生成人脸数据对应表

人脸数据生成了,还得有一个人物<->名称映射表,让机器知道人脸数据对应那个人物。

// python脚本,请保存为create_csv.py
#!/usr/bin/env python
#coding=utf-8
import sys
import os.path
#import Image
if __name__ == '__main__':
    if len(sys.argv) != 2:
        print "usage: create_csv.py <生成的人脸数据路径>"
        sys.exit(0)

    BASE_PATH=sys.argv[1]
    SEPARATOR=";"
    label = 0
    for dirpath, dirnames, filenames in os.walk(BASE_PATH): 
        for subdirname in dirnames:
            subject_path = os.path.join(dirpath, subdirname) 
            #print subject_path
            for filename in os.listdir(subject_path):
                image_filename = subject_path + "/"+ filename 
                #print(image_filename) 
                #img=Image.open(image_filename)
                ##  img=img.resize((92,112))
                #img.show()
                abs_path = "%s/%s" % (subject_path, filename) 
                print("%s%s%d"%(abs_path,SEPARATOR, label))
                # print("%s"%(abs_path)) 
            label = label + 1

然后执行python create_csv.py ./data/generate/ > ./data/datamap.csv
打开生成的datamap.csv文件,检查对应关系(如图所示):

datamap.csv

这样,人脸数据就准备好了。

3.人脸识别

使用样图,使用树莓派摄像头获取图片。

// python脚本,请保存为facerec.py
#!/usr/bin/env python
#coding=utf-8
### Imports ###################################################################

import multiprocessing as mp
import cv2
import os
import sys
import time
import numpy as np


### Setup #####################################################################

resX = 640
resY = 480

# The face cascade file to be used
face_cascade = cv2.CascadeClassifier('/usr/share/opencv/lbpcascades/lbpcascade_frontalface.xml')

#三种识别算法
#model = cv2.createEigenFaceRecognizer()
model = cv2.createFisherFaceRecognizer()
#model = cv2.createLBPHFaceRecognizer()

t_start = time.time()
fps = 0


### Helper Functions ##########################################################

def normalize(X, low, high, dtype=None):
    """Normalizes a given array in X to a value between low and high."""
    X = np.asarray(X)
    minX, maxX = np.min(X), np.max(X)
    # normalize to [0...1].
    X = X - float(minX)
    X = X / float((maxX - minX))
    # scale to [low...high].
    X = X * (high-low)
    X = X + low
    if dtype is None:
        return np.asarray(X)
    return np.asarray(X, dtype=dtype)


def load_images(path, sz=None):
    c = 0
    X,y = [], []
    for dirname, dirnames, filenames in os.walk(path):
        for subdirname in dirnames:
            subject_path = os.path.join(dirname, subdirname)
            for filename in os.listdir(subject_path):
                try:
                    filepath = os.path.join(subject_path, filename)
                    if os.path.isdir(filepath):
                        continue
                    img = cv2.imread(os.path.join(subject_path, filename), cv2.IMREAD_GRAYSCALE)
                    if (img is None):
                        print ("image " + filepath + " is none")
                    else:
                        print (filepath)
                    # resize to given size (if given)
                    if (sz is not None):
                        img = cv2.resize(img, (200, 200))

                    X.append(np.asarray(img, dtype=np.uint8))
                    y.append(c)
                # except IOError, (errno, strerror):
                #     print ("I/O error({0}): {1}".format(errno, strerror))
                except:
                    print ("Unexpected error:", sys.exc_info()[0])
                    raise
            print (c)
            c = c+1


    print (y)
    return [X,y]

def get_faces( img ):

    gray = cv2.cvtColor( img, cv2.COLOR_BGR2GRAY )
    faces = face_cascade.detectMultiScale(gray, 1.3, 5)

    return faces, img, gray

def draw_frame( faces, img, gray ):

    global xdeg
    global ydeg
    global fps
    global time_t

    # Draw a rectangle around every face
    for ( x, y, w, h ) in faces:

        cv2.rectangle( img, ( x, y ),( x + w, y + h ), ( 200, 255, 0 ), 2 )
        #-----rec-face
        roi = gray[x:x+w, y:y+h]
        try:
            roi = cv2.resize(roi, (200, 200), interpolation=cv2.INTER_LINEAR)
            params = model.predict(roi)
            sign=("%s %.2f" % (names[params[0]], params[1]))
            cv2.putText(img, sign, (x, y-2), cv2.FONT_HERSHEY_SIMPLEX, 0.5, ( 0, 0, 255 ), 2 )
            if (params[0] == 0):
                cv2.imwrite('face_rec.jpg', img)
        except:
            continue


    # Calculate and show the FPS
    fps = fps + 1
    sfps = fps / (time.time() - t_start)
    cv2.putText(img, "FPS : " + str( int( sfps ) ), ( 10, 15 ), cv2.FONT_HERSHEY_SIMPLEX, 0.5, ( 0, 0, 255 ), 2 )

    cv2.imshow( "recognize-face", img )


### Main ######################################################################

if __name__ == '__main__':

    camera = cv2.VideoCapture(0)
    camera.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH,resX)  
    camera.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT,resY) 

    pool = mp.Pool( processes=4 )

    # -----------init-rec----------
    # 人名要与datamap.csv里面的对应,不要弄错了顺序
    names = ['Mengying', 'Kaixin', 'Mengcheng']
    if len(sys.argv) < 2:
        print ("USAGE: facerec.py <人脸数据存放路径> [<数据对应表>]")
        sys.exit()

    [X,y] = load_images(sys.argv[1])
    y = np.asarray(y, dtype=np.int32)

    if len(sys.argv) == 3:
        out_dir = sys.argv[2]

    model.train(np.asarray(X), np.asarray(y))
    # ------init finish---------

    read, img = camera.read()
    pr1 = pool.apply_async( get_faces, [ img ] )   
    read, img = camera.read()
    pr2 = pool.apply_async( get_faces, [ img ] )  
    read, img = camera.read() 
    pr3 = pool.apply_async( get_faces, [ img ] )   
    read, img = camera.read()
    pr4 = pool.apply_async( get_faces, [ img ] )    

    fcount = 1
    while (True):
        read, img = camera.read()

        if   fcount == 1:
            pr1 = pool.apply_async( get_faces, [ img ] )
            faces, img, gray=pr2.get()
            draw_frame( faces, img, gray )

        elif fcount == 2:
            pr2 = pool.apply_async( get_faces, [ img ] )
            faces, img, gray=pr3.get()
            draw_frame( faces, img, gray )

        elif fcount == 3:
            pr3 = pool.apply_async( get_faces, [ img ] )
            faces, img, gray=pr4.get()
            draw_frame( faces, img, gray )

        elif fcount == 4:
            pr4 = pool.apply_async( get_faces, [ img ] )
            faces, img, gray=pr1.get()
            draw_frame( faces, img, gray )
            fcount = 0

        fcount += 1

        if cv2.waitKey(1000 // 12) & 0xff == ord("q"):
            break

    camera.release()
    cv2.destroyAllWindows()

注意:这里对于OpenCV3的版本需要修改如下内容:
cv2.createEigenFaceRecognizer()
—>cv2.face.createEigenFaceRecognizer()
cv2.rectangle()
—>img=cv2.rectangle()


然后执行python facerec.py ./data/generate ./data/datamap.csv,此时,摄像头会自动打开,在显示屏上可以看到画面,如图:

result

如果想测试得更理想,应选择脸型差别比较大的来测试,其次是素材高清一些,摄像头成像清晰一些。

4.扩展资料

对于OpenCV有三种人脸识别方法,它们分别基于三种不同的算法:Eigenfaces、Fisherfaces和Local Binary Pattern Histogram(LBPH)。

首先,所有的方法都有类似的过积,即都使用了分好类的训练数据集(人脸数据库,每 个人都有很多样本)来进行“训练”,对图像或视频中检测到的人脸进行分析,并从两方面来确定:是否识别到目标,目标真正被识别到的置信度的度量,这也称为置信度评分。

  • Eigenfaces是通过PCA来处理的。PCA是计算机视觉中提到最多的数学概。PCA的本质是识别某个训练集上(比如人脸数据库)的主成分,并计算出训练集(图像或帧中检测到的人脸)相对于数据库的发散程度,并输出一个值。该值越小,表明人脸数据库和检测到的人脸之间差别就越小;0值表示完全匹配。

  • Fisherfaces是从PCA衍生并发展起来的概念,它采用更复杂的逻辑。尽管计算更加密集,但比Eigenfaces更容易得到准确的效果。

  • LBPH粗略地(在非常高的层次上)将检测到的人脸分成小单元,并将其与模型中的对应单元进行比较,对每个区域的匹配值产生一个直方图。由于这种方法的灵活性.LBPH是唯一允许模型样本人脸和检测到的人脸在形状、大小上可以不同的人脸识别算法。个人认为这是最准确的算法,但是每个算法都有其长处和缺点。

5.扩展书籍

看较多网友对此文章有较多疑问,但我也没有较深入去研究具体原理。故无法对你们的提问作出准确的解答,在此推荐一本书给大家,相信能化解你们的疑问![本文章代码也有部分来自此书]
OpenCV 3计算机视觉 Python语言实现(第二版)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

树莓派3B+ 人脸识别(OpenCV) 的相关文章

  • 用于 C++ 中图像分析的 OpenCV 二进制图像掩模

    我正在尝试分析一些图像 这些图像的外部周围有很多噪声 但内部有一个清晰的圆形中心 中心是我感兴趣的部分 但外部噪声正在影响我对图像的二进制阈值处理 为了忽略噪音 我尝试设置一个已知中心位置和半径的圆形蒙版 从而使该圆之外的所有像素都更改为黑
  • 如何计算立体视觉的基本矩阵

    我正在尝试编写一些代码来计算基本矩阵以确定立体图像之间的关系 我从大多数人推荐的 Hartley 和 Zisserman 书开始 但它没有任何实际示例 并且示例代码是在 MATLAB 中 而我没有 然后我切换到这个比较实用 里面有实际例子
  • Opencv - 找不到头文件

    我正在尝试使用 opencv 开始开发 问题是 到目前为止我几乎无法设置 opencv 因为我找不到它的头文件 我对此主题进行了一些研究 但没有一个真正有帮助 下面是一些链接 opencv2 包含文件在哪里 https stackoverf
  • 如何将 opencv mat 图像转换为 gdi 位图

    我想将 openCV Mat 文件转换为 GDI 位图图像 我找不到任何有关如何执行此操作的信息 我认为没有直接的方法可以做到这一点 但我希望它不涉及将其写入文件并读回 http opencv users 1802565 n2 nabble
  • 从 2 个摄像头捕获(OpenCV、Python)[重复]

    这个问题在这里已经有答案了 所以我试图从 openCV 中的两个摄像头 python 和 windows 7 进行捕获 我用一台相机拍摄的效果很好 你也会注意到我正在对图像做一些时髦的事情 但这并不重要 这是尝试使用两个的代码 import
  • ValueError:当数组不是序列时设置带有序列的数组元素

    您好 此代码旨在存储使用 open cv 绘制的矩形的坐标 并将结果编译为单个图像 import numpy as np import cv2 im cv2 imread 1 jpg im3 im copy gray cv2 cvtColo
  • OpenCV 旋转图像而不裁剪澄清

    我想扩展这个主题 参考用户 Lars Schillingmann 给出的这个 SO 问题和接受的答案 在 C 中的 OpenCV 中旋转图像而不裁剪 https stackoverflow com questions 22041699 ro
  • GrabCut - bgdModel 和 fgdModel 为空 - 断言错误

    我正在尝试使用 OpenCV2 1 C 中的 GrabCut 算法进行图像分割 这是我的代码 Mat rgbWorkImage imread argv 1 Mat mask mask Scalar 0 Mat bgdModel fgdMod
  • 在OpenCV中将YUV转换为BGR或RGB

    我有一个电视采集卡 其输入内容为 YUV 格式 我在这里看到了与此问题类似的其他帖子 并尝试尝试所述的所有可能的方法 但它们都没有提供清晰的图像 目前最好的结果是 OpenCVcvCvtColor scr dst CV YUV2BGR 函数
  • 使用opencv+picamera流IO用树莓派捕获视频

    我使用 Raspberry 来简单地显示一个视频 目前仅此 为此 我必须使用 opencv cv2 我尝试了很多解决方案 但现在我想使用 Picamera 库捕获视频 我将向您展示我的代码 import io import time imp
  • 将向量 转换为大小为 (n x 3) 的 Mat,反之亦然

    我有 Point3d 向量 向量形式的点云 如果我使用 OpenCV 提供的转换 比如 cv Mat tmpMat cv Mat pts Here pts is vector
  • OpenCV 中的 Gabor 内核参数

    我必须在我的应用程序中使用 Gabor 过滤器 但我不知道这个 OpenCV 方法参数值 我想对虹膜进行编码 启动 Gabor 过滤器并获取特征 我想对 12 组 Gabor 参数值执行此操作 然后我想计算 Hamming Dystans
  • Python 中的 Lanczos 插值与 2D 图像

    我尝试重新缩放 2D 图像 灰度 图像大小为 256x256 所需输出为 224x224 像素值范围从 0 到 1300 我尝试了两种使用 Lanczos 插值来重新调整它们的方法 首先使用PIL图像 import numpy as np
  • 将图像分割成多个网格

    我使用下面的代码将图像分割成网格的 20 个相等的部分 import cv2 im cv2 imread apple jpg im cv2 resize im 1000 500 imgwidth im shape 0 imgheight i
  • Opencv C++ 检测并裁剪图像上的白色区域

    我在网上搜索过 已经找到了一些方法来完成我想要的事情 但是与我需要的相比 这些方法的效率较低 我有一个 kinect 使用 Microsoft SDK 当前正在获取一个移除背景的人 将结果保存在 3 通道 Mat 中 并将该人从背景中移除
  • Python 2.7从非默认目录打开多个文件(对于opencv)

    我在 64 位 win7 上使用 python 2 7 并拥有 opencv 2 4 x 当我写 cv2 imread pic 时 它会在我的默认 python 路径中打开 pic 即C Users Myname 但是我如何设法浏览不同的目
  • 线程“main”java.lang.UnsatisfiedLinkError中出现异常:java.library.path中没有opencv_java249

    我目前正在尝试在我的 32 位笔记本电脑上设置 OpenCV 但我不断收到一条令我困惑的错误消息 Exception in thread main java lang UnsatisfiedLinkError no opencv java2
  • 通过 cmake 链接作为外部项目包含的 opencv 库[重复]

    这个问题在这里已经有答案了 我对 cmake 比较陌生 经过几天的努力无法弄清楚以下事情 我有一个依赖于 opencv 的项目 它本身就是一个 cmake 项目 我想静态链接 opencv 库 我正在做的是我的项目中有一份 opencv 源
  • 如何根据图像中的对象大小(以像素为单位)来测量现实世界中的对象大小(例如英寸、厘米等)?

    我计算了物体的大小pixel来自包含对象的图像 我想测量现实世界中物体的大小 有没有办法找出乘数来测量实际尺寸 我目前正在使用python以便实施 通常 您将使用相机获取图像 该相机通过镜头将 3 维场景投影到 2 维传感器上 垂直 高度
  • Android 上的硬币识别

    我目前正在开发一个 Android 应用程序 它能够拍摄硬币的现有图像 或者使用内置摄像头扫描单个硬币 非常像 Google Goggles 我正在使用 Android 版 OpenCV 我的问题如下 什么方法最适合使用 OpenCV 在

随机推荐