Arduino开发 esp32cam+opencv人脸识别距离+语音提醒

效果

低于20厘米语音提醒字体变红

QQ录屏20240406131651

Arduino代码

可直接复制使用(修改自己的WIFI)

#include <esp32cam.h>
#include <WebServer.h>
#include <WiFi.h>
// 设置要连接的WiFi名称和密码
const char* WIFI_SSID = "gumou"; 
const char* WIFI_PASS = "gu3456789";
WebServer server(80);
// 设置不同分辨率的静态变量
static auto loRes = esp32cam::Resolution::find(320, 240);
static auto hiRes = esp32cam::Resolution::find(1280, 1024);
// 处理BMP图像请求
void handleBmp() {if (!esp32cam::Camera.changeResolution(loRes)) {Serial.println("SET-LO-RES FAIL");}auto frame = esp32cam::capture();if (frame == nullptr) {Serial.println("CAPTURE FAIL");server.send(503, "", "");return;}if (!frame->toBmp()) {Serial.println("CONVERT FAIL");server.send(503, "", "");return;}server.setContentLength(frame->size());server.send(200, "image/bmp");WiFiClient client = server.client();frame->writeTo(client);
}// 服务JPG图像请求
void serveJpg() {auto frame = esp32cam::capture();if (frame == nullptr) {Serial.println("CAPTURE FAIL");server.send(503, "", "");return;}server.setContentLength(frame->size());server.send(200, "image/jpeg");WiFiClient client = server.client();frame->writeTo(client);
}// 处理低分辨率JPG请求
void handleJpgLo() {if (!esp32cam::Camera.changeResolution(loRes)) {Serial.println("SET-LO-RES FAIL");}serveJpg();
}// 处理高分辨率JPG请求
void handleJpgHi() {if (!esp32cam::Camera.changeResolution(hiRes)) {Serial.println("SET-HI-RES FAIL");}serveJpg();
}// 处理JPG请求
void handleJpg() {server.sendHeader("Location", "/cam-hi.jpg");server.send(302, "", "");
}// 处理MJPEG流请求
void handleMjpeg() {if (!esp32cam::Camera.changeResolution(hiRes)) {Serial.println("SET-HI-RES FAIL");}Serial.println("STREAM BEGIN");WiFiClient client = server.client();auto startTime = millis();int res = esp32cam::Camera.streamMjpeg(client);if (res <= 0) {Serial.printf("STREAM ERROR %d\n", res);return;}auto duration = millis() - startTime;Serial.printf("STREAM END %dfrm %0.2ffps\n", res, 1000.0 * res / duration);
}void setup() {Serial.begin(115200);Serial.println();// 初始化摄像头{using namespace esp32cam;Config cfg;cfg.setPins(pins::AiThinker);cfg.setResolution(hiRes);cfg.setBufferCount(2);cfg.setJpeg(80);bool ok = Camera.begin(cfg);Serial.println(ok ? "CAMERA OK" : "CAMERA FAIL");}// 连接WiFiWiFi.persistent(false);WiFi.mode(WIFI_STA);WiFi.begin(WIFI_SSID, WIFI_PASS);while (WiFi.status() != WL_CONNECTED) {delay(500);}// 打印服务器地址和端口Serial.print("http://");Serial.println(WiFi.localIP());Serial.println("  /cam.bmp");Serial.println("  /cam-lo.jpg");Serial.println("  /cam-hi.jpg");Serial.println("  /cam.mjpeg");// 定义服务器路由server.on("/cam.bmp", handleBmp);server.on("/cam-lo.jpg", handleJpgLo);server.on("/cam-hi.jpg", handleJpgHi);server.on("/cam.jpg", handleJpg);server.on("/cam.mjpeg", handleMjpeg);// 启动服务器server.begin();
}
void loop() {// 处理客户端请求server.handleClient();
}

查看Esp32的IP地址

录入后,在串口监视器处查看IP(自动会输出)

录入前要把波特率调整115200

python端计算代码

可更改 1.IP地址 2.提醒语音 3.提醒距离 4.可删除倒数第二行 不显示画面 只测量距离

