Python人脸识别

Python人脸识别

    • OpenCV 简介
    • 安装 OpenCV 模块
    • OpenCV 基本使用
    • 人脸检测
    • 使用 OpenCV 进行人脸检测
    • 人脸识别
    • 后序

OpenCV 简介

OpenCV 的全称是 Open Source Computer Vision Library,是一个跨平台的计算机视觉库。 OpenCV 是由英特尔公司发起并参与开发,以 BSD 许可证授权发行,可以在商业和研究领 域中免费使用。OpenCV 可用于开发实时的图像处理、计算机视觉以及模式识别程序。该程序库也可以使用英特尔公司的 IPP 进行加速处理。 OpenCV 用 C++语言编写,它的主要接口也是 C++语言,但是依然保留了大量的 C 语言接口。该库也有大量的 Python、Java and MATLAB/OCTAVE(版本 2.5)的接口。这些语 言的 API 接口函数可以通过在线文档获得。如今也提供对于 C#、Ch、Ruby、GO 的支持。

安装 OpenCV 模块

OpenCV 已经支持 python 的模块了,直接使用 pip 就可以进行安装,命令如下:

pip install opencv-python

若下载缓慢可以通过第三方下载

pip install -i https://mirrors.aliyun.com/pypi/simple 模块名

若安装失败,可能需要更新pip

python -m pip install --upgrade pip

OpenCV 基本使用

  • 读取图片
    显示图像是 OpenCV 最基本的操作之一,imshow()函数可以实现该操作。如果使用过其 他 GUI 框架背景,就会很自然第调用 imshow()来显示一幅图像。imshow()函数有两个参数: 显示图像的帧名称以及要显示的图像本身。直接调用 imshow()函数图像确实会显示,但随 即会消失。要保证图片一直在窗口上显示,要通过 waitKey()函数。waitKey()函数的参数为 等待键盘触发的时间,单位为毫秒,其返回值是-1(表示没有键被按下)
import cv2 as cv 
img=cv.imread('lena.jpg')  # 注意读取图片的路径不能有中文,不然数据读取不出来 
cv.imshow('input image',img) 
cv.waitKey(0)  # 等待键盘的输入 单位是毫秒 传入 0 无限等待 
cv.destroyAllWindows()  # C++语言 使用完内存必须释放
  • 图片灰度转换
    OpenCV 中有数百种关于在不同色彩空间之间转换的方法。当前,在计算机视觉中有三 种常用的色彩空间:灰度、BGR、以及 HSV(Hue,Saturation,Value)。
    (1)灰度色彩空间是通过去除彩色信息来将其转换成灰阶,灰度色彩空间对中间处理 特别有效,比如人脸识别。 (2)BGR 及蓝、绿、红色彩空间,每一个像素点都由一个三元数组来表示,分别代表 蓝、绿、红三种颜色。网页开发者可能熟悉另一个与之相似的颜色空间:RGB 它们只是颜 色顺序上不同。 (3)HSV,H(Hue)是色调,S(Saturation)是饱和度,V(Value)表示黑暗的程度 (或光谱另一端的明亮程度)。 灰度转换的作用就是:转换成灰度的图片的计算强度得以降低。示例如下:
# 将图片灰度转换
import cv2 as cv

# 读取图片
img = cv.imread('0.jpg')
# 显示图片
cv.imshow('BGR_img', img)

# 将图片进行灰度转换
gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
cv.imshow('gray_img', gray_img)

# 保存图片
cv.imwrite('gray_1.jpg', gray_img)

# 等待键盘输入,解决一闪而过 单位毫秒 传入0则是无限等待
cv.waitKey(0)

# 释放内存,由于OpenCv底层是C++写的
cv.destroyAllWindows()
  • 修改图片尺寸
    使用 cv.resize()方法,第一个参数是 要修改的图片对象,第二个参数是 dsize= 传入一个元组,表示图片的(宽度,高度)
# 修改图片大小,用一个变量接收,可以保存或显示
resize_img = cv.resize(img, dsize=(600, 500))
  • 附:设置当键盘输入指定字符后关闭图片
