使用 esp32-cam 搭配 opencv 实现人脸识别

前提摘要

之前介绍了如何通过 esp32-cam 实现一个家用监控。但是光有监控没有智能识别总少了点味道,所以本文主要是探索人脸识别 + 物体识别的功能。

原理很简单,这里需要一个上位机和一个下位机。上位机用来算法处理接受到的数据,下位机用来接收处理完之后的内容。并通过构建一个可视化窗口展示结果。

思维导图

这里的上位机就是香橙派,下位机就是 esp32。我们可以理解成esp32 拍摄的数据就是没加字幕的电影,而 orangePI 就是加字幕工具,加好字幕之后呈现在我们面前的就是所谓的熟肉

本文主要的难点就是捕获esp32 的视频流数据,然后对原始视频流进行二次加工的过程。

准备

  1. esp32-cam x 1
  2. 香橙派 zero3 x1 (这个按需求来,只要是服务器就行)
  3. 杜邦线若干

环境搭建

在这个案例中需要注意的是我们需要了解一些关于 python 相关的知识。环境部分为 esp32-cam 部分和 opencv 部分。编辑器都是统一用的 vscode(我就是它的脑残粉)

1. esp32-cam 部分

这个可以参考我之前的案例,其它的基本没有什么大的改动,照抄就行。

2. opencv部分

重点是这个部分,我们需要安装一个 python 环境来支持这个功能的使用。安装 python 直接上官网下载自己需要的平台,下载最新的就好(3.0 版本的)。然后通过控制台输入以下命令:

1
2
python --version
// or python3 --version

如果输出版本号就说明安装成功了。

接下来就安装 opencv 的依赖包了。输入以下命令:

1
2
pip install opencv-python requests
// or pip3 install opencv-python requests

这里安装接下来需要用到的两个依赖包。

然后在当前摄像头项目根目录下新建一个文件,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import cv2
import numpy as np
import requests

url = 'http://192.168.xx.xx:81/stream' // 这里填入当前 esp32 访问的 web 地址即可
cap = cv2.VideoCapture(url)

if not cap.isOpened():
print("Failed to open video stream!")
exit()

#初始化人脸识别器(默认的人脸haar级联)
prototxt_path = "used/deploy.prototxt.txt" // 这个文件可以去 opencv 官方网站去下载
model_path = "used/res10_300x300_ssd_iter_140000.caffemodel" // 这个文件可以去 opencv 官方网站去下载
model = cv2.dnn.readNetFromCaffe(prototxt_path, model_path)
flash = 0
frame = 9
requests.get("http://192.168.xx.xx/flash?var=led_intensity&val={}".format(flash))

# 设置视频编码器和输出文件
def face_select(image):
h, w = image.shape[:2]
blob = cv2.dnn.blobFromImage(image, 1.0, (300, 300))
model.setInput(blob)
output = np.squeeze(model.forward())
for i in range(0, output.shape[0]):
confidence = output[i, 2]
if confidence > 0.9:
box = output[i, 3:7] * np.array([w, h, w, h])
start_x, start_y, end_x, end_y = box.astype(np.int64)
cv2.rectangle(image, (start_x, start_y), (end_x, end_y), color=(255, 0, 0), thickness=2)

cv2.putText(image, f"{confidence*100:.2f}%", (start_x, start_y-5), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
cv2.putText(image, f"{confidence*100:.2f}%", (start_x, start_y-5), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
cv2.putText(image, f"flash:{flash:d}", (5, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
cv2.putText(image, f"frame:{frame:d}", (5, 60), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)

cv2.imshow('image',image)

while True:
_, image = cap.read()
face_select(image)
key=chr(cv2.waitKey(1) & 0xFF)
# 按下 'q' 键退出循环
if key == 'q':
cv2.destroyAllWindows()
break
cap.release()

很简单的操作。

拓展

对于之前 esp32-cam 的代码由于使用的是示例代码没有什么好讲的。填好 wifi 信息,然后通过控制台打印的 ip 地址访问即可。

但是示例代码里面的几个 api 我们可以了解一下,比如 /status 这个 api,通过这个 api 我们可以获取在示例代码的环境下可以修改的参数。以下是可以修改的所有参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
"0xd3": 8,
"0x111": 0,
"0x132": 9,
"xclk": 20,
"pixformat": 4,
"framesize": 8,
"quality": 10,
"brightness": 0,
"contrast": 0,
"saturation": 0,
"sharpness": 0,
"special_effect": 0,
"wb_mode": 0,
"awb": 1,
"awb_gain": 1,
"aec": 1,
"aec2": 0,
"ae_level": 0,
"aec_value": 168,
"agc": 1,
"agc_gain": 0,
"gainceiling": 0,
"bpc": 0,
"wpc": 1,
"raw_gma": 1,
"lenc": 1,
"hmirror": 0,
"dcw": 1,
"colorbar": 0,
"led_intensity": 0
}

里面的所有参数都可以通过调用 post 请求 /control?var=xx&val=xx 这样的形式来修改回调画面的显示情况。例如:

1
control?var=hmirror&val=1

快点动手试试吧。

小结

总体使用下来,发现 opencv 识别的人脸模型不够精确,并且对像素要求比较高,也可能是我的模型不够精准。所以后面我又重新找了 tensorflow 的方案替代。这个就留着下篇在分享吧。

dev 的艺术空间

使用 esp32-cam 搭配 opencv 实现人脸识别

http://blog.jzxer.cn/20241121/20241121_esp32_cam_with_face/

作者

dev

发布于

2024-11-21

更新于

2024-12-22

许可协议

评论

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×