人脸识别概述

news2024/12/22 22:04:59

 博主简介

博主是一名大二学生,主攻人工智能研究。感谢让我们在CSDN相遇,博主致力于在这里分享关于人工智能,c++,Python,爬虫等方面知识的分享。 如果有需要的小伙伴可以关注博主,博主会继续更新的,如果有错误之处,大家可以指正。

专栏简介:   本专栏主要研究计算机视觉,涉及算法,案例实践,网络模型等知识。包括一些常用的数据处理算法,也会介绍很多的Python第三方库。如果需要,点击这里订阅专栏   。

给大家分享一个我很喜欢的一句话:“每天多努力一点,不为别的,只为日后,能够多一些选择,选择舒心的日子,选择自己喜欢的人!”


目录

人脸识别的主要方法

1.基于几何特征的方法

2.特征脸方法

3.渔夫脸方法

4.基于弹性匹配

5.基于支持向量机(SVM)的方法

6. 基于神经网络的方法

深度学习方法


其实人脸识别在前面我们已经介绍过了,不过那个时候介绍的人脸识别是基于opencv的识别,使用的是已经训练好的数据集。所以,对于人脸识别这个章节的学习,其实已经不需要太多的说明,主要是讲解一下基于深度学习的人脸识别。

人脸识别的主要方法

1.基于几何特征的方法

几何特征的检测方法最早是由Kelly和Kannade提出,现在基本上已经不用了,根据名字就可以得出,这个检测方法就是根据脸部的一些特征,比如眼睛的大小,鼻子的大小,眼睛到鼻子的距离等等一些基本特征点,所以说,它的优缺点也显而易见,识别简单,速度快,缺点却也很明显,每个人的脸部特征都是不一样的,没有办法做到非常准确,尤其是现在发展的人脸识别扫码支付,如果只是用特征检测,那么很有可能会导致识别错乱,造成不可估量的后果。但是也不是完全不能发展,现在的人来能识别都是二维的,并不能做到三维,如果说能够做到三维的识别,那么几何特征的识别将是非常出众的。

2.特征脸方法

MIT的Turk和Pentland在1991年提出的人脸识别算法,其实简单的来说,就是将识别到的脸放在一个目标空间中,和已经存在的人脸进行匹配,就是对于一个模板的匹配。优缺点肯定也很明显,优点就是快速,一旦匹配成功,就基本不会出错,缺点就是数据库中必须存在这个人脸模板,人脸识别的时候必须保持和数据库中的人脸模板具有相同的特征,识别效果差,可应用范围小。

具体的步骤如下:

(1)、将所有人脸图像变成Nx1的向量,然后将所有人脸向量组成矩阵M。

(2)、对矩阵M做归一化

(3)、求矩阵M的协方差矩阵C。

(4)、求协方差矩阵C的特征值和特征向量,并将最大的R个特征值对应的特征向量按行组成矩阵P,此时P就是算法希望找到的空间转换。

3.渔夫脸方法

由 Belhumeur提出,在特征脸的基础上,加入线性判别分析方法,该方法目前依旧是主流的人脸识别之一。基本思想就是同一人脸由于光照条件和角度变化带来的差异往往要大于不同人脸之间的差异,所以要将这些特征删除,方法就是应用线性判别分析,使得类内的散度最小。具体算法步骤:

(1)、将所有人脸图像变成Nx1的向量。

(2)、应用PCA降维(与特征脸方法类似),得到人脸向量x_{n}

(3)、对所有图像求平均值u

(4)、对每一类(同一人脸)做平均值得到:u_{i}

(5)、计算类间散度:S_{B}=\sum N_{i}(u_{i}-u)(u_{i}-u)^{T},N_{i}为i类的数量。

(6)、计算类内散度:S_{w}=\sum \sum _{x_{k}}(x_{k}-u_{i})(x_{k}-u_{i})^{T}

(7)、对目标函数(投影矩阵)求极值:W=argmax\frac{W^{T}S_{B}W}{W^{T}S_{w}W}

 

#渔夫脸方法
import sys
import os
import cv2
import numpy as np