# 等待键盘输入,使图片持续显示
# cv.waitKey(0)
# 只有输入q时候才退出
while True:
    if ord('q') == cv.waitKey(0):  # 返回从键盘输入的键的ascii码值
        break
  • 画图(绘制矩形&圆)
    OpenCV 的强大之处的一个体现就是其可以对图片进行任意编辑,处理。 下面的这个函数最后一个参数指定的就是画笔的大小。
import cv2 as cv

# 加载图片
img = cv.imread('0.jpg')

# 左上角的坐标是(x,y) 矩形的宽度和高度(w,h)
x, y, w, h = 100, 100, 100, 100
cv. rectangle(img, (x, y, x+w, y+w), color=(0, 255, 255), thickness=2)  # 三个色彩的通道, thickness:线条宽度, 绘制矩形传参是两个点
# 绘制圆center元组指原点的坐标
# x, y, r = 200, 200, 100  # x,y原点坐标 r是半径
# cv.circle(img, center=(x, y), radius=r, color=(0, 0, 255))

# 显示图片
cv.imshow('rectangle_img', img)
# 输入键盘内容,关闭图片
cv.waitKey(0)

# 关闭内容
cv.destroyAllWindows()

人脸检测

  • Haar 级联的概念
     摄影作品可能包含很多令人愉悦的细节。但是,由于灯光、视角、视距、摄像头抖动以 及数字噪声的变化,图像细节变得不稳定。人们在分类时不会受这些物理细节方面差异的影响。以前学过,在显微镜下没有两片看起来很像的雪花。幸运的是,作者生长在加拿大,已经学会如何不用显微镜来识别雪花。
     因此,提取出图像的细节对产生稳定分类结果和跟踪结果很有用。这些提取的结果被称为特征,专业的表述为:从图像数据中提取特征。虽然任意像素都可以能影响多个特征,但 特征应该比像素少得多。两个图像的相似程度可以通过它们对应特征的欧氏距离来度量。
      Haar 特征是一种用于实现实时人脸跟踪的特征。每一个 Haar 特征都描述了相邻图像区域的对比模式。例如,边、顶点和细线都能生成具有判别性的特征。
  • 获取 Haar 级联数据
     1.首先我们要进入 OpenCV 官网:https://opencv.org 下载你需要的版本。点击 RELEASES (发布)。
     2.由于 OpenCV 支持好多平台,比如 Windows, Android, Maemo, FreeBSD, OpenBSD, iOS, Linux 和 Mac OS,一般初学者都是用 windows,点击 Windows。
     3.点击 Windows 后跳出新界面,等待 5s 自动下载
     4.然后双击下载的文件,进行安装,实质就是解压一下,解压完出来一个文件夹,其他什 么也没发生。安装完后的目录结构如下。其中 build 是 OpenCV 使用时要用到的一些库文件, 而 sources 中则是 OpenCV 官方为我们提供的一些 demo 示例源码
     5.在 sources 的一个文件夹 data/haarcascades。该文件夹包含了所有 OpenCV 的人脸检测的 XML 文件,这些可用于检测静止图像、视频和摄像头所得到图像中的人脸。
     6,
    人脸检测器(默认):haarcascade_frontalface_default.xml
    人脸检测器(快速 Harr):haarcascade_frontalface_alt2.xml
    人脸检测器(侧视):haarcascade_profileface.xml
    眼部检测器(左眼):haarcascade_lefteye_2splits.xml
    眼部检测器(右眼):haarcascade_righteye_2splits.xml
    嘴部检测器:haarcascade_mcs_mouth.xml
    鼻子检测器:haarcascade_mcs_nose.xml
    身体检测器:haarcascade_fullbody.xml
    人脸检测器(快速 LBP):lbpcascade_frontalface.xml

使用 OpenCV 进行人脸检测

  • 静态图像中人脸检测
     人脸检测首先是加载图像并检测人脸,这也是最基本的一步。为了使所得到的结果有意 义,可在原始图像的人脸周围绘制矩形框
    示例:
# 人脸检测
import cv2 as cv

