XIAO ESP32S3之物体检测加入视频流

一、前言

        由于XIAO ESP32S3开发套件没有显示屏配件,因此加入http视频流功能,可通过浏览器请求ESP32S3上的视频流。

二、思路

1、XIAO ESP32S3启动后通过wifi连接到AP;

2、启动http服务器,注册get_mjpeg处理函数;

3、主任务将算法输出的图像压缩为jpg通过xMessageBuffer传递给get_mjpeg处理函数;

4、连接到同一个AP的终端启动浏览器输入XIAO ESP32S3的IP:8081获取视频流。

三、编写代码

1、加入文件

main文件夹下增加http_stream.cpp、http_stream.h文件

修改CMakeLists.txt文件,加入http_stream.cpp,内容如下:

idf_component_register(SRCS app_main.cppfomo_mobilenetv2_model_data.cpphttp_stream.cpp
)
2、主函数中加入连接AP和传递图像的功能

修改之后的app_main.cpp代码:

#include <inttypes.h>
#include <stdio.h>#include "img_converters.h"
#include "core/edgelab.h"
#include "fomo_mobilenetv2_model_data.h"#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/message_buffer.h"#include "http_stream.h"#define DEMO_WIFI_SSID   "huochaigun"
#define DEMO_WIFI_PASS   "12345678"#define STORAGE_SIZE_BYTES 128*1024static uint8_t *ucStorageBuffer;StaticMessageBuffer_t xMessageBufferStruct;#define kTensorArenaSize (1024 * 1024)uint16_t color[] = {0x0000,0x03E0,0x001F,0x7FE0,0xFFFF,
};extern "C" void app_main(void) {using namespace edgelab;Device*  device  = Device::get_device();device->init();printf("device_name:%s\n", device->get_device_name() );Network* net = device->get_network();el_printf(" Network Demo\n");uint32_t cnt_for_retry = 0;net->init();while (net->status() != NETWORK_IDLE) {el_sleep(100);if(cnt_for_retry++ > 50) {net->init();cnt_for_retry = 0;}}el_printf(" Network initialized!\n");cnt_for_retry = 0;net->join(DEMO_WIFI_SSID, DEMO_WIFI_PASS);while (net->status() != NETWORK_JOINED) {el_sleep(100);if(cnt_for_retry++ > 100) {net->join(DEMO_WIFI_SSID, DEMO_WIFI_PASS);cnt_for_retry = 0;}}el_printf(" WIFI joined!\n");  //    Display* display = device->get_display();Camera*  camera  = device->get_camera();//   display->init();camera->init(240, 240);ucStorageBuffer = (uint8_t *)malloc( STORAGE_SIZE_BYTES );if( ucStorageBuffer != NULL ){xMessageBuffer = xMessageBufferCreateStatic( STORAGE_SIZE_BYTES, ucStorageBuffer, &xMessageBufferStruct );if( xMessageBuffer == NULL ){// There was not enough heap memory space available to create the// message buffer.printf("Create xMessageBuffer fail\n");}}else{printf("malloc ucStorageBuffer fail\n");}start_http_stream();auto* engine       = new EngineTFLite();auto* tensor_arena = heap_caps_malloc(kTensorArenaSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);engine->init(tensor_arena, kTensorArenaSize);engine->load_model(g_fomo_mobilenetv2_model_data, g_fomo_mobilenetv2_model_data_len);auto* algorithm = new AlgorithmFOMO(engine);while (true) {el_img_t img;camera->start_stream();camera->get_frame(&img);algorithm->run(&img);uint32_t preprocess_time  = algorithm->get_preprocess_time();uint32_t run_time         = algorithm->get_run_time();uint32_t postprocess_time = algorithm->get_postprocess_time();uint8_t  i                = 0u;for (const auto& box : algorithm->get_results()) {el_printf("\tbox -> cx_cy_w_h: [%d, %d, %d, %d] t: [%d] s: [%d]\n",box.x,box.y,box.w,box.h,box.target,box.score);int16_t y = box.y - box.h / 2;int16_t x = box.x - box.w / 2;el_draw_rect(&img, x, y, box.w, box.h, color[++i % 5], 4);}el_printf("preprocess: %d, run: %d, postprocess: %d\n", preprocess_time, run_time, postprocess_time);
//        display->show(&img);uint8_t * jpg_buf;size_t jpg_buf_len;bool jpeg_converted = fmt2jpg( img.data, img.size, img.width, img.height, PIXFORMAT_RGB565, 30, &jpg_buf, &jpg_buf_len);if( jpeg_converted == true ){
//            printf("jpg_buf_len:%d\n", jpg_buf_len );if( xMessageBuffer != NULL ){xMessageBufferSend( xMessageBuffer, jpg_buf, jpg_buf_len , 0 );}free(jpg_buf);}camera->stop_stream();}delete algorithm;delete engine;
}

