“ESP32-S3 AI摄像头”边缘轮廓检测—AI数万物
本帖最后由 b8hqQHaWdEN1 于 2025-5-5 01:55 编辑【概述】
“ESP32-S3 AI摄像头”模块是一款基于ESP32-S3的开发板,搭载了一个OV3660摄像头,集成了边缘AI处理能力的多功能开发平台,具备强大的神经网络计算能力,本项目就以该摄像头为核心,展示一下该摄像头强大的图像采集和边缘轮廓检测能力。
【项目来源】
本项目的灵感来源于路边的烧烤摊,在有一天吃夜宵时,贴主突发奇想,将”ESP32-S3 AI摄像头模块”的边缘轮廓检测用于结账时数签子,这样就可以脱离人工计数的误差,进一步解放双手,实现自动化建设,但是,该项目不仅仅只能用于数签子,还可以用于所有的同类计数识别,也可以进一步优化,实现多个种类同时识别的功能。
【功能点】
本项目分为设备端(“ESP32-S3 AI摄像头”)和客户端(电脑python),原理如下:
1. 设备端:以“ESP32-S3 AI摄像头”为核心,连接网络获取ip地址并建立Web服务器,通过摄像头采集JPEG图像上传到该ip地址服务器。
2. 客户端:通过访问相应URL获取图像数据,将图像数据解码为OpenCV图像格式-灰度图像-边缘检测-绘制轮廓,在窗口显示实时图像和边缘图像。通过按键实现计数的功能。
【未来展望】
目前该项目是通过摄像头采集数据发送至电脑,后续将移植到摄像头本地运行,在功能方面,不仅可以添加集成例如颜色识别的功能,另该项目更加智能化,也可以添加代码变量,统计各项数据,进一步完善该作品。
【功能实现】一.准备工作
设备端(使用Arduino ide开发环境):
1.下载Arduino IDE,下载esp32主板,这部分可以在产品维库中实现,因此不在赘述。
2.配置好该开发板参数,项目-导入库-管理库-下载好“WiFi”“WebServer”两个库文件。
客户端(电脑运行python开发环境):1.打开python代码,下载numpy和opencv-py两个库
2.在你的python开发环境输入
“pip install numpy”
”Pip install opencv-python“
回车并下载,
至此准备工作已全部完成。
二.代码实现
准备工作结束后就可以复制如下代码粘贴到Arduion ide中:
#include <WiFi.h>
#include <WebServer.h>
#include <esp_camera.h>
// ================= 用户配置区域 =================
const char* ssid = "U123"; //替换你的wifi
const char* password = "88888888";//替换你的密码
// 摄像头引脚配置
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 5
#define Y9_GPIO_NUM 4
#define Y8_GPIO_NUM 6
#define Y7_GPIO_NUM 7
#define Y6_GPIO_NUM 14
#define Y5_GPIO_NUM 17
#define Y4_GPIO_NUM 21
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 16
#define VSYNC_GPIO_NUM 1
#define HREF_GPIO_NUM 2
#define PCLK_GPIO_NUM 15
#define SIOD_GPIO_NUM 8
#define SIOC_GPIO_NUM 9
const framesize_t FRAME_SIZE = FRAMESIZE_QVGA;// 320x240
const int JPEG_QUALITY = 15; // 质量 (0-63)
const int FB_COUNT = 3; // 帧缓冲区数量
// ==============================================
WebServer server(80);
void setupCamera() {
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.pixel_format = PIXFORMAT_JPEG;
// 自适应配置
if(psramFound()){
config.frame_size = FRAME_SIZE;
config.jpeg_quality = JPEG_QUALITY;
config.fb_count = FB_COUNT;
} else {
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 15;
config.fb_count = 1;
}
// 初始化摄像头
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("摄像头初始化失败: 0x%x", err);
ESP.restart();
}
// 图像方向修正
sensor_t *s = esp_camera_sensor_get();
s->set_vflip(s, 1); // 垂直翻转(0关闭1开启)
s->set_hmirror(s, 1);// 水平镜像(0关闭1开启)
}
void setupWiFi() {
WiFi.begin(ssid, password);
WiFi.setSleep(false);
Serial.print("正在连接WiFi");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println("\nWiFi已连接");
Serial.print("访问地址: http://");
Serial.println(WiFi.localIP());
}
void handleJPG() {
camera_fb_t *fb = esp_camera_fb_get();
if(!fb) {
server.send(500, "text/plain", "Camera Error");
return;
}
WiFiClient client = server.client();
// 构建完整HTTP响应
String response = "HTTP/1.1 200 OK\r\n";
response += "Content-Type: image/jpeg\r\n";
response += "Content-Length: " + String(fb->len) + "\r\n";
response += "Connection: close\r\n\r\n";
// 分块发送数据
client.print(response);
client.write(fb->buf, fb->len);
esp_camera_fb_return(fb);
}
void setup() {
Serial.begin(115200);
delay(1000);// 等待串口初始化
setupCamera();
setupWiFi();
// 路由设置
server.on("/", HTTP_GET, [](){
server.sendHeader("Location", "/jpg");
server.send(302, "text/plain", "");
});
server.on("/jpg", HTTP_GET, handleJPG);
server.begin();
Serial.println("HTTP服务器已启动");
}
void loop() {
server.handleClient();
delay(2);
}</font>
步骤如下
设备端:
1.在Arduino IDE中选择esp32-s3主板及其串口
2.File->Examples->ESP32->Camera->CameraWebServer示例
3.使用下面的代码替换CameraWebServer中的代码,只要替换主程序即可
(注意:需要填入WIFI账号密码)
4.上传程序,静等连接WiFi,打开串口监视器返回IP地址(注:电脑和主板需在同一局域网中)
5.打开浏览器,在Web地址中粘贴获取的IP地址,刷新就可以查看摄像头获取的图片。
客户端:
import cv2
import urllib.request
import numpy as np
url = 'http://192.168.0.106/jpg'# 获取的esp32-s3 ai的ip地址
# 创建显示窗口
cv2.namedWindow("live transmission", cv2.WINDOW_AUTOSIZE)
while True:
try:
# 获取图像数据
img_resp = urllib.request.urlopen(url)
imgnp = np.array(bytearray(img_resp.read()), dtype=np.uint8)
img = cv2.imdecode(imgnp, -1)
# 如果图像为空则跳过后续处理
if img is None:
continue
# 图像处理流程
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (11, 11), 0)
canny = cv2.Canny(blurred, 30, 150)
dilated = cv2.dilate(canny, (1, 1), iterations=2)
contours, _ = cv2.findContours(dilated.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 绘制轮廓
cv2.drawContours(img, contours, -1, (0, 255, 0), 2)
# 显示结果
cv2.imshow("Edge Detection", canny)
cv2.imshow("Live Feed with Contours", img)
# 按键处理
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
elif key == ord('a'):
print(f"检测到轮廓数量: {len(contours)}")
except Exception as e:
print(f"发生错误: {str(e)}")
break
cv2.destroyAllWindows()</font>
1.打开python开发环境,复制以上代码并粘贴,修改IP为串口监视器获取的IP地址
2.屏幕上显示实时图像和边缘检测图像
3.按下键盘的“Q”键退出程序,按下“A”键检测检测的边缘数量。
https://www.bilibili.com/video/BV1hAVKzQEEn?buvid=XUB283FB9990F888F282764E1B889A1689536&from_spmid=main.space.0.0&is_story_h5=false&mid=B%2B%2Bap2FLB1nam6J37LLtxQ%3D%3D&plat_id=116&share_from=ugc&share_medium=android&share_plat=android&share_session_id=596a16a9-d41f-48bd-8394-40e824734815&share_source=COPY&share_tag=s_i&spmid=united.player-video-detail.0.0×tamp=1746381271&unique_k=wyFrICh&up_id=184951246
页:
[1]