94浏览
查看: 94|回复: 0

[ESP8266/ESP32] "ESP32-S3 AI摄像头"+DeepSeek—皮肤分析系统—灵犀镜

[复制链接]
本帖最后由 b8hqQHaWdEN1 于 2025-4-29 16:32 编辑

【试用背景
最近发现DF创客社区发布了ESP32-S3 AI摄像头的试用,我便怀着激动的心情填写试用名单,最终有幸被选中,希望借此来表达我的想法和制作思路,同各位老师们一起探索。
【概述】
本项目灵感来源于童话世界中的魔镜,我命名为灵犀镜。该项目的核心是ESP32-S3 AI摄像头”,利用自带的摄像头采集人脸图像信息并生成图片,借由Base64将图片转化为数据信息,最后传输给DeepSeek大模型返回识别的数据,并在串口监视器显示数据。
【功能点】
灵犀镜正如童话的魔镜一般,告诉你谁才是这个世界最美丽的人,可以利用ESP32-S3 AI摄像头”采集图片,交由DeepSeek大模型的强大图像分析能力来识别当前人脸状态,如:黑眼圈,皮肤状态,护肤建议等等,能成为各位的护肤专家。
"ESP32-S3 AI摄像头"+DeepSeek—皮肤分析系统—灵犀镜图5
【未来展望】
目前该项目的连接网络和发送deepseek等功能都是基于“ESP32-S3 AI摄像头”独立运行,但是串口数据还是要借助电脑串口监视器实现,也无法查看图片信息等,只能通过网络base64编码转图片才能查看,没有真正脱离电脑,目前有两个发展方向:1.可以借助其他显示屏显示数据,如:行空板或者其他显示屏等;2.进一步添加语音识别和语音合成,可以实现对话功能,拓展使用范围。
【功能实现】
一.准备工作
1.下载Arduino IDE,下载esp主板,这部分可以在产品wiki实现,因此不在赘述。
2.获取你的deepseek api key,用于调用deepseek
"ESP32-S3 AI摄像头"+DeepSeek—皮肤分析系统—灵犀镜图1
浏览器打开deepseek的官网(DeepSeek | 深度求索),选择api开放平台,deepseek对话的是免费,但是调用api要收费,也不用担心,几块钱可以用很久
点击充值,随便多少都行,随后在api文档创建新的api,该api只有在创建第一次才能看见,请牢记你的api key
"ESP32-S3 AI摄像头"+DeepSeek—皮肤分析系统—灵犀镜图2
3. 测试deepseek连通性:
复制如下代码,在其中更改wifi,密码,和deepseek api,并上传程序
  1. #include <WiFi.h>
  2. #include <WiFiClientSecure.h>
  3. #include <ArduinoJson.h>
  4. const char* ssid = "";   //替换你的wifi
  5. const char* password = "";  //替换你的密码
  6. const char* apiKey = "";     //替换你的api
  7. const char* host = "api.deepseek.com";
  8. const int httpsPort = 443;
  9. // 超时配置
  10. const unsigned long wifiTimeout = 15000;
  11. const unsigned long responseTimeout = 15000;
  12. WiFiClientSecure client;
  13. void setup() {
  14.   Serial.begin(115200);
  15.   Serial.println("测试deepseek连接\n");
  16.   
  17.   // 完全禁用证书验证
  18.   client.setInsecure();
  19.   
  20.   connectWiFi();
  21. }
  22. void loop() {
  23.   if (Serial.available()) {
  24.     String question = Serial.readStringUntil('\n');
  25.     question.trim();
  26.    
  27.     if (question.length() > 0) {
  28.       // 显示用户问题
  29.       Serial.print("\n[用户问题] ");
  30.       Serial.println(question);
  31.       Serial.println("[正在发送分析请求...]");
  32.       
  33.       bool result = sendRequest(question);
  34.       
  35.       if (!result) {
  36.         Serial.println("[请求失败,请检查连接]");
  37.       }
  38.       Serial.println("\n[请输入新问题]");
  39.     }
  40.   }
  41. }
  42. void connectWiFi() {
  43.   WiFi.begin(ssid, password);
  44.   Serial.print("正在连接WiFi");
  45.   
  46.   unsigned long start = millis();
  47.   while (WiFi.status() != WL_CONNECTED) {
  48.     delay(500);
  49.     Serial.print(".");
  50.    
  51.     if (millis() - start > wifiTimeout) {
  52.       Serial.println("\n连接超时!");
  53.       ESP.restart();
  54.     }
  55.   }
  56.   Serial.println("\nWiFi连接成功!");
  57.   Serial.print("IP地址: ");
  58.   Serial.println(WiFi.localIP());
  59. }
  60. bool sendRequest(String prompt) {
  61.   if (!client.connect(host, httpsPort)) {
  62.     Serial.println("服务器连接失败");
  63.     return false;
  64.   }
  65.   // 构建HTTP请求
  66.   String request = createRequest(prompt);
  67.   client.print(request);
  68.   // 处理响应
  69.   return processResponse();
  70. }
  71. String createRequest(String prompt) {
  72.   DynamicJsonDocument doc(2048);  // 增加文档大小以适应系统提示
  73.   doc["model"] = "deepseek-chat";
  74.   doc["stream"] = true;
  75.   doc["temperature"] = 0.3;      // 添加温度参数
  76.   
  77.   JsonArray messages = doc.createNestedArray("messages");
  78.   
  79.   // 系统角色设定
  80.   JsonObject systemMsg = messages.createNestedObject();
  81.   systemMsg["role"] = "system";
  82.   systemMsg["content"] = "你是deepseek,是一个乐于助人的助手";
  83.   
  84.   // 用户问题
  85.   JsonObject userMsg = messages.createNestedObject();
  86.   userMsg["role"] = "user";
  87.   userMsg["content"] = prompt;
  88.   String body;
  89.   serializeJson(doc, body);
  90.   return String("POST /v1/chat/completions HTTP/1.1\r\n") +
  91.          "Host: " + host + "\r\n" +
  92.          "Authorization: Bearer " + apiKey + "\r\n" +
  93.          "Content-Type: application/json\r\n" +
  94.          "Accept: text/event-stream\r\n" +
  95.          "Connection: close\r\n" +
  96.          "Content-Length: " + body.length() + "\r\n\r\n" +
  97.          body;
  98. }
  99. bool processResponse() {
  100.   unsigned long lastData = millis();
  101.   bool gotResponse = false;
  102.   while (client.connected() || client.available()) {
  103.     if (client.available()) {
  104.       String line = client.readStringUntil('\n');
  105.       line.trim();
  106.       lastData = millis();
  107.       if (line.startsWith("data: ")) {
  108.         String json = line.substring(6);
  109.         if (json == "[DONE]") break;
  110.         DynamicJsonDocument doc(1024);
  111.         if (deserializeJson(doc, json)) break;
  112.         const char* content = doc["choices"][0]["delta"]["content"];
  113.         if (content) {
  114.           Serial.print(content);
  115.           gotResponse = true;
  116.         }
  117.       }
  118.     } else {
  119.       if (millis() - lastData > responseTimeout) {
  120.         Serial.println("\n响应超时");
  121.         break;
  122.       }
  123.       delay(10);
  124.     }
  125.   }
  126.   
  127.   client.stop();
  128.   return gotResponse;
  129. }