class SkinDetector():
    """
    对颜色空间取阈值
    """
    def _R1(self,BGR):
        B = BGR[:,:,0]
        G = BGR[:,:,1]
        R = BGR[:,:,2]
        e1 = (R>95) & (G>40) & (B>20) & ((np.maximum(R,np.maximum(G,B)) - np.minimum(R, np.minimum(G,B)))>15) & (np.abs(R-G)>15) & (R>G) & (R>B)
        e2 = (R>220) & (G>210) & (B>170) & (abs(R-G)<=15) & (R>B) & (G>B)
        return (e1|e2)
    
    def _R2(self,YCrCb):
        Y = YCrCb[:,:,0]
        Cr = YCrCb[:,:,1]
        Cb = YCrCb[:,:,2]
        e1 = Cr <= (1.5862*Cb+20)
        e2 = Cr >= (0.3448*Cb+76.2069)
        e3 = Cr >= (-4.5652*Cb+234.5652)
        e4 = Cr <= (-1.15*Cb+301.75)
        e5 = Cr <= (-2.2857*Cb+432.85)
        return e1 & e2 & e3 & e4 & e5
    
    def _R3(self,HSV):
        H = HSV[:,:,0]
        S = HSV[:,:,1]
        V = HSV[:,:,2]
        return ((H<25) | (H>230))
    
    def detect(self, src):
        if np.ndim(src) < 3:
            return np.ones(src.shape, dtype=np.uint8)
        if src.dtype != np.uint8:
            return np.ones(src.shape, dtype=np.uint8)
        srcYCrCb = cv2.cvtColor(src, cv2.COLOR_BGR2YCR_CB)
        srcHSV = cv2.cvtColor(src, cv2.COLOR_BGR2HSV)
        skinPixels = self._R1(src) & self._R2(srcYCrCb) & self._R3(srcHSV)
        return np.asarray(skinPixels, dtype=np.uint8)

class CascadedDetector():
    """
    利用OpenCV函数构建检测器,可调参数:scaleFactor、minNeighbors、minSize
    """
    def __init__(self, cascade_fn="C:\Users\Administrator\AppData\Local\Programs\python\Python310\Lib\site-packages\cv2\data\haarcascade_frontalface_alt2.xml", scaleFactor=1.2, minNeighbors=5, minSize=(30,30)):
        self.cascade = cv2.CascadeClassifier(cascade_fn)
        self.scaleFactor = scaleFactor
        self.minNeighbors = minNeighbors
        self.minSize = minSize
    
    def detect(self, src):
        if np.ndim(src) == 3:
            src = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
        src = cv2.equalizeHist(src)
        rects = self.cascade.detectMultiScale(src,scaleFactor=self.scaleFactor, minNeighbors=self.minNeighbors, minSize=self.minSize)
        if len(rects) == 0:
            return np.ndarray((0,))
        rects[:,2:] += rects[:,:2]
        return rects

class SkinFaceDetector():
    """
    只接受与肤色相近的候选人脸
    """
    def __init__(self, threshold=0.3, cascade_fn='C:\Users\Administrator\AppData\Local\Programs\python\Python310\Lib\site-packages\cv2\data\haarcascade_frontalface_alt2.xml', scaleFactor=1.2, minNeighbors=5, minSize=(30,30)):
        self.faceDetector = CascadedDetector(cascade_fn=cascade_fn, scaleFactor=scaleFactor, minNeighbors=minNeighbors, minSize=minSize)
        self.skinDetector = SkinDetector()
        self.threshold = threshold

    def detect(self, src):
        rects = []
        for i,r in enumerate(self.faceDetector.detect(src)):
            x0,y0,x1,y1 = r
            face = src[y0:y1,x0:x1]
            skinPixels = self.skinDetector.detect(face)
            skinPercentage = float(np.sum(skinPixels)) / skinPixels.size
            print(skinPercentage)
            if skinPercentage > self.threshold:
                rects.append(r)
        return rects
        
if __name__ == "__main__":
    #输入图像
    if len(sys.argv) < 2:
        raise Exception("No image given.")
    inFileName = sys.argv[1]
    outFileName = None
    #输出目录
    if len(sys.argv) > 2:
        outFileName = sys.argv[2]
    if outFileName == inFileName:
        outFileName = None
    #开始检测
    img = np.array(cv2.imread('F:\Image\\test16.jpg'), dtype=np.uint8)
    imgOut = img.copy()
    detector = CascadedDetector(cascade_fn="C:\Users\Administrator\AppData\Local\Programs\python\Python310\Lib\site-packages\cv2\data\haarcascade_frontalface_alt2.xml")
    eyesDetector = CascadedDetector(scaleFactor=1.1,minNeighbors=5, minSize=(20,20), cascade_fn="C:\Users\Administrator\AppData\Local\Programs\python\Python310\Lib\site-packages\cv2\data\haarcascade_eye.xml")
    for i,r in enumerate(detector.detect(img)):
        x0,y0,x1,y1 = r
        cv2.rectangle(imgOut, (x0,y0),(x1,y1),(0,255,0),1)
        face = img[y0:y1,x0:x1]
        for j,r2 in enumerate(eyesDetector.detect(face)):
            ex0,ey0,ex1,ey1 = r2
            cv2.rectangle(imgOut, (x0+ex0,y0+ey0),(x0+ex1,y0+ey1),(0,255,0),1)
    #显示图片
    if outFileName is None:
        cv2.imshow('faces', imgOut)
        cv2.waitKey(0)
        cv2.imwrite(outFileName, imgOut)