def face_detect():
    # 将图片灰度处理,降低色彩的通道
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    # 加载特征数据
    face_detector = cv.CascadeClassifier('D:/Python/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
    face = face_detector.detectMultiScale(gray)

    for x, y, w, h in face:  # 坐标及宽度高度
        cv.rectangle(img, (x, y), (x+w, y+h), color=(0, 255, 0), thickness=2)  # img所画图片,坐标,颜色,宽度
    # 显示
    cv.imshow('result', img)


# 加载图片
img = cv.imread('lena.jpg')

# 人脸检测
face_detect()

cv.waitKey(0)

cv.destroyAllWindows()
  • 当图片中人数较多时,识别需要指定参数,限定识别范围参数: scaleFactor(比例因子):图片缩放多少,minNeighbors:至少检测多少次,minSize maxSize:当前检测区域的最大最小面积。
# 将照片灰度
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 加载特征数据
face_detector = cv.CascadeClassifier('D:/Python/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
# 参数: scaleFactor(比例因子):图片缩放多少,minNeighbors:至少检测多少次,minSize maxSize:当前检测区域的最大最小面积
faces = face_detector.detectMultiScale(gray)  # , scaleFactor=1.01, minNeighbors=3, maxSize=(33, 33), minSize=(28, 28)
  • 视频中的人脸检测
    视频是一张一张图片组成的,在视频的帧上重复这个过程就能完成视频中的人脸检测。
import cv2 as cv

# 检测图片
def face_detect(img):
    # 灰度处理
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    # 加载特征数据
    face_detector = cv.CascadeClassifier('D:/Python/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
    # 参数: scaleFactor(比例因子):图片缩放多少,minNeighbors:至少检测多少次,minSize maxSize:当前检测区域的最大最小面积
    faces = face_detector.detectMultiScale(gray)  # scaleFactor=1.01, minNeighbors=3, maxSize=(33, 33), minSize=(28, 28)

    # 遍历检测到的区域
    for x, y, w, h in faces:
        cv.rectangle(img, (x, y), (x+w, y+h), color=(0, 0, 255), thickness=2)
        cv.circle(img, center=(x+w//2, y+h//2), radius=w//2, color=(0, 255, 0), thickness=2)

    # 显示图片
    cv.imshow('result', img)

# 读取视频
cap = cv.VideoCapture('video.mp4')

# 视频是重复播放,用循环来接收
while True:
    flag, frame = cap.read()
    print('flag', flag, 'frame', frame.shape)
    # 如果视频播放停止,则跳出循环
    if not flag:
        break
    # 将每一张图片传进去进行检测
    face_detect(frame)
    # 等待键盘10s若输入q则关闭
    if ord('q') == cv.waitKey(10):
        break

cv.destroyAllWindows()
cap.release()

人脸识别

  人脸检测是 OpenCV 的一个很不错的功能,它是人脸识别的基础。
   人脸识别其实就是一个程序能识别给定图像或视频中的人脸。实现这一目标的方法之一是用一系列分好类的图像来“训练”程序,并基于这些图像来进行识别。这就是OpenCV 及其人脸识别模块进行人脸识别的过程。 人脸识别模块的另外一个重要特征是:每个识别都具有转置信(confidence)评分,因此可在实际应用中通过对其设置阈值来进行筛选。人脸识别所需要的人脸可以通过两种方式来得到:自己获得图像或从人脸数据库免费获得可用的人脸图像。互联网上有许多人脸数据库:为了对这些样本进行人脸识别,必须要在包含人脸的样本图像上进行人脸识别。这是一 个学习的过程,但并不像自己提供的图像那样令人满意。

  • 训练数据
      有了数据,需要将这些样本图像加载到人脸识别算法中。所有的人脸识别算法在它们的 train()函数中都有两个参数:图像数组和标签数组。这些标签表示进行识别时候某人人脸的 ID,因此根据 ID 可以知道被识别的人是谁。要做到这一点,将在「trainer/」目录中保存为.yml 文件。
     在使用 Python 3 &OpenCV 3.0.0 进行人脸识别训练时发现异常: AttributeError: ‘module’ object has no attribute ‘LBPHFaceRecognizer_create’OpenCV 需要安装 opencv-contrib-python 模块,直接使用 pip 就可以进行安装,命令如下:
pip install opencv-contrib-python
  • 安装opencv-contrib-python模块可能出现的问题:

1.下载缓慢引起超时timeout问题

pip --default-timeout=100 install -U opencv-contrib-python

2.该模块较大官方途径下载缓慢,推荐使用第三方通道下载

pip install -i https://mirrors.aliyun.com/pypi/simple opencv-contrib-python

示例:
需要在当前目录下创建datatrainer两个文件夹,分别存放要识别的人脸的多张.pgm照片训练完的数据

附:PGM 是便携式灰度图像格式(portable graymap file format),在黑白超声图像系统中经常使用PGM格式的图像。文件的后缀名为”.pgm”,PGM格式图像格式分为两类:P2和P5类型。不管是P2还是P5类型的PGM文件,都由两部分组成,文件头部分和数据部分。)

import os
import cv2
from PIL import Image
import numpy as np

def getImageAndLabels(path):
    facesSamples = []
    ids = []
    imagePaths = [os.path.join(path, f) for f in os.listdir(path)]

    # 检测人脸
    # 加载特征数据
    face_detector = cv2.CascadeClassifier(
        'D:/Python/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
    # 参数: scaleFactor(比例因子):图片缩放多少,minNeighbors:至少检测多少次,minSize maxSize:当前检测区域的最大最小面积
    # scaleFactor=1.01, minNeighbors=3, maxSize=(33, 33), minSize=(28, 28)

    # 遍历列表中的图片
    for imagePath in imagePaths:
        # 打开当前图片
        PIL_img = Image.open(imagePath).convert('L')

        # 将图片转化为数组
        img_numpy = np.array(PIL_img, 'uint8')
        faces = face_detector.detectMultiScale(img_numpy)

        # 获取每张图片的id
        id = int(os.path.split(imagePath)[1].split('.')[0])

        # 获取人脸区域
        for x, y, w, h in faces:
            # 进行切片处理,获取图像数组和id
            facesSamples.append(img_numpy[y:y+h, x:x+w])
            ids.append(id)

        return facesSamples, ids


if __name__ == '__main__':
    # 图片路径
    path = './data/jm/'
    # 获取图像数组和id标签数组
    faces, ids = getImageAndLabels(path)

    # 获取循环对象
    recognizer = cv2.face.LBPHFaceRecognizer_create()
    recognizer.train(faces, np.array(ids))

    # 保存文件
    recognizer.write('trainer/trainer.yml')

  • 基于 LBPH 的人脸识别
    LBPH(Local Binary Pattern Histogram)将检测到的人脸分为小单元,并将其与模型中的对应单元进行比较,对每个区域的匹配值产生一个直方图。由于这种方法的灵活性,LBPH 是唯一允许模型样本人脸和检测到的人脸在形状、大小上可以不同的人脸识别算法。
     调整后的区域中调用 predict()函数,该函数返回两个元素的数组:第一个元素是所识别 个体的标签,第二个是置信度评分。所有的算法都有一个置信度评分阈值,置信度评分用来 衡量所识别人脸与原模型的差距,0 表示完全匹配。可能有时不想保留所有的识别结果,则需要进一步处理,因此可用自己的算法来估算识别的置信度评分。LBPH 一个好的识别参考值要低于 50 ,任何高于 80 的参考值都会被认为是低的置信度评分。

示例:

import cv2

# 加载训练数据集文件

# 获取人脸识别对象
recognizer = cv2.face.LBPHFaceRecognizer_create()
# 读取训练数据
recognizer.read('trainer/trainer.yml')

# 准备识别图片
img = cv2.imread('6.pgm')

# 将图片灰度
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 加载特征数据
face_detector = cv2.CascadeClassifier('D:/Python/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
# 参数: scaleFactor(比例因子):图片缩放多少,minNeighbors:至少检测多少次,minSize maxSize:当前检测区域的最大最小面积
faces = face_detector.detectMultiScale(gray)  # scaleFactor=1.01, minNeighbors=3, maxSize=(33, 33), minSize=(28, 28)

# 获取脸部特征值
for x, y, w, h in faces:
    cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), thickness=2)
    cv2.circle(img, (x+w//2, y+h//2), radius=w//2, thickness=2, color=(0, 0, 255))

    # 人脸识别
    id, confidence = recognizer.predict(gray[y:y+h, x:x+w])
    print('标签id:', id, '置信评分:', confidence)


# 显示图片
cv2.imshow('result', img)
cv2.waitKey(0)  # 一直显示
cv2.destroyAllWindows()  # 释放资源

后序

继续深究人脸识别领域后,将更新文章。

感谢跟随老师的代码在未知领域里探索,希望我能走的更高更远

你可能感兴趣的:(Python,python,神经网络,机器学习)