复制代码

打开串口监视器发送问题,稍等就能得到回复
遇到网络或者服务器问题不回复可以按rst重试几次。
回复如下:"ESP32-S3 AI摄像头"+DeepSeek—皮肤分析系统—灵犀镜图3
二.代码实现
测试没问题就可以复制如下代码:
  1. #include "esp_camera.h"
  2. #include <WiFi.h>
  3. #include <base64.h>
  4. #include <WiFiClientSecure.h>
  5. #include <ArduinoJson.h>
  6. // 摄像头引脚定义
  7. #define PWDN_GPIO_NUM     -1
  8. #define RESET_GPIO_NUM    -1
  9. #define XCLK_GPIO_NUM     5
  10. #define Y9_GPIO_NUM       4
  11. #define Y8_GPIO_NUM       6
  12. #define Y7_GPIO_NUM       7
  13. #define Y6_GPIO_NUM       14
  14. #define Y5_GPIO_NUM       17
  15. #define Y4_GPIO_NUM       21
  16. #define Y3_GPIO_NUM       18
  17. #define Y2_GPIO_NUM       16
  18. #define VSYNC_GPIO_NUM    1
  19. #define HREF_GPIO_NUM     2
  20. #define PCLK_GPIO_NUM     15
  21. #define SIOD_GPIO_NUM     8
  22. #define SIOC_GPIO_NUM     9
  23. #define BUTTON_PIN        0
  24. // WiFi配置
  25. const char* ssid = "";
  26. const char* password = "";
  27. const char* apiKey = "";
  28. const char* host = "api.deepseek.com";
  29. const int httpsPort = 443;
  30. // 超时配置
  31. const unsigned long wifiTimeout = 15000;
  32. const unsigned long responseTimeout = 15000;
  33. WiFiClientSecure client;
  34. void setup() {
  35.   Serial.begin(115200);
  36.   while(!Serial); // 串口连接
  37.   
  38.   pinMode(BUTTON_PIN, INPUT_PULLUP);
  39.   // 摄像头配置
  40.   camera_config_t config;
  41.   config.ledc_channel = LEDC_CHANNEL_0;
  42.   config.ledc_timer = LEDC_TIMER_0;
  43.   config.pin_d0 = Y2_GPIO_NUM;
  44.   config.pin_d1 = Y3_GPIO_NUM;
  45.   config.pin_d2 = Y4_GPIO_NUM;
  46.   config.pin_d3 = Y5_GPIO_NUM;
  47.   config.pin_d4 = Y6_GPIO_NUM;
  48.   config.pin_d5 = Y7_GPIO_NUM;
  49.   config.pin_d6 = Y8_GPIO_NUM;
  50.   config.pin_d7 = Y9_GPIO_NUM;
  51.   config.pin_xclk = XCLK_GPIO_NUM;
  52.   config.pin_pclk = PCLK_GPIO_NUM;
  53.   config.pin_vsync = VSYNC_GPIO_NUM;
  54.   config.pin_href = HREF_GPIO_NUM;
  55.   config.pin_sccb_sda = SIOD_GPIO_NUM;
  56.   config.pin_sccb_scl = SIOC_GPIO_NUM;
  57.   config.pin_pwdn = PWDN_GPIO_NUM;
  58.   config.pin_reset = RESET_GPIO_NUM;
  59.   config.xclk_freq_hz = 20000000;
  60.   config.frame_size = FRAMESIZE_240X240;
  61.   config.pixel_format = PIXFORMAT_JPEG;
  62.   config.jpeg_quality = 10;
  63.   config.fb_count = 1;
  64.   // 初始化摄像头
  65.   esp_err_t err = esp_camera_init(&config);
  66.   if (err != ESP_OK) {
  67.     Serial.printf("摄像头初始化失败: 0x%x\n", err);
  68.     return;
  69.   }
  70.   // 完全禁用证书验证
  71.   client.setInsecure();
  72.   
  73.   connectWiFi();
  74.   Serial.println("\n系统就绪,按下BOOT按钮进行皮肤分析");
  75. }
  76. void loop() {
  77.   static uint32_t lastPress = 0;
  78.   if(digitalRead(BUTTON_PIN) == LOW && millis() - lastPress > 1000) {
  79.     lastPress = millis();
  80.     String imageData = captureToBase64();
  81.     if(imageData.length() > 0){
  82.       sendAnalysisRequest(imageData);
  83.     }
  84.     while(digitalRead(BUTTON_PIN) == LOW) delay(10);
  85.   }
  86.   delay(10);
  87. }
  88. String captureToBase64() {
  89.   camera_fb_t *fb = esp_camera_fb_get();
  90.   if(!fb || !fb->buf || fb->len == 0) {
  91.     Serial.println("捕获失败");
  92.     if(fb) esp_camera_fb_return(fb);
  93.     return "";
  94.   }
  95.   // 直接编码JPEG数据为Base64
  96.   String base64Data = base64::encode(fb->buf, fb->len);
  97.   esp_camera_fb_return(fb);
  98.   return "data:image/jpeg;base64," + base64Data;
  99. }
  100. void connectWiFi() {
  101.   WiFi.begin(ssid, password);
  102.   Serial.print("正在连接WiFi");
  103.   
  104.   unsigned long start = millis();
  105.   while (WiFi.status() != WL_CONNECTED) {
  106.     delay(500);
  107.     Serial.print(".");
  108.    
  109.     if (millis() - start > wifiTimeout) {
  110.       Serial.println("\n连接超时!");
  111.       ESP.restart();
  112.     }
  113.   }
  114.   Serial.println("\nWiFi连接成功!");
  115.   Serial.print("IP地址: ");
  116.   Serial.println(WiFi.localIP());
  117. }
  118. void sendAnalysisRequest(String imageData) {
  119.   if (!client.connect(host, httpsPort)) {
  120.     Serial.println("服务器连接失败");
  121.     return;
  122.   }
  123.   // 构建请求内容
  124.   String prompt = "分析该人物的皮肤状态:" + imageData;
  125.   
  126.   // 构建HTTP请求
  127.   String request = createRequest(prompt);
  128.   client.print(request);
  129.   // 处理响应
  130.   processResponse();
  131. }
  132. String createRequest(String prompt) {
  133.   DynamicJsonDocument doc(24576); // Base64数据长度
  134.   doc["model"] = "deepseek-chat";
  135.   doc["stream"] = true;
  136.   doc["temperature"] = 0.3;
  137.   
  138.   JsonArray messages = doc.createNestedArray("messages");
  139.   
  140.   // 系统角色设定
  141.   JsonObject systemMsg = messages.createNestedObject();
  142.   systemMsg["role"] = "system";
  143.   systemMsg["content"] = "你是灵犀镜,专业皮肤科分析助手,用简洁中文指出面部问题并提供建议,格式:问题发现+建议列表";
  144.   
  145.   // 用户消息
  146.   JsonObject userMsg = messages.createNestedObject();
  147.   userMsg["role"] = "user";
  148.   userMsg["content"] = prompt;
  149.   String body;
  150.   serializeJson(doc, body);
  151.   return String("POST /v1/chat/completions HTTP/1.1\r\n") +
  152.          "Host: " + host + "\r\n" +
  153.          "Authorization: Bearer " + apiKey + "\r\n" +
  154.          "Content-Type: application/json\r\n" +
  155.          "Accept: text/event-stream\r\n" +
  156.          "Connection: close\r\n" +
  157.          "Content-Length: " + body.length() + "\r\n\r\n" +
  158.          body;
  159. }
  160. void processResponse() {
  161.   Serial.println("\n[皮肤分析结果]");
  162.   unsigned long lastData = millis();
  163.   bool gotResponse = false;
  164.   while (client.connected() || client.available()) {
  165.     if (client.available()) {
  166.       String line = client.readStringUntil('\n');
  167.       line.trim();
  168.       lastData = millis();
  169.       if (line.startsWith("data: ")) {
  170.         String json = line.substring(6);
  171.         if (json == "[DONE]") break;
  172.         DynamicJsonDocument doc(1024);
  173.         if (deserializeJson(doc, json)) break;
  174.         const char* content = doc["choices"][0]["delta"]["content"];
  175.         if (content) {
  176.           Serial.print(content);
  177.           gotResponse = true;
  178.         }
  179.       }
  180.     } else {
  181.       if (millis() - lastData > responseTimeout) {
  182.         Serial.println("\n响应超时");
  183.         break;
  184.       }
  185.       delay(10);
  186.     }
  187.   }
  188.   
  189.   client.stop();
  190.   if (!gotResponse) Serial.println("未收到有效响应");
  191.   Serial.println("\n[分析完成,可再次拍照]");
  192. }
复制代码

步骤如下
1.Arduino IDE中选择File->Examples->ESP32->Camera->CameraWebServer示例
2.使用下面的代码替换CameraWebServer中的代码,只要替换主程序即可
(注意:需要填入WIFI账号密码和api key)
3. 按下ESP32-S3 AI摄像头”boot按键,自动采集图片
4. 图片自动压缩并转为base64格式,发送deepseek大模型,目前测试deepseek可以识别图片base64格式
5. 打开串口监视器返回皮肤情况+护肤建议等
"ESP32-S3 AI摄像头"+DeepSeek—皮肤分析系统—灵犀镜图4










您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4 备案 沪公网安备31011502402448

© 2013-2025 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail