[ESP32]:基于HTTP实现百度AI识图

ESP32开发路程I2S篇——音频播放,自定义分区 自定义分区,自建分区表,将自建分区烧录至 ESP32,通过 I2S 播放音频文件,完整代码展示 阅读详情

[ESP32]:基于HTTP实现百度AI识图

测试环境:

  • esp32-s3
  • esp idf 5.1

首先,先配置sdk,可以写入到sdkconfig.defaults

CONFIG_IDF_TARGET="esp32s3"
CONFIG_IDF_TARGET_ESP32S3=y

CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

CONFIG_ESP_TLS_INSECURE=y
CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY=y

这里关闭了认证,并且建了分区表来存放我们待识别的图片。

1.百度控制台调试

1.获取token

在这里插入图片描述

2.在线调试,看下传输过程

在这里插入图片描述

主要关注如下内容:

header:

{
    "Accept": "application/json",
    "Content-Type": "application/x-www-form-urlencoded"
}

body:

image=%2F9j%2F4AAQSkZJRgABAQEBLAEsAAD%2F2wBDAAUEBAUEAwUFBAUGBgUGCA4JCAcHCBEMDQoO...

其中imge图像要先base64编码,在url编码

2.esp32调试

我们这里主要参考esp http client的代码

1.base64编码

esp-idf中已经有base64编码的代码,我们include一下即可

#include "mbedtls/base64.h"

int mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen,
                          const unsigned char *src, size_t slen)
2.url编码

这个要自己实现一下

int url_encode(const unsigned char *src, size_t slen, size_t *olen, unsigned char *dst, size_t dlen)
{
    size_t i, j = 0;

    // clac encoed size
    for (i = 0; i < slen; i++)
    {
        if ((src[i] >= 'A' && src[i] <= 'Z') ||
            (src[i] >= 'a' && src[i] <= 'z') ||
            (src[i] >= '0' && src[i] <= '9') ||
            src[i] == '-' || src[i] == '_' || src[i] == '.' || src[i] == '~')
        {
            j++;
        }
        else if (src[i] == ' ')
        {
            j++;
        }
        else
        {
            j += 3; // length of %xx is three
        }
    }

    // check buffer size
    if (dlen < j + 1)
    {
        *olen = j + 1; // reytun need size
        return -1;
    }

    // url encode
    for (i = 0, j = 0; i < slen; i++)
    {
        if ((src[i] >= 'A' && src[i] <= 'Z') ||
            (src[i] >= 'a' && src[i] <= 'z') ||
            (src[i] >= '0' && src[i] <= '9') ||
            src[i] == '-' || src[i] == '_' || src[i] == '.' || src[i] == '~')
        {
            dst[j++] = src[i];
        }
        else if (src[i] == ' ')
        {
            dst[j++] = '+';
        }
        else
        {
            dst[j++] = '%';
            dst[j++] = "0123456789ABCDEF"[src[i] >> 4];
            dst[j++] = "0123456789ABCDEF"[src[i] & 0x0F];
        }
    }

    // add end
    dst[j] = '\0';

    // return size
    *olen = j;

    return 0;
}
3.添加http client的调用
 char post_url[1024] = {0};
    esp_http_client_config_t config = {
        .method = HTTP_METHOD_POST,
        .event_handler = app_http_baidu_event_handler,
        .buffer_size = 4 * 1024,
    };
    sprintf(post_url, "%s?access_token=%s", base_url, access_token);
    config.url = post_url;
    esp_http_client_handle_t client = esp_http_client_init(&config);
    esp_http_client_set_method(client, HTTP_METHOD_POST);
    esp_http_client_set_post_field(client, img_params, strlen(img_params)); //填入url编码后的图像数据
    esp_http_client_set_header(client, "Content-Type", "application/x-www-form-urlencoded");
    esp_err_t err = esp_http_client_perform(client);
    if (err == ESP_OK)
    {
        ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %d", esp_http_client_get_status_code(client), (int)esp_http_client_get_content_length(client));
    }
    else
    {
        ESP_LOGI(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));
    }
    esp_http_client_cleanup(client);
4.整体代码
#include "app_baidu.h"
#include "mbedtls/base64.h"
#include "esp_http_client.h"
#include "esp_log.h"
#include "esp_heap_caps.h"
#include "string.h"

static const char *TAG = "HTTP_BAIDU";

char access_token[256] = "xxxx"; //更换自己的token
char base_url[256] = "https://aip.baidubce.com/rest/2.0/image-classify/v2/advanced_general";