说明:RGB转为jpg的图像质量为30,这样转换后的图形数据小,视频流更流畅。

3、http服务

http_stream.cpp代码:

#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>#include "esp_log.h"
#include "esp_timer.h"#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/event_groups.h"
#include "esp_http_server.h"
#include "freertos/message_buffer.h"#define PART_BOUNDARY "123456789000000000000987654321"static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";
static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n";static const char *TAG = "http_stream";MessageBufferHandle_t xMessageBuffer;
/*** @brief  jpg_stream_httpd_handler* @param  None* @retval None*/
esp_err_t jpg_stream_httpd_handler(httpd_req_t *req)
{esp_err_t res = ESP_OK;size_t _jpg_buf_size;size_t _jpg_buf_len;uint8_t * _jpg_buf;char * part_buf[64];static int64_t last_frame = 0;if(!last_frame) {
//		last_frame = esp_timer_get_time();}_jpg_buf_size = 128*1024;_jpg_buf = (uint8_t *)malloc( _jpg_buf_size );if( _jpg_buf == NULL ){return res;}xMessageBufferReset( xMessageBuffer );res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE);if(res != ESP_OK){return res;}while(true){size_t xReceivedBytes = xMessageBufferReceive( xMessageBuffer, _jpg_buf, _jpg_buf_size, pdMS_TO_TICKS(100) );_jpg_buf_len = xReceivedBytes;res = ESP_FAIL;if( _jpg_buf_len > 0 ){res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));}else{continue;}if(res == ESP_OK){size_t hlen = snprintf((char *)part_buf, 64, _STREAM_PART, _jpg_buf_len);res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen);}if(res == ESP_OK){res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len);}if(res != ESP_OK){break;}}free( _jpg_buf );last_frame = 0;return res;
}httpd_uri_t uri_get_mjpeg = {.uri = "/",.method = HTTP_GET,.handler = jpg_stream_httpd_handler,.user_ctx = NULL};/*** @brief  start http_stream.* @param  None.* @retval None.*/
httpd_handle_t start_http_stream( void )
{printf("start_http_stream\n");/* 生成默认的配置参数 */httpd_config_t config = HTTPD_DEFAULT_CONFIG();config.server_port = 8081;/* 置空 esp_http_server 的实例句柄 */httpd_handle_t server = NULL;/* 启动 httpd server */if (httpd_start(&server, &config) == ESP_OK){/* 注册 URI 处理程序 */// httpd_register_uri_handler(server, &uri_get);// httpd_register_uri_handler(server, &uri_get_1m);httpd_register_uri_handler(server, &uri_get_mjpeg);}/* 如果服务器启动失败,返回的句柄是 NULL */return server;
}

http_stream.h代码:

#ifndef __HTTP_STREAM_H__
#define __HTTP_STREAM_H__extern MessageBufferHandle_t xMessageBuffer;void start_http_stream( void );#endif
4、修改PSRAM的配置

由于增加的功能需要消耗很多RAM空间,所以需要将PSRAM充分利用起来。

执行idf.py menuconfig,修改SPI RAM config,将malloc()阀值改小一些,这里改为4096字节,意思是使用malloc()分配内存时,大于4096字节则从外部PSRAM获取,配置如下:

 Component config  --->

        ESP PSRAM  --->

                SPI RAM config  --->

                        (4096) Maximum malloc() size, in bytes, to always put in internal memory

四 、运行测试

1、编译、烧录、监视
idf.py build
idf.py flash
idf.py monitor

连接AP的日志:

I (813) wifi:mode : sta (dc:54:75:d7:a2:10)
I (813) wifi:enable tsfNetwork initialized!
I WAITING FOR IP...I (2033) wifi:new:<11,0>, old:<1,0>, ap:<255,255>, sta:<11,0>, prof:1
I (2403) wifi:state: init -> auth (b0)
I (2413) wifi:state: auth -> assoc (0)
I (2423) wifi:state: assoc -> run (10)
W (2423) wifi:[ADDBA]rx delba, code:39, delete tid:5
I (2443) wifi:<ba-add>idx:0 (ifx:0, 90:76:9f:23:a3:58), tid:5, ssn:6, winSize:64
I (2583) wifi:connected with CMCC-2106, aid = 1, channel 11, BW20, bssid = 90:76:9f:23:a3:58
I (2583) wifi:security: WPA2-PSK, phy: bgn, rssi: -63
I (2583) wifi:pm start, type: 1I (2583) wifi:dp: 1, bi: 102400, li: 3, scale listen interval from 307200 us to 307200 us
I (2583) wifi:set rx beacon pti, rx_bcn_pti: 0, bcn_timeout: 25000, mt_pti: 0, mt_time: 10000
I (2633) wifi:AP's beacon interval = 102400 us, DTIM period = 1
I (3583) esp_netif_handlers: edgelab ip: 192.168.10.104, mask: 255.255.255.0, gw: 192.168.10.1

 可见IP地址为192.168.10.104。

2、浏览器获取视频流

同一个局域网的电脑启动浏览器,地址栏输入:192.168.10.104:8081,然后回车,浏览器会显示视频,图像分辨率为240*240,因为转换为jpg的质量设置的较低,所以不怎么清晰,下图为浏览器显示的图像:

 

有方框表示识别到了物体。

五、总结

此模型主要是对尺寸较小且颜色较深的物体能检测。

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

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

相关文章

ChatGPT在地学、GIS、气象、农业、生态、环境等领域中的高级应用

目录 ​专题一 开启大模型 专题二 基于ChatGPT大模型提问框架 专题三 基于ChatGPT大模型的数据清洗 专题四 基于ChatGPT大模型的统计分析 专题五 基于ChatGPT大模型的机器学习 专题六 基于ChatGPT大模型的科研绘图 专题七 基于ChatGPT大模型的GIS应用 专题八 基于基于C…

FTP原理与配置

FTP是用来传送文件的协议。使用FTP实现远程文件传输的同时&#xff0c;还可以保证数据传输的可靠性和高效性。 FTP的应用 FTP 提供了一种在服务器和客户机之间上传和下载文件的有效方式。在企业网络中部署一台FTP服务器&#xff0c;将网络设备配置为FTP客户端&#xff0c;则可…

在Ubuntu20.04配置PX4环境

目录 1.下载PX4源码2.安装PX4所有工具链3.编译PX4工程1.下载PX4源码 打开Ubuntu,Ctrl+Alt+T打开终端输入下面代码: git clone https://github.com/PX4/PX4-Autopilot.git --recursive出现上图中出现“Command ‘git’ not found, but can be installed with”,使用以下代码…

蓝桥杯嵌入式KEY

1.按键原理图 2.按键GPIO引脚设置成输入&#xff0c;上拉模式 3.设置TIM4时钟源为外部时钟源 PSC为80-1 Period为10000-1 打开NVIC 中断时间为10ms 4.在bsp文件中添加interrupt.c文件 5.按键单击代码 6.长按键 7.按键过程和显示过程

c语言结构体(初阶)

1. 结构体的声明 1.1 结构体的基础知识 结构是一些值的集合&#xff0c;这些值被称为成员变量。结构的每个成员可以是不同类型的变量。 1.2 结构的声明 struct tag {member - list; }variable-list; 例&#xff1a;描述一个人的信息&#xff1a;名字电话性别身高 //声明的…

深入浅出:分布式、CAP 和 BASE 理论(荣耀典藏版)

大家好&#xff0c;我是月夜枫&#xff0c;一个漂泊江湖多年的 985 非科班程序员&#xff0c;曾混迹于国企、互联网大厂和创业公司的后台开发攻城狮。 在计算机科学领域&#xff0c;分布式系统是一门极具挑战性的研究方向&#xff0c;也是互联网应用中必不可少的优化实践&…

LabVIEW利用视觉引导机开发器人精准抓取

LabVIEW利用视觉引导机开发器人精准抓取 本项目利用单目视觉技术指导多关节机器人精确抓取三维物体的技术。通过改进传统的相机标定方法&#xff0c;结合LabVIEW平台的Vision Development和Vision Builder forAutomated Inspection组件&#xff0c;优化了摄像系统的标定过程&a…

ROS学习记录:如何在Github上寻找并安装软件包

一、打开网页输入www.github.com 二、进入github界面 三、打开一个终端&#xff0c;输入mkdir catkin_ws1建立一个工作空间 四、使用cd catkin_ws1进入工作空间 五、使用mkdir src创建一个子目录src就是source&#xff0c;原始资料的意思,指的就是程序源代码这类资源材料&#…

小机器人,电子锁,牙刷,表类开关,磁阀开关等一些安防直流驱动的选型介绍分析

安防监控是一门被人们日益重视的新兴行业&#xff0c;就目前发展来看&#xff0c;应用普及程度越来越广&#xff0c;科技含量也越来越高&#xff0c;几乎所有高新科技都可促进其发展&#xff0c;尤其是信息时代的来临&#xff0c;更为该行业的发展提供契机。其中安防领域最为典…

electron 菜单栏打开指定url页面菜单实现方法

electron 菜单栏打开指定url页面菜单 可以是本地URL也可以是远程的URL 自动判断跳转 以下代码可以在主进程main.js里面也可以是在独立的模块文件里面 const { BrowserWindow } require(electron);//定义窗口加载URL export const winURL process.env.NODE_ENV development …

Android原生实现单选

六年前写的一个控件&#xff0c;一直没有时间总结&#xff0c;趁年底不怎么忙&#xff0c;整理一下之前写过的组件。供大家一起参考学习。废话不多说&#xff0c;先上图。 一、效果图 实现思路使用的是radioGroup加radiobutton组合方式。原理就是通过修改RadioButton 的backgr…

企业私有云容器化架构运维实战

企业私有云容器化架构运维实战 了解 什么是虚拟化: 虚拟化&#xff08;Virtualization&#xff09;技术最早出现在 20 世纪 60 年代的 IBM 大型机系统&#xff0c;在70年代的 System 370 系列中逐渐流行起来&#xff0c;这些机器通过一种叫虚拟机监控器&#xff08;Virtual M…

java浅拷贝BeanUtils.copyProperties引发的RPC异常 | 京东物流技术团队

背景 近期参与了一个攻坚项目&#xff0c;前期因为其他流程原因&#xff0c;测试时间已经耽搁了好几天了&#xff0c;本以为已经解决了卡点&#xff0c;后续流程应该顺顺利利的&#xff0c;没想到 人在地铁上&#xff0c;bug从咚咚来~ 没有任何修改的服务接口&#xff0c;抛出…

配置管理员使用Local方式认证并授权用户级别示例

AAA简介 访问控制是用来控制哪些用户可以访问网络以及可以访问的网络资源。AAA是Authentication&#xff08;认证&#xff09;、Authorization&#xff08;授权&#xff09;和Accounting&#xff08;计费&#xff09;的简称&#xff0c;提供了在NAS&#xff08;Network Access…

OpenAI大模型中的模型推理

模型推理 推理有两个方案&#xff0c;一个和训练相同&#xff0c;直接加入Lora层&#xff0c;不过会增加推理延时因为多了lora层的计算&#xff0c;适合线下测评用&#xff0c;如下 from peft import PeftModel from transformers import AutoModel, AutoTokenizer ​ model …

解密负载均衡:如何平衡系统负载(下)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

spring boot 增量包部署,jar包变小

##pom.xml配置 <plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><layout>ZIP</layout><includes><include><groupId&…

云原生数据库性能对比(阿里云、百度智能云、腾讯云)

本文作者 LYZ 近些年&#xff0c;云原生数据库成为云厂商的重要发展方向&#xff0c;阿里云、百度智能云、腾讯云均先后发布了自研的云原生数据库。笔者认为云原生数据库具有更高的性价比、更极致的弹性&#xff0c;可以满足业务发展的不同阶段和负载场景的需求&#xff0c;也是…

FPGA高端项目:SDI 视频+音频编解码,提供工程源码和技术支持

目录 1、前言免责声明 2、相关方案推荐我这里已有的 GT 高速接口解决方案我目前已有的SDI编解码方案 3、设计思路和框架设计框图GV8601A均衡EQGTX 时钟要求GTX 调用与控制SMPTE SD/HD/3G-SDISMPTE SD/HD/3G-SDI 接收SMPTE SD/HD/3G-SDI 发送 SDI 视频接收数据处理SDI 音频接收-…

pycharm 工具栏不见了

新版pycharm后&#xff0c; 菜单栏和工具栏不见了 目录 我发现的解决方法&#xff1a; 其他旧版的解决方法&#xff1a; 我发现的解决方法&#xff1a; 其他旧版的解决方法&#xff1a; 另外&#xff0c;一些使用pycharm的新手可能会由于不熟悉软件的功能而误操作&#xff…