4.基于弹性匹配

Wiskott于1997年使用Gabor小波对人脸图像进行处理,将人脸表达成由若干个 特征点构成的并具有一定拓扑结构信息的人脸弹性图。图的顶点代表关键特征点(Jet),边的属性则为不同特征点之间的关系。此方法用了全局特征,还用了局部特征。

什么叫Gabor小波?为什么要用Habor小波?

Gabor小波是以任意一个高斯函数作为窗口函数的波函数。一个图像像素与不同的Gabor核卷积后的系数集合称为一个Jet(一般为40个系数)。一个jet描述了一个像素周围一小块的灰度。

用Gabor小波的原因是因为Gabor小波对于亮度变化和人脸的不同表情不敏感,匹配精度大大提高。

搜索步骤:

(1)、对每个特征点,从图像中定位起粗略位置(x_{i},y_{i})

(2)、在以标准化的人脸图像中计算出(x_{i},y_{i})处的Gabor变换系数。

(3)、将J_{i}与模板中的特征点进行比较,其中相似度最高的为候选者J_{i}',计算其位置误差d_{i}=J_{i}'-J_{i},则特征点的精确位置修正为(x_{i}',y_{i}')=(x_{i},y_{i})+d

(4)、重复上述步骤,将最后的得到的精确点的求出Gaboe系数即可。

5.基于支持向量机(SVM)的方法

SVM在后面的专栏会做出详细的介绍,这里就不过多的介绍,SVM分类器训练为一个二分类器(人脸和非人脸),当然也可以每一类训练一个SVM分类器。其实就是利用分类器的特点进行匹配。

6. 基于神经网络的方法

基于神经网络的方法前面已经介绍过,不需要我们来提取特征点,只需要利用已经训练好的样本就可以,尤其是近年来深度学习的快速发展,神经网络的检测也越来越受到欢迎,不过缺点就是需要大量的训练。

深度学习方法

深度学习中对于图像的处理发展最快的就是卷积神经网络,所以对于人脸识别,大多数时候都采用卷积神经网络方法进行训练测试,但是深度学习是一个很复杂的知识脉络,这里不能很深渡的介绍,所以深度学习就放在另一个专栏中介绍,这里就只是简单的介绍一下。

神经网络训练模型有很多,比如GoogleNet、VGG16、YOLO等模型,他们的原理前面都介绍过了,神经网络基本上都差不多,所以他们的具体步骤就不过多介绍。主要就是其中卷积层,全连接层,池化层的操作,以及一些激活函数,损失函数,优化分类器的选择。下面就给出了一个示例,后面对于神经网络的搭建也会深度介绍。

#深度学习人脸识别方法
import os
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Conv2D, Flatten, Dropout, MaxPooling2D
import cv2
import numpy as np
from sklearn.model_selection import train_test_split

faces_path = '人脸数据集位置'
imgs = []
labels = []
#读取数据
for filename in os.listdir(faces_path):
    if filename.endswith('.jpg'):
        filename = path + '/' + filename
        img = cv2.imread(filename)
        imgs.append(img)
        labels.append(filename[-1])
#将图片数据与标签转换成数组
imgs = np.array(imgs)
labels = np.array(labels)
#划分训练集与测试集
train_x,test_x,train_y,test_y = train_test_split(imgs, labels, test_size=0.2)
#统一人脸图像大小
train_x = train_x.reshape(train_x.shape[0], 100, 100, 3)
test_x = test_x.reshape(test_x.shape[0], 100, 100, 3)
#归一化
train_x = train_x.astype('float32')/255.0
test_x = test_x.astype('float32')/255.0

batch_size = 64
num_batch = len(train_x) //batch_size

