树莓派应用--AI项目实战篇来啦-7.OpenCV脸部和眼睛检测

news2024/11/24 22:46:17

1. 介绍

        在深度学习时代,人脸识别一般是利用卷积神经网络进行监督式学习,也就是通过让算法(神经网络)自己去发现规律的方式,创造出有用的卷积核,然后利用其进行寻找图片和视频中的人脸,而在这之前,人们需要的则是自己去设计算法,寻找人脸。不过后来人们发明了一种近似于深度学习思路的人脸寻找算法,那就是Haar 算法。
        这个算法简单点来说,就是计算一个区域内不同像素之间的灰度差别,来判断是不是人脸,原理就是一种有规律的图像,比如一个物体,无论光线明亮与否,其不同区域之间的像素差总是有一定规律的。就是凭借这种特殊的思路,科学家们第一次创造出了一种及其有效的人脸识别算法。而且其运算性能要求真的很低。
        OpenCV内部集成了人脸检测算法,并且 OpenCV 提供了训练好的人脸检测Haar模型,使用yml 保存。只需要简单的调用其中的类库就可以对照片或者祝频进行人脸检测。

2. 使用Haar 分类器进行面部及眼睛检测

        以Haar 特征分类器为基础的对象检测技术是一种非常有效的对象检测技术。它是基于机器学习的,通过使用大量的正负样本图像训练得到一个 cascade_function,最后再用它来做对象检测。
现在我们来学习面部检测。开始时,算法需要大量的正样本图像(面部图像)和负样本图像(不含面部的图像)来训练分类器。需要从其中提取特征。下图中的Haar 特征会被使用。它们就像我们的卷积核。每一个特征是一个值,这个值等于黑色矩形中的像素值之后减去白色矩形中的像素值之和。

        使用所有可能的核来计算足够多的特征。(想象一下这需要多少计算量?仅仅是一个24x24的窗口就有160000个特征)。对于每一个特征的计算我们都需要计算白色和黑色矩形内的像素和。为了解决这个问题,引入了积分图像,这可以大大的简化求和运算,对于任何一个区域的像素和只然要对积分图像上的四个像素操作即可。
        但是在我们计算得到的所有的这些特征中,大多数是不相关的。如下图所示。上边一行显示了两个好的特征,第一个特征看上去是对眼部周围区域的描述,因为眼睛总是比鼻子黑一些。第二个特征是描述的是眼晴比鼻梁要黑一些。
        但是如果把这两个窗口放到脸颊的话,就一点都不相关。那么我们怎样从超过160000+个特征中选出最好的特征呢?使用 Adaboost。


        为了达到这个目的,我们将每一个特征应用于所有的训练图像。对于每一个特征,我们要找到它能够区分出正样本和负样本的最佳阈值。但是很明显,这会产生错误或者错误分类。我们要选取错误率最低的特征,这说明它们是检测面部和非面部图像最好的特征。(这个过程其实不像我们说的这么简单。在开始时每一张图像都具有相同的权重,每一次分类之后,被错分的图像的权重会增大。同样的过程会被再做一遍。然后我们又得到新的错误率和新的权重。重复执行这个过程知道到达要求的准确率或者错误率或者要求数目的特征找到)。
        最终的分类器是这些弱分类器的加权和。之所以成为弱分类器是应为只是用这些分类器不足以对图像进行分类,但是与其他的分类器联合起来就是一个很强的分类器了。文章中说200个特征就能够提供 95% 的准确度了。他们最后使用6000个特征。
        现在你有一幅图像,对每一个24x24的窗口使用这 6000个特征来做检查,看它是不是面部。这是不是很低效很耗时呢?的确如此,但作者有更好的解决方法。
        在一副图像中大多数区域是非面部区域。所以虽好有一个简单的方法来证明这个窗口不是面部区域,如果不是就直接抛弃,不用对它再做处理。而不是集中在研究这个区域是不是面部。按照这种方法我们可以在可能是面部的区域多花点时间。
        为了达到这个目的,提出了级联分类器的概念。不是在一开始就对窗口进行这 6000个特征测试,将这些特征分成不同组。在不同的分类阶段逐个使用。(通常前面很少的几个阶段使用较少的特征检测)。如果一个窗口第一阶段的检测都过不了就可以直接放弃后面的测试了,如果它通过了就进入第二阶段的检测。如果一个窗口经过了所有的测试,那么这个窗口就被认为是面部区域。
采用的模型将6000多个特征分为38个阶段,前五个阶段的特征数分别为1,10,25,25和50。(上图中的两个特征其实就是从 Adaboost 获得的最好特征)。

3. 源程序代码

        OpenCV自带了训练器和检测器。如果你想自己训练一个分类器来检测汽车,飞机等的话,可以使用OpenCV构建。
        现在我们来学习一下如何使用检测器。OpenCV 已经包含了很多已经训练好的分类器,其中包括:面部,眼睛,微笑等。下面我们将使用 OpenCV 创建一个面部和眼部检测器。
首先我们要加载需要的XML分类器。然后以灰度格式加载输入图像或者是视频。
然后,我们在图像中检测面部。如果检测到面部,它会返回面部所在的矩形区域Rect(x,y,w,h)。一旦我们获得这个位置,我们可以创建一个ROI 并在其中进行眼部检测。

# 导入必要的库
import numpy as np
import cv2

# 载入HAAR模型
face_cascade = cv2.CascadeClassifier('./images/haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('./images/haarcascade_eye.xml')

# 线程函数操作库
import threading # 线程
import ctypes
import inspect

# 线程结束代码
def _async_raise(tid, exctype):
    tid = ctypes.c_long(tid)
    if not inspect.isclass(exctype):
        exctype = type(exctype)
    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
    if res == 0:
        raise ValueError("invalid thread id")
    elif res != 1:
        ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
        raise SystemError("PyThreadState_SetAsyncExc failed")
        
def stop_thread(thread):
    _async_raise(thread.ident, SystemExit)

import libcamera
from picamera2 import Picamera2

picamera = Picamera2()
config = picamera.create_preview_configuration(main={"format": 'RGB888', "size": (640, 480)},
                                               raw={"format": "SRGGB12", "size": (1920, 1080)})
config["transform"] = libcamera.Transform(hflip=0, vflip=1)
picamera.configure(config)
picamera.start()

# 创建显示控件
def bgr8_to_jpeg(value, quality=75):
    return bytes(cv2.imencode('.jpg', value)[1])
    
import traitlets
import ipywidgets.widgets as widgets
from IPython.display import display
face_imge = widgets.Image(format='jpeg', width=480, height=320)
display(face_imge)

def Video_display():
    while True:      
        frame = picamera.capture_array()
        img = cv2.flip(frame,1)
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        faces = face_cascade.detectMultiScale(gray, 1.3, 5)
        for (x,y,w,h) in faces:
            cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
            roi_gray = gray[y:y+h, x:x+w]
            roi_color = img[y:y+h, x:x+w]
            print(int(x+w/2), int(y+h/2))
            eyes = eye_cascade.detectMultiScale(roi_gray)
            for (ex,ey,ew,eh) in eyes:
                cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)
        face_imge.value = bgr8_to_jpeg(img)
    cap.release()

t = threading.Thread(target=Video_display)
t.setDaemon(True)
t.start()

# 结束线程
stop_thread(t)

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

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

相关文章

【Mac苹果电脑安装】DBeaverEE for Mac 数据库管理工具软件教程【保姆级教程】

Mac分享吧 文章目录 DBeaverEE 数据库管理工具 软件安装完成,打开效果图片Mac电脑 DBeaverEE 数据库管理工具 软件安装——v24.21️⃣:下载软件2️⃣:安装JDK,根据下图操作步骤提示完成安装3️⃣:安装DBeaverEE&#…

【ESP32】ESP-IDF开发 | LED PWM控制器+呼吸灯例程

1. 简介 LED PWM控制器,简称LEDC,主要用于控制LED的亮度和颜色,当然也可以当作普通的PWM进行使用。 LEDC有16路通道,8路高速通道和8路低速通道,16路通道都能够产生独立的数字波形来驱动LED设备。高速和低速通道分别有8…

C++:模拟stack、queue

目录 容器适配器 定义 特点 deque deque的优势与缺点 选择deque作为stack和queue的底层默认容器的原因 模拟实现stack 模拟实现queue 容器适配器 定义 在C标准模板库(STL)中,容器适配器(Container Adapters)是…

Harmony开发基础

背景介绍 鸿蒙系统的开发一来是为了打破国外垄断,实现操作系统的国产化,另一方面是针对目前市场上出现大量新的移动设备,手表,折叠屏等,移动端程序要适配不同设备,需要维护一套代码下的多个版本&#xff0…

U盘直接拔掉之后数据丢失怎么恢复 U盘数据丢失了怎么恢复

U盘作为一种存储设备,可以帮助人们存储很多资料文件,无论是办公文件,亦或是生活中的照片,所以在存储数据文件时,人们是比较依赖U盘。不过,U盘也存在很多的不确定性,比如数据容易丢失、或者损坏。…

NirCmd-sendkeysendkeypress

引入script [Script File] This command allows you to execute a sequence of commands stored inside the file specified in [Script File] parameter. Example: script "c:\temp\msg.ncl" Example for a script:infobox "Hello !" "This is the …

微知-如何查看服务器CPU当前运行主频?(cat /sys/devices/system/cpu/cpu1/cpufreq/scaling_cur_freq)

关键命令 cat /sys/devices/system/cpu/cpu1/cpufreq/scaling_cur_freq背景 首先lscpu可以查看到有多个cpu,里面也会显示cpu的频率,但是这里显示仅仅是规格,不是实际值。为了查看实际值,需要到/sys文件系统中查看,也…

大数据-167 ELK Elasticsearch 详细介绍 特点 分片 查询

点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…

ARIMA 模型初体验 —— 预测股票数据

第 1 步,从 twelvedata 上获取苹果 11 号 15:30 到 16:00 的 OHLC、成交量 数据。 第 2 步,编写 Python 代码(实际上可以用 R 语言,R 语言从语言的级别对分析预测提供了支持,而 Python 需要第三方库)。 …

Yolov8 搭配 Frequency-aware Feature Fusion for Dense Image Prediction

个人觉得论文赞的地方 https://github.com/Linwei-Chen/FreqFusion https://www.arxiv.org/abs/2408.12879 因为我有个项目需要训练边界模糊的情况,但又需要目标能在模糊里凸显出来,就是看到这张图以后觉得很赞,边界变得清晰有特征是我想要的,所以尝试用了 使后感 哈哈…

【CSS3】css开篇基础(2)

1.❤️❤️前言~🥳🎉🎉🎉 Hello, Hello~ 亲爱的朋友们👋👋,这里是E绵绵呀✍️✍️。 如果你喜欢这篇文章,请别吝啬你的点赞❤️❤️和收藏📖📖。如果你对我的…

数据结构-5.2.树的性质

一.树的常考性质: 性质1:结点数 总度数 1(结点的度:结点分支的数量) 一个分支中,如父结点B,两个子结点为E和F,结点B的度的值为2,等于子结点数量,加上这一个父结点(父结点只能有一…

【计算机网络 - 基础问题】每日 3 题(三十九)

✍个人博客:https://blog.csdn.net/Newin2020?typeblog 📣专栏地址:http://t.csdnimg.cn/fYaBd 📚专栏简介:在这个专栏中,我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话,欢迎点赞…

大型语言模型(LLMs)关键技术指南

在AI这个超火的领域,打好基础真的超级重要,尤其是当你开始研究那些超大型的语言模型,也就是LLMs的时候。这个指南就是想帮新手们把那些听起来高大上的概念变得简单易懂,比如神经网络、自然语言处理(NLP)还有…

【ROS2实操一】话题通信与自定义消息

一、准备工作 1.请先创建工作空间 mkdir -p ws01_plumbing/src //创建工作空间 colcon build //在工作空间目录下编译 2.创建专门的接口功能包定义接口文件(需要注意的是,目前为止无法在Python功能包中定义接口文件),终端下进…

线程基础学习

线程的实现 通过实现Runnable接口的方式,实现其中的run方法。继承Thread类,然后重写其中的run方法。通过线程池创建线程,默认采用DefaultThreadFactory。有返回值的callable,实现callable接口,实行call方法。 本质上…

wait和waitpid

在Linux中,wait 和 waitpid 是用于进程控制的系统调用,它们主要用来让父进程等待子进程的终止,并获取子进程的退出状态。下面详细介绍它们的用法和区别。 1. wait() 函数 wait() 会阻塞调用进程,直到一个子进程终止。它的典型用…

怎么ping网络ip地址通不通

怎么Ping网络IP地址通不通?要检查网络中的IP地址是否连通,可以使用‌Ping命令。Ping命令通过发送ICMP(Internet Control Message Protocol,因特网控制消息协议)Echo请求报文并等待回应,来判断目标主机是否可…

ARP限制网速攻击

ARP限制网速攻击 大家没想到吧,ARP还能限制对方网速。当kali欺骗了网关和受害者的时候,受害者访问网络就需要经过kali的网卡,那我们限制kali网卡的速度或者转发的速度就可以限制对方的网速。这里可以使用的工具有tc、iptables、WonderShaper…

Unix Standardization and Implementations

Unix标准化 在Unix未制定较为完备的标准时,各个平台的系统调用方式各异,所开发出的应用程序存在可移植性差的特点,因此人们呼吁指定一套Unix标准来规范接口,增加应用程序的可移植性。所谓Unix标准即适用于Unix环境下的一系列函数…