esp_err_t app_http_baidu_event_handler(esp_http_client_event_t *evt)
{
    if (evt->event_id == HTTP_EVENT_ON_DATA)
    {
        ESP_LOGI(TAG, "%s",(char *)evt->data);
    }

    return ESP_OK;
}

int url_encode(const unsigned char *src, size_t slen, size_t *olen, unsigned char *dst, size_t dlen)
{
    size_t i, j = 0;

    // clac encoed size
    for (i = 0; i < slen; i++)
    {
        if ((src[i] >= 'A' && src[i] <= 'Z') ||
            (src[i] >= 'a' && src[i] <= 'z') ||
            (src[i] >= '0' && src[i] <= '9') ||
            src[i] == '-' || src[i] == '_' || src[i] == '.' || src[i] == '~')
        {
            j++;
        }
        else if (src[i] == ' ')
        {
            j++;
        }
        else
        {
            j += 3; // length of %xx is three
        }
    }

    // check buffer size
    if (dlen < j + 1)
    {
        *olen = j + 1; // reytun need size
        return -1;
    }

    // url encode
    for (i = 0, j = 0; i < slen; i++)
    {
        if ((src[i] >= 'A' && src[i] <= 'Z') ||
            (src[i] >= 'a' && src[i] <= 'z') ||
            (src[i] >= '0' && src[i] <= '9') ||
            src[i] == '-' || src[i] == '_' || src[i] == '.' || src[i] == '~')
        {
            dst[j++] = src[i];
        }
        else if (src[i] == ' ')
        {
            dst[j++] = '+';
        }
        else
        {
            dst[j++] = '%';
            dst[j++] = "0123456789ABCDEF"[src[i] >> 4];
            dst[j++] = "0123456789ABCDEF"[src[i] & 0x0F];
        }
    }

    // add end
    dst[j] = '\0';

    // return size
    *olen = j;

    return 0;
}

// base64 encode: http://www.yzcopen.com/img/imgbase64
// url encode: https://www.jyshare.com/front-end/695/?
void app_baidu_classification(char *img_buf, int file_size)
{
    char *img_base64 = NULL;
    char *img_params = NULL;
    char *img_base64_url = NULL;
    char *img_params_format = "image=%s";
    size_t img_base64_size = 0;
    size_t img_base64_url_size = 0;

    // base64 encode
    mbedtls_base64_encode(NULL, 0, &img_base64_size, (const unsigned char *)img_buf, file_size);
    ESP_LOGI(TAG, "Image size after bash64:%zu", img_base64_size);

    img_base64 = heap_caps_calloc(1, img_base64_size + 1, MALLOC_CAP_DMA);
    if (img_base64 == NULL)
    {
        ESP_LOGI(TAG, "Memory image bash64 allocation failed");
        return;
    }
    mbedtls_base64_encode((unsigned char *)img_base64, img_base64_size + 1, &img_base64_size, (const unsigned char *)img_buf, file_size);

    // url encode
    url_encode((const unsigned char *)img_base64, img_base64_size, &img_base64_url_size, NULL, 0);
    ESP_LOGI(TAG, "Image size after url:%zu", img_base64_url_size);

    img_base64_url = heap_caps_calloc(1, img_base64_url_size + 1, MALLOC_CAP_DMA);
    if (img_base64_url == NULL)
    {
        ESP_LOGI(TAG, "Memory image bash64 url allocation failed");
        free(img_base64);
        return;
    }
    url_encode((const unsigned char *)img_base64, img_base64_size, &img_base64_url_size, (unsigned char *)img_base64_url, img_base64_url_size + 1);

    // set data params
    img_params = heap_caps_calloc(1, img_base64_url_size + 1 + strlen(img_params_format), MALLOC_CAP_DMA);
    if (img_params == NULL)
    {
        ESP_LOGI(TAG, "Memory image params allocation failed");
        free(img_base64);
        free(img_base64_url);
        return;
    }

    sprintf(img_params, img_params_format, img_base64_url);

    // http client setting

    char post_url[1024] = {0};
    esp_http_client_config_t config = {
        .method = HTTP_METHOD_POST,
        .event_handler = app_http_baidu_event_handler,
        .buffer_size = 4 * 1024,
    };
    sprintf(post_url, "%s?access_token=%s", base_url, access_token);
    config.url = post_url;
    esp_http_client_handle_t client = esp_http_client_init(&config);
    esp_http_client_set_method(client, HTTP_METHOD_POST);
    esp_http_client_set_post_field(client, img_params, strlen(img_params));
    esp_http_client_set_header(client, "Content-Type", "application/x-www-form-urlencoded");
    esp_err_t err = esp_http_client_perform(client);
    if (err == ESP_OK)
    {
        ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %d", esp_http_client_get_status_code(client), (int)esp_http_client_get_content_length(client));
    }
    else
    {
        ESP_LOGI(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));
    }
    esp_http_client_cleanup(client);

    free(img_base64);
    free(img_base64_url);
    free(img_params);
}

3.实验效果

拿了一张泰勒的图来识别

在这里插入图片描述

在这里插入图片描述

【丁丁历险记】ESP32-CAM做图像识别 【丁丁历险记】Arduino配置esp8266/esp32开发环境 【丁丁历险记】ESP8266配置microPython 【丁丁历险记】ESP8266花式连接wifi 【丁丁历险记】ESP8266/ESP32做微信遥控语音识别 【丁丁历险记】ESP8266/ESP32发送数据到微信 【丁丁历险记】Arduino IDE编译ESP8266/ESP32代码加密 【丁丁历险记】ESP32... 阅读详情

相关推荐

用ESP32S3 Sense做个会聊天的智能硬件:手把手教你接入百度语音和MiniMax大模型

本文详细介绍了如何基于ESP32S3 Sense开发板打造智能语音助手,涵盖硬件选型、百度语音识别API集成、MiniMax大模型对话引擎对接等关键技术。通过Arduino开发环境配置和代码优化,实现从语音采集到智能对话的全流程解决方案,适用于智能家居、工业质检等多种应用场景。

weixin_26846533的博客 351

半小时内实现Esp32-Cam模型训练和图像识别

半小时内实现Esp32-Cam物体识别。

weixin_44035986的博客 3万+

基于ESP32与大模型的智能语音交互系统设计与实现

本文详细介绍了基于ESP32与大模型的智能语音交互系统设计与实现方案。通过ESP32硬件平台结合开源大模型,实现了低成本、高效率的语音交互系统,涵盖声音采集、语音识别、语义理解、内容生成和语音合成全流程。文章提供了硬件选型、电路连接、大模型服务接入及语音处理等关键技术实现细节,适合创客和教育场景应用。

weixin_29174141的博客 438

【ESP32CAM识别图形左边界】(一)初步使用ESP32CAM

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 前言 ESP32-CAM是安信可最新发布小尺寸的摄像头模组。这款摄像头可以满足最低的图像 一、ESP-32CAM是什么? 我直接在淘宝买的一整套这款摄像头。 二、使用步骤 1.引入库 代码如下(示例): import numpy as np import pandas as p.

xanadw的博客 6242

基于掌控板与AI图像识别的智能垃圾分类系统设计与实现

图像识别作为计算机视觉的基础技术,其核心原理是通过算法模型让计算机“看懂”图像内容。这项技术通过提取图像特征并进行分类,赋予了机器感知环境的能力,在智能安防、自动驾驶、工业质检等领域价值巨大。随着物联网和边缘计算的发展,图像识别与嵌入式硬件结合,催生了众多创新的应用场景。本文聚焦于一个典型的AIoT实践案例——智能垃圾分类系统。项目利用掌控板作为主控,结合内置视觉算法的智能摄像头模块(如HuskyLens)或云端AI服务(如Teachable Machine),实现了对垃圾物品的实时识别与自动分类。通过**

weixin_34082695的博客 468

AI编程副驾驶实战指南:VS Code+Claude Code五年进阶路径

AI编程不是替代程序员,而是重构开发者的角色定位——从代码执行者升级为需求抽象者与AI协作者。其底层原理在于大模型对上下文理解、模式识别与多步推理的增强能力,技术价值体现在提升工程确定性、加速知识复用、强化系统可维护性。典型应用场景覆盖智能调试(如Python爬虫反爬策略生成)、Git协同审查、MCP插件驱动的端到端测试,以及基于SDD规范的AI原生架构设计。本文聚焦VS Code深度集成与Claude Code权限控制、@-提及上下文锚定、MCP外设调用等硬核实践,提供可落地的五年能力跃迁路线。

aocaiti5781的博客 600

AI原生IDE的本质:从代码补全到工程意图理解

AI原生IDE已超越传统代码补全工具,演进为具备工程上下文理解能力的智能开发内核。其核心在于将自然语言指令转化为AST遍历、符号表查询与依赖图推理等底层动作,实现对跨文件契约、调试会话动态修正及多文档联合语义的深度解析。技术价值体现在可验证的意图承载、可审计的决策过程与资源可控的本地化推理,广泛应用于微服务重构、Kafka故障诊断、嵌入式固件生成等真实工程场景。本文聚焦Trae Solo、Cursor Pro与VS Code在‘理解-决策-执行’链上的代际差异,揭示AI如何从写代码走向理解工程。

hqmln的博客 424

【雕爷学编程】MicroPython手册之 ESP32-CAM 图像识别

首先,我们需要一个训练好的分类器模型文件(haarcascade_frontalface_default.xml),这个模型文件是OpenCV自带的一种用于面部识别的分类器模型。需要评估ESP32-CAM的计算能力,并根据应用场景选择合适的算法和优化方法,以实现实时的图像识别。智能监控和安防:ESP32-CAM可以应用于智能监控和安防领域,用于识别和分类场景中的人、车等物体。合适的数据集和标注工作是必要的,同时需要选择合适的算法和模型架构,并进行充分的训练和验证。这为图像识别系统提供了灵活性和扩展性。

雕爷学编程 3226

【ESP32 S3开发】在Arduino IDE中使用PSRAM

最近使用ESP32 WROOM开发语音识别项目时,需要使用阵列麦克风采集信号,并进行切片取出含有语音部分的片段,进而使用编码将语音上传到后端服务器进行识别。在项目开发时,发现虽然ESP32 WROOM有520KB的SRAM,但是还是无法满足语音识别的需求。查找资料后,发现ESP32-S3N16R8带有8MB的PSRAM,下面记录ESP32-S3 PSRAM的配置与测试方法。ESP32-S3的开发板配置见之前的一篇笔记。在Arduino IDE中配置完开发板后,还需要手动开启PSRAM功能,否则调用相关函数时

m0_43395703的博客 1万+

使用 OpenCV 进行基于 ESP32 CAM 的目标检测和识别

介绍使用 OpenCV 进行基于 ESP32 CAM 的目标检测和识别实现。

DT程序员的博客 4797

esp-idf的内存管理——内存调试

目录1 堆调试功能的使能1.1 通过Kconfig使能1.2 使能之后源码层面的变化2 堆调试功能——POISONING3 堆调试功能——TRACE4 堆调试功能的使用经验参考 1 堆调试功能的使能 1.1 通过Kconfig使能 idf提供了两种堆调试机制,POISONING以及TRACE。默认情况下,堆调试是未使能的。可以在menuconfig中配置使能,位置在: Component config Heap memory debugging POISONING默认是no poisoning,但

gzxb1995的博客 2558

base64编解码的两个函数

base64编解码的两个函数,声明,参考网络上的代码实现。 unsigned char *base64_encode(unsigned char *str, long* lpBufLen) { long len; long str_len; unsigned char *res; int i,j; //定义base64编码表...

weixin_30401605的博客 429

Zotero+Obsidian+Bookxnote联动让文献阅读丝滑般体验

摘录文字或图片到Obsidian

weixin_43694742的博客 1万+

【esp32-s3】6.3 文件系统——wav格式判定及存储信息

存储wav文件信息

qq_38091632的博客 1114

PostgreSQL向量数据插件--pgvector安装(附PostgreSQL安装)

本文为本人在安装pgvector中踩过的坑,已找到解决方法,现向大家分享。

m0_62627802的博客 2万+

别再为FPGA程序裸奔发愁了!手把手教你用Quartus和AES256给Altera芯片上把‘锁’

本文详细介绍了如何为Altera/Intel FPGA芯片(如Cyclone系列)构建可靠的AES256加密体系,涵盖密钥类型选择、Quartus实操到JTAG链路验证的全流程。通过硬件级AES256引擎实现配置流解密,确保FPGA程序的安全保护,适用于工业控制器等高安全需求场景。

weixin_28309571的博客 389

ESP32实现Wave(.wav)音频文件输出

ESP32实现Wave(.wav)音频文件输出

LJH021028的博客 5263

分子动力学模拟学习1-采用AmberTools21的MCPB.py构建金属蛋白的top文件

分子动力学模拟学习1-采用AmberTools21的MCPB.py构建金属蛋白的top文件

weixin_45011386的博客 3827

esp32 图片base64转码 遇到的问题与解决

【代码】esp32 图片base64转码 遇到的问题与解决。

ResumeProject的博客 2405

【音视频 ffmpeg 学习】 RTMP推流 mp4文件

3.当RTMP协议在互联网中传输数据的时候,消息会被拆分成更小的单元,称为消息块(Chunk)。1.RTMP(实时消息传输协议)是Adobe 公司开发的一个基于TCP的应用层协议。2.RTMP协议中基本的数据单元称为消息(Message)。下载地址:http://nginx.org/download。下载 rtmp模块 到nginx 模块下。安装nginx 和 rtmp模块。(1). linux 环境准备。下载nginx安装包。使用 vcl 播放流。

weixin_45397344的博客 2276

我终于停止写 JUnit 了!用 JavaParser + GPT-4 自动生成 90% 覆盖率的单元测试

本文介绍了一种基于JavaParser和GPT-4的智能单元测试生成方案。针对开发者在单元测试编写中面临的繁琐、无聊和硬指标等问题,提出通过AST语法树分析代码结构,提取关键信息后生成精准提示词,再调用GPT-4自动生成高质量的单元测试代码。文章详细阐述了技术原理、实现步骤(包括JavaParser解析、上下文感知提示词构建和GPT-4调用),并展示了该方法能自动识别依赖、Mock对象和覆盖边界条件,显著提升测试效率。同时指出了在复杂数据结构、私有方法测试等方面的局限性,最终强调这种技术组合可以解放开发者,

BUG猿的博客 1131

安信可 ESP32-S3 模组上驱动摄像头 OV2640,实现远程拍照并 HTTP 传输到阿里云对象存储OSS,并显示在微信小程序上。(深度好文,全部开源)

文章目录一、 ESP32-S3 产品特性CPU 和存储外设接口和传感器功耗特性二、 准备工作硬件软件接线三、通讯协议和原理3.1 模组拍照上传服务器3.2 小程序下发指令给模组拍照给服务器3.3 模组把上传服务器结果回调给小程序四、服务器准备3.1 接收图片处理3.2 接收图片处理3.3 服务器业务逻辑五、嵌入式开发准备六、微信小程序开发准备源码下载联系我们 一、 ESP32-S3 产品特性    安信可已做好了ESP32S3模组,给大家看最近特火的ESP32S3模组规格书。

安信可科技 9188

复现论文《Analysis of circulating current mechanism of Grid-forming offshore wind farm based on DRU-HVDC》

该论文研究了基于二极管整流单元(DRU)和低频交流(LFAC)输电的构网型(GFM)海上风电场并网系统中环流的产生机理。由于 DRU 不可控,系统电压与频率依赖于风力发电机(WT)的网侧变流器,当多台 WT 并联运行时,因输出电压幅值、相位、输出阻抗或频率不匹配,会产生基频环流,导致系统损耗增加与稳定性下降。论文通过理论建模与 MATLAB/Simulink 仿真,分析了四种不平衡工况下的环流机理,并指出幅值不平衡和阻抗不平衡引起无功环流,相位不平衡引起有功环流,频率不平衡则引起环流振荡,为后续环流抑制研究

huanghm88的专栏 105

为什么要使用base64编码,有哪些情景需求?

为什么要使用base64编码,有哪些情景需求 公钥证书也好,电子邮件数据也好,经常要用到Base64编码,那么为什么要作一下这样的编码呢? 我们知道在计算机中任何数据都是按ascii码存储的,而ascii码的128~255之间的值是不可见字符。 而在网络上交换数据时,比如说从A地传到B地,往往要经过多个路由设备, 由于不同的设备对字符的处理方式有一些不同,这样那些不可见字符就有可能被处理错误,这...

Sam-zhang的博客 3117

RAG测评实战代码

本文主要介绍了RAG测评实战代码,希望对使用RAG的同学们有所帮助。 文章目录 1. 前言 2. 实战代码 2.1 实战代码一 2.2 实战代码二

herosunly的博客 1万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

ESP32接入百度云,在线语音识别

1开发环境及工具 开发板使用的是ESP32_LyraTv4.3,入下图所示,开环境在是在Ubuntu20.04上搭建的ESP-IDF,在ESP-IDF中添加了支持语音开发的sdk,ESP-ADF。 2开发过程 参考的例程为adf中esp-adf/examples/speech_recognition/asr这个目录下面的程序,这个目录中包含了离线的语音识别,其中包含了原始语音数据的采集。 3注意事项 参考ESP32开发(6)esp-adf:百度语音识别_lovehanchenchen的博客-C

libofu的博客 5050

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

上一篇: [全志T113]:5寸RGB屏幕测试
下一篇: [ESP32]:基于esp-modbus实现serial主机
YAN_KEEE
博客等级 码龄9年 287粉丝 41原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值