import urllib
import cv2
import numpy as np
from cvzone.FaceMeshModule import FaceMeshDetector
import pygame
import threading
from PIL import Image, ImageDraw, ImageFont
# 初始化pygame.mixer
pygame.mixer.init()
# 加载音频文件
pygame.mixer.music.load('7359.wav')  # 靠的太近啦音频
detector = FaceMeshDetector(maxFaces=1)
url = 'http://192.168.85.168/cam-hi.jpg'  # 改成自己的IP地址+/cam-hi.jpg
# 定义播放音频的函数
def play_audio():pygame.mixer.music.play(1)while pygame.mixer.music.get_busy():continue
# 函数:从ESP32CAM获取图像
def get_esp32cam_image(url):img_resp = urllib.request.urlopen(url)img_np = np.array(bytearray(img_resp.read()), dtype=np.uint8)img = cv2.imdecode(img_np, -1)return img
# 开始检测人脸距离
while True:# 从ESP32CAM获取图像img = get_esp32cam_image(url)# 检测人脸img, faces = detector.findFaceMesh(img, draw=False)if faces:face = faces[0]point_left = face[145]point_right = face[374]w, _ = detector.findDistance(point_left, point_right)W = 6.3f = 600d = (W * f) / wprint(d)# 设置距离颜色if d < 20:print("过近提醒")# 检查是否正在播放音频if not pygame.mixer.music.get_busy():# 使用线程播放音频,避免阻塞主程序audio_thread = threading.Thread(target=play_audio)audio_thread.start()text_color = (255, 0, 0)  # 红色else:text_color = (0, 0, 255)  # 蓝色# 将Depth文本显示为汉语pil_img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))draw = ImageDraw.Draw(pil_img)font = ImageFont.truetype("msyh.ttc", 36)  # 使用微软雅黑字体,大小为36draw.text((face[10][0] - 95, face[10][1] - 5), f'距离:{int(d)}厘米', font=font, fill=text_color)img = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)cv2.imshow("Distance recognition", img)   #这行注释掉后可以不显示摄像头窗口只输出距离if cv2.waitKey(1) == ord('q'):break
cv2.destroyAllWindows()

手机端查看  IP地址同上

图片

http://192.168.85.168/cam-hi.jpg

视频

http://192.168.85.168/cam.mjpeg

UI设计

设计ui之后画面较小 若摄像头分辨率较低建议使用上面的代码

import sys
from PyQt5 import QtGui
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtCore import Qt, QPoint, pyqtSignal
from esp32_ui import Ui_Form  # UI
import cv2
from cvzone.FaceMeshModule import FaceMeshDetector
import pygame
import threading
from PIL import Image, ImageDraw, ImageFont
import numpy as np
import urllib.request
import ping
class guWindow(QWidget):close_signal = pyqtSignal()def __init__(self):super().__init__()self.gu = Ui_Form()self.gu.setupUi(self)self.gu.lineEdit.returnPressed.connect(self.gumou)  # lineEdit回车运行self.video_label = self.gu.label_2# 2 QLabel2self.user_name_qwidget = self.gu.lineEditself.progress_bar = self.gu.progressBar  #进度条self.setWindowOpacity(0.90)  # 设置窗口透明度self.setWindowFlag(Qt.FramelessWindowHint)  # 去除边框self.setAttribute(Qt.WA_TranslucentBackground)  # 去除白色背景self.offset = QPoint()  # 记录鼠标按下的初始位置self.close_signal.connect(self.closeEvent)def closeEvent(self, event):# 关闭窗口时发送信号self.stop_capture()def mousePressEvent(self, event):self.offset = event.pos()def mouseMoveEvent(self, event):if event.buttons() == Qt.LeftButton:self.move(self.pos() + event.pos() - self.offset)  # 移动窗口位置def gumou(self):  # 按钮绑定的函数 功能s = self.user_name_qwidget.text()self.user_name_qwidget.clear()try:distance_threshold = float(s)  # 将用户输入的文本转换为浮点数作为距离阈值except ValueError:print("Invalid input. Please enter a valid number.")returnpygame.mixer.init()# 加载音频文件pygame.mixer.music.load('7359.wav')  # 靠的太近啦self.capture_active = Truedef play_audio():pygame.mixer.music.play(1)while pygame.mixer.music.get_busy():continuewhile self.capture_active:img = get_esp32cam_image('http://192.168.85.168/cam-hi.jpg')  # Get image from ESP32CAMif img is not None:self.detect_and_display(img, distance_threshold, play_audio)def detect_and_display(self, img, distance_threshold, play_audio):self.detector = FaceMeshDetector(maxFaces=1)img, faces = self.detector.findFaceMesh(img, draw=False)if faces:face = faces[0]pointLeft = face[145]pointRight = face[374]w, _ = self.detector.findDistance(pointLeft, pointRight)W = 6.5f = 600  # 焦距d = (W * f) / wprint(d)# 设置距离颜色if d < distance_threshold:  # 使用用户输入的距离阈值作为判断条件print("过近提醒")# 检查是否正在播放音频if not pygame.mixer.music.get_busy():# 使用线程播放音频,避免阻塞主程序audio_thread = threading.Thread(target=play_audio)audio_thread.start()text_color = (255, 0, 0)  # 红色else:text_color = (0, 0, 255)  # 蓝色# Update the QProgressBar valueself.progress_bar.setValue(int(d))# 将 Depth 文本显示为汉语pil_img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))draw = ImageDraw.Draw(pil_img)font = ImageFont.truetype("msyh.ttc", 36)  # 使用微软雅黑字体,大小为36draw.text((face[10][0] - 95, face[10][1] - 5), f'距离:{int(d)}厘米', font=font, fill=text_color)img = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)h, w, c = img.shapebytesPerLine = c * wif c == 3:  # 如果颜色通道为3(BGR)q_img = QtGui.QImage(img.data, w, h, bytesPerLine, QtGui.QImage.Format_BGR888)else:  # 如果颜色通道为4(BGRA)q_img = QtGui.QImage(img.data, w, h, bytesPerLine, QtGui.QImage.Format_BGRA8888)# Convert QImage to QPixmappixmap = QtGui.QPixmap.fromImage(q_img)# Display QPixmap on QLabelself.video_label.setPixmap(pixmap)self.video_label.setScaledContents(True)self.video_label.update()cv2.waitKey(1)def stop_capture(self):self.capture_active = Falsedef get_esp32cam_image(url):img_resp = urllib.request.urlopen(url)img_np = np.array(bytearray(img_resp.read()), dtype=np.uint8)img = cv2.imdecode(img_np, -1)return imgif __name__ == '__main__':app = QApplication(sys.argv)icon = QtGui.QIcon(':/jay.ico')app.setWindowIcon(icon)# 创建可拖动窗口实例ui = guWindow()  # 函数# 显示窗口ui.show()# 启动应用程序事件循环sys.exit(app.exec_())