#网络
model = Sequential([
    Conv2D(32, 3, padding='same', activation='relu', input_shape=(100, 100,3)),
    MaxPooling2D(),
    Dropout(0.5)
    Conv2D(64, 3, padding='same', activation='relu'), 
    MaxPooling2D(),
    Dropout(0.5),
    Conv2D(64, 3, padding='same', activation='relu'),
    MaxPooling2D(),
    Dropout(0.5),
    Conv2D(64, 3, padding='same', activation='relu'),
    MaxPooling2D(),
    Dropout(0.5),
    Flatten(),
    Dense(256, activation='relu'),
    Dense(1, activation='sigmoid')
])
#编译模型,输入优化器、损失函数
model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])
#训练
model.fit(train_x, train_y,epoch=10, batchsize = 64)
#测试
model.eval(test_x, test_y)

好了,本节的只是就到此结束了,计算机视觉专栏也就到此结束了,后面就进入深度学习专栏了。由于博主能力有限,如果后面有其他知识,会补充到这里的。再见了

 

点赞加关注不迷路

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/466567.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

封装 (encapsulation)--计算机程序术语

封装&#xff0c;即隐藏对象的属性和实现细节&#xff0c;仅对外公开接口&#xff0c;控制在程序中属性的读和修改的 访问级别&#xff1b;将抽象得到的数据和行为(或功能)相结合&#xff0c;形成一个有机的整体&#xff0c;也就是将数据与操作数据的 源代码进行有机的结合&…

以轻量级服务器niginx为核心的JavaWeb项目:第一章 项目设计

这里写目录标题 一 需求分析与环境搭建1.需求分析2.环境搭建1.2.1首先配置mysql环境1.2.2 配置maven环境 二 打成War包&#xff0c;发到linux上 一 需求分析与环境搭建 1.需求分析 2.环境搭建 1.2.1首先配置mysql环境 先查找一下mysql环境 [roothadoop122 ~]# mysql --vers…

SpringCloudAlibaba分布式事务——Seata

Seata 本专栏学习内容来自尚硅谷周阳老师的视频 有兴趣的小伙伴可以点击视频地址观看 分布式事务问题 在使用分布式之前&#xff0c;一般都是单机单库或者是单机多库的情况&#xff0c;一个服务对应一个数据库或者多个数据库&#xff0c;这样事务的问题可以通过Transaction解决…

Python学习:Anaconda23.3.1+spyder5.4.3+Python3.10.11环境配置

问题1&#xff1a;Anaconda安装配置教程&#xff08;真的非常详细的安装过程&#xff0c;还带环境配置&#xff09; 【参考文献】本文链接&#xff1a;Windows安装Anaconda使用教程_在奋斗的大道的博客-CSDN博客 问题2&#xff1a;Anaconda半天打不开&#xff0c;就在这转啊转…

MYSQL(六)函数

函数是指一段可以直接被另一端程序调用的代码 字符串函数 update employees set workn lpad(workno,5, 0); 数值函数 根据数据库的函数&#xff0c;生成一个六位数的随机验证码 select rpad(round(rand()*1000000, 0), 6, 0); 日期函数 流程函数

尚融宝24-标的管理

目录 一、需求介绍 &#xff08;一&#xff09;借款人申请借款 &#xff08;二&#xff09;流程 二、生成新标的 三、标的列表 &#xff08;一&#xff09;后端 &#xff08;二&#xff09;前端 四、标的详情 &#xff08;一&#xff09;后端 &#xff08;二&#xf…

FPGA动态配置si5338输出差分时钟,提供工程源码和技术支持

目录 1、前言2、设计框图3、si5338原理图设计4、si5338使用流程5、vivado工程详解6、上板调试验证并演示7、福利&#xff1a;工程代码的获取 1、前言 如今的FPGA板卡随着FPGA本身性能的提高也越来越高端&#xff0c;特别是在高速接口方面表现得越发明显&#xff0c;以Xilinx的…

Redis(10)哨兵

redis哨兵 哨兵配置步骤步骤一 启动redis节点步骤二 配置哨兵节点第三步 设置主从复制第四步 查看状态第五步 验证哨兵配置是否成功第六步 测试 哨兵配置步骤 本文将介绍redis哨兵的配置步骤。Redis哨兵是一种用于监控Redis主从复制和自动故障转移的系统 Redis哨兵是Redis的核…

“探索C++非质变算法:如何更高效地处理数据“

&#x1f4d6;作者介绍&#xff1a;22级树莓人&#xff08;计算机专业&#xff09;&#xff0c;热爱编程&#xff1c;目前在c&#xff0b;&#xff0b;阶段>——目标Windows&#xff0c;MySQL&#xff0c;Qt&#xff0c;数据结构与算法&#xff0c;Linux&#xff0c;多线程&…

无线电设备发射型号核准证(SRRC)

SRRC认证简介 SRRC为国家无线电管理委员会State Radio Regulatory Commission of the People’s Republic of China SRMC认证(又称SRRC认证)自1999年6月1日起&#xff0c;中国信息产业部(Ministry of Information Industry,MII)强制规定&#xff0c;所有在中国境内销售及使用的…

【c语言】static静态变量

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 给大家跳段街舞感谢支持&#xff01;ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ…

C++【二叉搜索树】

文章目录 一、二叉搜索树&#xff08;1&#xff09;概念&#xff08;2&#xff09;操作&#xff08;3&#xff09;应用 二、BST模拟实现及函数解析&#xff08;1&#xff09;构建BST结点结构体&#xff08;2&#xff09;BST默认构造及拷贝构造&#xff08;3&#xff09;BST赋值…

2023亚马逊云科技行业峰会,汇聚行业专家分享行业数字化创新之道

从实验室扩展到真实世界&#xff0c;从前沿技术探索到医疗生命科学行业的快速创新实践&#xff0c;亚马逊云科技不断地通过数字化助力医疗和生命科学的行业创新。由上海徐汇区科委指导&#xff0c;上海枫林集团作为支持单位&#xff0c;亚马逊云科技主办的2023亚马逊云科技医疗…

yum仓库及NFS共享服务

部署yum仓库及NFS共享服务 一、yum仓库服务yum概述源种类&#xff1a; 二、安装源安装ftp源安装在线源本地源和在线源同时使用将软件包变成Yum源 三、NFS共享存储服务NFS架构NFS原理 四、NFS实操 一、yum仓库服务 yum概述 基于RPM包构建的软件更新机制可以自动解决依赖关系所…

LVS负载均衡群集部署—NAT

目录 一、群集的概述1、群集的含义2、出现高并发的解决方法3、群集的三种分类3.1负载均衡群集3.2高可用群集3.3高性能运算群集 4、负载均衡的结构 三、LVS调度器用的调度方法四、LVS的工作模式及其工作过程1.NAT模式&#xff08;VS-NAT&#xff09;2.直接路由模式&#xff08;V…

冲实习 or 全力准备秋招?

作者&#xff1a;阿秀 校招八股文学习网站&#xff1a;https://interviewguide.cn 这是阿秀的第「261」篇原创 小伙伴们大家好&#xff0c;我是阿秀。 欢迎今年参加秋招的小伙伴加入阿秀的学习圈&#xff0c;目前已经超过 2300 小伙伴加入&#xff01;去年认真准备和走下来的基…

ADKEY多按键制作阻值选择

参考链接 (10条消息) 【物尽其用】ADKEY多按键制作与经验分享_SimpleJY的博客-CSDN博客https://blog.csdn.net/qq_31247231/article/details/81013459其中的阻值选择经过仿真电路 仿真结果如下表 按键序号ad值键值差0409337113722907228151813263458742047975195028261668657…

数字硬件建模SystemVerilog-通信总线建模 --Interface方法

来到了SV最后一部分&#xff0c;预计三篇文章&#xff0c;两周更完&#xff0c;所有的思维导图如下&#xff1a; 概述 SystemVerilog Interface是modport的一种&#xff0c;但比简单的输入、输出或输入输出端口的功能更多。在其最简单的形式中&#xff0c;Interface端口将相关的…

第5章 数据结构之“链表”

链表简介 1.多个元素组成的列表。 2.元素的存储不连续&#xff0c;用next指针连在一起。 数组 vs 列表 数组&#xff1a;增删非手尾元素时往往需要移动元素。如果要在数组中增加一个元素&#xff0c;数组后面的所有元素需要往后面移动一位。如果在数组中删除一个元素&#x…

Hive ---- Hive 安装

Hive ---- Hive 安装 1. Hive安装地址2. Hive安装部署1. 安装Hive2. 启动并使用Hive 3. MySQL安装1. 安装MySQL2. 配置MySQL3. 卸载MySQL说明 4. 配置Hive元数据存储到MySQL1. 配置元数据到MySQL2. 验证元数据是否配置成功3. 查看MySQL中的元数据 5. Hive服务部署1. hiveserver…