项目踩坑

1.驱动ESP32-CAM 这里下载zip自己导入

2.配置开发板 

Arduino中文社区

从这里下载会自动安装指定位置

不要在图中位置配置,速度太慢!!

3.python识别面部距离,需要电脑端和esp32-cam同时连接一个WIFI

由于esp32-cam连WIFI能力较差

(若手机开热点供双方连接,建议esp32-cam先连接后再让电脑连)

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

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

相关文章

MYSQL 8.0版本修改用户密码(知道登录密码)和Sqlyog错误码2058一案

今天准备使用sqlyog连接一下我Linux上面的mysql数据库&#xff0c;然后就报如下错误 有一个简单的办法就是修改密码为password就完事!然后我就开始查找如何修改密码! 如果是需要解决Sqlyog错误码2058的话&#xff0c;执行以下命令&#xff0c;但是注意root对应host是不是loca…

Fecify站点斗篷cloak

斗篷cloak站点斗篷模式功能发布&#xff01;全新的应用场景&#xff0c;该模式是针对推广不用GMC&#xff0c;而是通过facebook&#xff0c;或者其他的一些平台/工具推广&#xff0c;这些推广方式的特点是&#xff1a;不需要商品的图片&#xff0c;或者说不会排查商品图片的侵权…

基础语法复习

常用的定义&#xff1a; 读取数据加速&#xff1a; input sys.stdin.readline 设置递归深度&#xff1a; sys.setrecursionlimit(100000) 记忆化搜索&#xff1a; from functools import lru_cache lru_cache(maxsizeNone) 计数器&#xff1a; Counter 类是一个非常有…

P8707 [蓝桥杯 2020 省 AB1] 走方格

原题链接&#xff1a;[蓝桥杯 2020 省 AB1] 走方格 - 洛谷 目录 1.题目描述 2.思路分析 3.代码实现 1.题目描述 2.思路分析 题目大意&#xff1a;现在有个人站在第 1 行第 1 列&#xff0c;要走到第 i 行第 j 列&#xff08;每次只能向右或者向下走&#xff09;&#xff0…

计算机的发展趋势

本文 我们来说计算机的发展趋势 目前来讲 计算机是朝着 巨型化 微型化 网络化 智能化发展 巨型化 指功能巨型化 是指其高速运算、大存储容量和强功能的巨型计算机。其运算能力一般在每秒百亿次以上、内存容量在几百兆字节以上。 主要用于航空航天、军事、气象、人工智能、生…

单链表学习

//静态链表&#xff0c;只往后看&#xff0c;找前面必须遍历 //算法题用数组解题更快速 //初始化,头节点为空 //将x插入到头节点 //将x插到结点k的后面 //将下标k的后面的点删掉 #include<algorithm> #include<iostream> #include<cstring> #include<queu…

Leetcode:27.移除元素

题目要求 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出…

智能单灯控制器 计讯物联TL112

智能单灯控制器集成了先进技术的照明控制设备&#xff0c;它极大地改变了传统照明方式&#xff0c;并使之更加智能化。计讯物联智能单灯控制器TL112广泛应用于道路、景区、园区、隧道等场景智慧路灯杆使用。      智能单灯控制器通过集成最先进的传感器、控制模块和通信技术…

基于vue实现动态table

1、代码 <div style"height: 600px; overflow: scroll;"> <!-- height: 600px; overflow: scroll;作用是超出页面可以滑动 --><div ng-repeat"row in entity.procedureList"><cb-title title"工序{{row.procedireLocation}}&quo…

SpringBoot整合RabbitMQ,三种交换机类型示例

SpringBoot整合RabbitMQ&#xff0c;三种交换机类型示例 1、流程概括 2、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>3、配置RabbitMQ连接 在a…

【C++成长记】C++入门 |auto、范围for、nullptr

&#x1f40c;博主主页&#xff1a;&#x1f40c;​倔强的大蜗牛&#x1f40c;​ &#x1f4da;专栏分类&#xff1a;C❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、auto关键字 1、auto简介 2、auto的使用细则 &#xff08;1&#xff09; auto与指针和引用结合起…

多线程入门

文章目录 多线程相关的概念什么是多线程多线程的创建方式继承Thread方式实现Runable方式两种方式比较Thread类中常用方法 多线程相关的概念 并发与并行 并行&#xff1a;在同一时刻&#xff0c;有多个任务在多个CPU上同时执行。并发&#xff1a;在同一时刻&#xff0c;有多个任…

[网鼎杯 2020 玄武组]SSRFMe

[网鼎杯 2020 玄武组]SSRFMe 源码 <?php function check_inner_ip($url) {$match_resultpreg_match(/^(http|https|gopher|dict)?:\/\/.*(\/)?.*$/,$url);if (!$match_result){die(url fomat error);}try{$url_parseparse_url($url);}catch(Exception $e){die(url foma…

Linux内核

一、 内核开发与逻辑开发对比 内核开发&#xff1a; 需要应用程序调用API去在操作系统里对硬件进行操作。操作系统不允许用户直接去通过置GPIO口1或者0去控制硬件&#xff0c;为了管理这一切。操作系统将整个开发中分成了两个空间&#xff0c;一个是用户空间&#xff08;上两…

HarmonyOS 开发-Navigation页面跳转对象传递案例

介绍 本示例主要介绍在使用Navigation实现页面跳转时&#xff0c;如何在跳转页面得到转入页面传的类对象的方法。实现过程中使用了第三方插件class-transformer&#xff0c;传递对象经过该插件的plainToClass方法转换后可以直接调用对象的方法&#xff0c; 效果图预览 使用说…

YOLOv9改进策略 :小目标 | 新颖的多尺度前馈网络(MSFN) | 2024年4月最新成果

💡💡💡本文独家改进:多尺度前馈网络(MSFN),通过提取不同尺度的特征来增强特征提取能力,2024年最新的改进思路 💡💡💡创新点:多尺度前馈网络创新十足,抢先使用 💡💡💡如何跟YOLOv8结合:1)放在backbone后增强对全局和局部特征的提取能力;2)放在detect…

蝙蝠优化算法(bat optimization algorithm)

注意&#xff1a;本文引用自专业人工智能社区Venus AI 更多AI知识请参考原站 &#xff08;[www.aideeplearning.cn]&#xff09; 算法背景 蝙蝠优化算法&#xff08;Bat Algorithm&#xff09;是一种基于群体智能的优化算法&#xff0c;它的灵感来源于蝙蝠捕食时的回声定位行…

Linux(Ubuntu)中创建【samba】服务,用于和Windows系统之间共享文件

目录 1.先介绍一下什么是Samba 2.安装&#xff0c;配置服务 安装 配置&#xff08;smb.conf&#xff09; 配置用户 3.出现的问题&#xff08;Failed to add entry for user XXXX&#xff09; 4.创建文件夹 5.windows访问 6.其他 Samba【服务状态】查看 Samba服务启动…

Training - Kubeflow 的 PyTorchJob 配置 DDP 分布式训练 (ncclInternalError)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://blog.csdn.net/caroline_wendy/article/details/137569332 Kubeflow 的 PyTorchJob 是 Kubernetes 自定义资源&#xff0c;用于在 Kubernetes 上运行 PyTorch 训练任务&#xff0c;是 K…

网格矢量如何计算莫兰指数

网格矢量如何计算莫兰指数 引言 遇到一个问题&#xff0c;计算矢量网格的莫兰指数。 概念解释 莫兰指数 莫兰指数&#xff08;Moran’s Index&#xff09;是一种空间自相关指标&#xff0c;用于衡量空间数据的相似性和聚集程度。它可以用来描述一个区域与其邻近区域之间的属…