基于ART-Pi实现的AI图像识别

原创 RTThread物联网操作系统 2021-09-27 18:32


开源地址:

https://github.com/liukangcc/ART-PI_BAIDUAI


不用自己训练模型,也能进行 AI 图像识别;借助百度云平台,我们可以在 APT-Pi 上实现图像识别功能。

创建图像识别应用

1、打开链接 百度智能云, 申请账号;
2、打开控制台


3、打开图像识别


4、创建应用


5、获取 AK 和 SK

通用图像识别

该请求用于通用物体及场景识别,即对于输入的一张图片(可正常解码,且长宽比适宜),输出图片中的多个物体及场景标签。

1、打开 image_classify.c 文件, 修改 access_token, 填入应用的 AK 和 SK;

2、在 SD 卡中放入要识别的图片;

3、编译下载;

4、在终端输入命令: baidu_ai cat.jpg

5、加入百度百科,使能宏定义:#define BD_AI_BAIKE,编译下载:

返回说明

返回参数



菜品识别

该请求用于菜品识别。即对于输入的一张图片(可正常解码,且长宽比适宜),输出图片的菜品名称、卡路里信息、置信度。

1、修改 URL 为菜品识别:

1    index = strlen(BAIDU_AI_API[1]);
2    post_uri_size = index;
3    post_uri = rt_malloc(256);
4
5    rt_memcpy(post_uri, BAIDU_AI_API[1], post_uri_size);


2、编译下载;

3、识别结果:


返回说明

返回参数



监控报表

在百度服务端,可以查看 API 调用成功和失败的次数:



图像格式

图像格式转换流程:



1、百度 AI 支持的图像格式有:PNG、JPG、JPEG、BMP

2、原始的图片数据需要转换为 base64 编码

3、base64 编码的图片数据进行百分比编码

Base64 编码

请求图片需经过base64编码:图片的base64编码指将一副图片数据编码成一串字符串,使用该字符串代替图像地址。您可以首先得到图片的二进制,然后用Base64格式编码即可。

Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。可查看RFC2045~RFC2049,上面有MIME的详细规范。

Base64编码是从二进制到字符的过程,可用于在HTTP环境下传递较长的标识信息。采用Base64编码具有不可读性,需要解码后才能阅读。

Base64由于以上优点被广泛应用于计算机的各个领域,然而由于输出内容中包括两个以上“符号类”字符(+, /, =),不同的应用场景又分别研制了Base64的各种“变种”。为统一和规范化Base64的输出,Base62x被视为无符号化的改进版本。

百分比编码

百分比编码 是一种拥有8位字符编码的编码机制,这些编码在URL的上下文中具有特定的含义。它有时被称为URL编码。编码由英文字母替换组成:“%” 后跟替换字符的ASCII的十六进制表示。

需要编码的特殊字符有:':','/','?','#','[',']','@','!','$','&',"'",'(',')','*','+',',',';','=',以及,'%'` 本身.其他的字符虽然可以进行编码但是不需要。

':' '/' '?' '#' '[' ']' '@' '!' '$' '&' "'" '(' ')' '*' '+' ',' ';' '=' '%' ' '
%3A %2F %3F %23 %5B %5D %40 %21 %24 %26 %27 %28 %29 %2A %2B %2C %3B %3D %25 %20 或 +
根据上下文, 空白符 ’ ’ 将会转换为 ‘+’ (必须在HTTP的POST方法中使定义 application/x-www-form-urlencoded 传输方式), 或者将会转换为 ‘%20’ 的 URL。

图像识别流程

获取 token


 1   /* get token */
2int get_ai_token(const char *uri, unsigned char *token)
3
{
4    char *request = RT_NULL;
5    int token_len = 0, index = 0;
6
7    cJSON* cjson_parse = RT_NULL;
8    cJSON* cjson_token = RT_NULL;
9
10    if (webclient_request(uri, RT_NULL, RT_NULL, (unsigned char **)&request) < 0)
11    {
12        rt_kprintf("webclient send get request failed.");
13        return -RT_ERROR;
14    }
15
16    rt_kprintf("webclient send get request by simplify request interface.\n");
17    rt_kprintf("webclient get response data: \n");
18
19    for (index = 0; index < rt_strlen(request); index++)
20    {
21        rt_kprintf("%c", request[index]);
22    }
23    rt_kprintf("\n");
24
25    cjson_parse = cJSON_Parse(request);
26    if(cjson_parse == RT_NULL)
27    {
28        LOG_E("parse fail.\n");
29        goto __exit;
30    }
31
32    cjson_token = cJSON_GetObjectItem(cjson_parse, "access_token");
33    if (cjson_token == RT_NULL)
34    {
35        LOG_E("get onject 'access_token' item fail.\n");
36        goto __exit;
37    }
38
39    LOG_D("get_token: %s\n", cjson_token->valuestring);
40    token_len = rt_strlen(cjson_token->valuestring);
41    rt_memcpy(token, cjson_token->valuestring, token_len);
42
43__exit:
44
45    if (cjson_parse)
46    {
47        cJSON_Delete(cjson_parse);
48        cjson_parse = RT_NULL;
49        cjson_token = RT_NULL;
50    }
51
52    if (request)
53    {
54        web_free(request);
55    }
56
57    return token_len;
58}


图片数据编码

Base 64


 1static const char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2
3/* encode image */
4int base64_encode(unsigned char * bytes_to_encode, unsigned char *encode, int bytes_len)
5
{
6    int i = 0, j = 0, encode_size = 0;
7    unsigned char char_array_3[3];
8    unsigned char char_array_4[4];
9
10    while (bytes_len--)
11    {
12        char_array_3[i++] = *(bytes_to_encode++);
13
14        if (i == 3)
15        {
16            char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
17            char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
18            char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
19            char_array_4[3] = char_array_3[2] & 0x3f;
20
21            for(i = 0; i < 4; i++)
22            {
23                encode[encode_size++] = base64_chars[char_array_4[i]];
24            }
25            i = 0;
26        }
27    }
28
29    if (i)
30    {
31        for (j = i; j < 3; j++)
32        {
33            char_array_3[j] = '\0';
34        }
35
36        char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
37        char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
38        char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
39        char_array_4[3] = char_array_3[2] & 0x3f;
40
41        for(j = 0; (j < i + 1); j++)
42        {
43            encode[encode_size++] = base64_chars[char_array_4[j]];
44        }
45
46        while ((i++ < 3))
47        {
48            encode[encode_size++] = '=';
49        }
50    }
51
52    return encode_size;
53}


百分比编码

  1int http_percentage_coding(unsigned char *org_data, unsigned char *new_data, int len)
2
{
3    int i = 0;
4    unsigned char org_char = 0;
5
6    while (len--)
7    {
8        org_char = *(org_data++);
9        switch (org_char)
10        {
11        case ':' :
12            new_data[i++] = '%';
13            new_data[i++] = '3';
14            new_data[i++] = 'A';
15        break;
16
17        case '/' :
18            new_data[i++] = '%';
19            new_data[i++] = '2';
20            new_data[i++] = 'F';
21        break;
22
23        case '?' :
24            new_data[i++] = '%';
25            new_data[i++] = '3';
26            new_data[i++] = 'F';
27        break;
28
29        case '#' :
30            new_data[i++] = '%';
31            new_data[i++] = '2';
32            new_data[i++] = '3';
33        break;
34
35        case '[' :
36            new_data[i++] = '%';
37            new_data[i++] = '5';
38            new_data[i++] = 'B';
39        break;
40
41        case ']' :
42            new_data[i++] = '%';
43            new_data[i++] = '5';
44            new_data[i++] = 'D';
45        break;
46
47        case '@' :
48            new_data[i++] = '%';
49            new_data[i++] = '4';
50            new_data[i++] = '0';
51        break;
52
53        case '!' :
54            new_data[i++] = '%';
55            new_data[i++] = '2';
56            new_data[i++] = '1';
57        break;
58
59        case '$' :
60            new_data[i++] = '%';
61            new_data[i++] = '2';
62            new_data[i++] = '4';
63        break;
64
65        case '&' :
66            new_data[i++] = '%';
67            new_data[i++] = '2';
68            new_data[i++] = '6';
69        break;
70
71        case '\'' :
72            new_data[i++] = '%';
73            new_data[i++] = '2';
74            new_data[i++] = '7';
75        break;
76
77        case '(' :
78            new_data[i++] = '%';
79            new_data[i++] = '2';
80            new_data[i++] = '8';
81        break;
82
83        case ')' :
84            new_data[i++] = '%';
85            new_data[i++] = '2';
86            new_data[i++] = '9';
87        break;
88
89        case '*' :
90            new_data[i++] = '%';
91            new_data[i++] = '2';
92            new_data[i++] = 'A';
93        break;
94
95        case '+' :
96            new_data[i++] = '%';
97            new_data[i++] = '2';
98            new_data[i++] = 'B';
99        break;
100
101        case ',' :
102            new_data[i++] = '%';
103            new_data[i++] = '2';
104            new_data[i++] = 'C';
105        break;
106
107        case ';' :
108            new_data[i++] = '%';
109            new_data[i++] = '3';
110            new_data[i++] = 'B';
111        break;
112
113        case '=' :
114            new_data[i++] = '%';
115            new_data[i++] = '3';
116            new_data[i++] = 'D';
117        break;
118
119        case '%' :
120            new_data[i++] = '%';
121            new_data[i++] = '2';
122            new_data[i++] = '5';
123        break;
124
125        case ' ' :
126            new_data[i++] = '%';
127            new_data[i++] = '2';
128            new_data[i++] = '0';
129        break;
130
131        default:
132            new_data[i++] = org_char;
133        break;
134        }
135    }
136    return i;
137}


获取识别结果

 1int get_ai_result(const char *uri, const char *post_data, int post_data_size)
2
{
3    struct webclient_sessionsession = RT_NULL;
4    unsigned char *buffer = RT_NULL;
5    int index, result = 0, resp_status, bytes_read;
6
7    buffer = (unsigned char *)web_malloc(POST_RESP_BUFSZ);
8    if (buffer == RT_NULL)
9    {
10        rt_kprintf("no memory for receive response buffer.\n");
11        result = -RT_ENOMEM;
12        goto __exit;
13    }
14
15    /* create webclient session and set header response size */
16    session = webclient_session_create(POST_HEADER_BUFSZ);
17    if (session == RT_NULL)
18    {
19        result = -RT_ENOMEM;
20        goto __exit;
21    }
22
23    /*  add http header */
24    webclient_header_fields_add(session, "Content-Length: %d\r\n", post_data_size);
25    webclient_header_fields_add(session, "Content-Type: application/x-www-form-urlencoded\r\n");
26
27    /* send POST request by default header */
28    if ((resp_status = webclient_post(session, uri, (const char *)post_data)) != 200)
29    {
30        LOG_E("webclient POST request failed, response(%d) error.\n", resp_status);
31        result = -RT_ERROR;
32        goto __exit;
33    }
34
35    rt_kprintf("webclient post response data: \n");
36    do
37    {
38        bytes_read = webclient_read(session, buffer, POST_RESP_BUFSZ);
39        if (bytes_read <= 0)
40        {
41            break;
42        }
43        for (index = 0; index < bytes_read; index++)
44        {
45            rt_kprintf("%c", buffer[index]);
46        }
47
48    } while (1);
49
50    rt_kprintf("\n");
51
52__exit:
53    if (session)
54    {
55        webclient_close(session);
56    }
57
58    if (buffer)
59    {
60        web_free(buffer);
61    }
62
63    return result;  
64}



你可以添加微信17775982065为好友,注明:公司+姓名,拉进RT-Thread官方微信交流群!



👇 点击阅读原文进入官网

RTThread物联网操作系统 帮助您了解RT-Thread相关的资讯.
评论
  • 美国加州CEC能效跟DOE能效有什么区别?CEC/DOE是什么关系?美国加州CEC能效跟DOE能效有什么区别?CEC/DOE是什么关系?‌美国加州CEC能效认证与美国DOE能效认证在多个方面存在显著差异‌。认证范围和适用地区‌CEC能效认证‌:仅适用于在加利福尼亚州销售的电器产品。CEC认证的范围包括制冷设备、房间空调、中央空调、便携式空调、加热器、热水器、游泳池加热器、卫浴配件、光源、应急灯具、交通信号模块、灯具、洗碗机、洗衣机、干衣机、烹饪器具、电机和压缩机、变压器、外置电源、消费类电子设备
    张工nx808593 2025-02-27 18:04 123浏览
  • 在2024年的科技征程中,具身智能的发展已成为全球关注的焦点。从实验室到现实应用,这一领域正以前所未有的速度推进,改写着人类与机器的互动边界。这一年,我们见证了具身智能技术的突破与变革,它不仅落地各行各业,带来新的机遇,更在深刻影响着我们的生活方式和思维方式。随着相关技术的飞速发展,具身智能不再仅仅是一个技术概念,更像是一把神奇的钥匙。身后的众多行业,无论愿意与否,都像是被卷入一场伟大变革浪潮中的船只,注定要被这股汹涌的力量重塑航向。01为什么是具身智能?为什么在中国?最近,中国具身智能行业的进
    艾迈斯欧司朗 2025-02-28 15:45 226浏览
  •           近日受某专业机构邀请,参加了官方举办的《广东省科技创新条例》宣讲会。在与会之前,作为一名技术工作者一直认为技术的法例都是保密和侵权方面的,而潜意识中感觉法律有束缚创新工作的进行可能。通过一个上午学习新法,对广东省的科技创新有了新的认识。广东是改革的前沿阵地,是科技创新的沃土,企业是创新的主要个体。《广东省科技创新条例》是广东省为促进科技创新、推动高质量发展而制定的地方性法规,主要内容包括: 总则:明确立法目
    广州铁金刚 2025-02-28 10:14 109浏览
  • 一、VSM的基本原理震动样品磁强计(Vibrating Sample Magnetometer,简称VSM)是一种灵敏且高效的磁性测量仪器。其基本工作原理是利用震动样品在探测线圈中引起的变化磁场来产生感应电压,这个感应电压与样品的磁矩成正比。因此,通过测量这个感应电压,我们就能够精确地确定样品的磁矩。在VSM中,被测量的样品通常被固定在一个震动头上,并以一定的频率和振幅震动。这种震动在探测线圈中引起了变化的磁通量,从而产生了一个交流电信号。这个信号的幅度和样品的磁矩有着直接的关系。因此,通过仔细
    锦正茂科技 2025-02-28 13:30 104浏览
  • 在物联网领域中,无线射频技术作为设备间通信的核心手段,已深度渗透工业自动化、智慧城市及智能家居等多元场景。然而,随着物联网设备接入规模的不断扩大,如何降低运维成本,提升通信数据的传输速度和响应时间,实现更广泛、更稳定的覆盖已成为当前亟待解决的系统性难题。SoC无线收发模块-RFM25A12在此背景下,华普微创新推出了一款高性能、远距离与高性价比的Sub-GHz无线SoC收发模块RFM25A12,旨在提升射频性能以满足行业中日益增长与复杂的设备互联需求。值得一提的是,RFM25A12还支持Wi-S
    华普微HOPERF 2025-02-28 09:06 156浏览
  • 1,微软下载免费Visual Studio Code2,安装C/C++插件,如果无法直接点击下载, 可以选择手动install from VSIX:ms-vscode.cpptools-1.23.6@win32-x64.vsix3,安装C/C++编译器MniGW (MinGW在 Windows 环境下提供类似于 Unix/Linux 环境下的开发工具,使开发者能够轻松地在 Windows 上编写和编译 C、C++ 等程序.)4,C/C++插件扩展设置中添加Include Path 5,
    黎查 2025-02-28 14:39 146浏览
  • 2025年2月26日,广州】全球领先的AIoT服务商机智云正式发布“Gokit5 AI智能体开发板”,该产品作为行业首个全栈式AIoT开发中枢,深度融合火山引擎云原生架构、豆包多模态大模型、扣子智能体平台和机智云Aiot开发平台,首次实现智能体开发全流程工业化生产模式。通过「扣子+机智云」双引擎协同架构与API开放生态,开发者仅需半天即可完成智能体开发、测试、发布到硬件应用的全流程,标志着智能体开发进入分钟级响应时代。一、开发框架零代码部署,构建高效开发生态Gokit5 AI智能体开发板采用 “
    机智云物联网 2025-02-26 19:01 162浏览
  • 振动样品磁强计是一种用于测量材料磁性的精密仪器,广泛应用于科研、工业检测等领域。然而,其测量准确度会受到多种因素的影响,下面我们将逐一分析这些因素。一、温度因素温度是影响振动样品磁强计测量准确度的重要因素之一。随着温度的变化,材料的磁性也会发生变化,从而影响测量结果的准确性。因此,在进行磁性测量时,应确保恒温环境,以减少温度波动对测量结果的影响。二、样品制备样品的制备过程同样会影响振动样品磁强计的测量准确度。样品的形状、尺寸和表面处理等因素都会对测量结果产生影响。为了确保测量准确度,应严格按照规
    锦正茂科技 2025-02-28 14:05 149浏览
  • 更多生命体征指标风靡的背后都只有一个原因:更多人将健康排在人生第一顺位!“AGEs,也就是晚期糖基化终末产物,英文名Advanced Glycation End-products,是存在于我们体内的一种代谢产物” 艾迈斯欧司朗亚太区健康监测高级市场经理王亚琴说道,“相信业内的朋友都会有关注,最近该指标的热度很高,它可以用来评估人的生活方式是否健康。”据悉,AGEs是可穿戴健康监测领域的一个“萌新”指标,近来备受关注。如果站在学术角度来理解它,那么AGEs是在非酶促条件下,蛋白质、氨基酸
    艾迈斯欧司朗 2025-02-27 14:50 415浏览
  • 构建巨量的驾驶场景时,测试ADAS和AD系统面临着巨大挑战,如传统的实验设计(Design of Experiments, DoE)方法难以有效覆盖识别驾驶边缘场景案例,但这些边缘案例恰恰是进一步提升自动驾驶系统性能的关键。一、传统解决方案:静态DoE标准的DoE方案旨在系统性地探索场景的参数空间,从而确保能够实现完全的测试覆盖范围。但在边缘案例,比如暴露在潜在安全风险的场景或是ADAS系统性能极限场景时,DoE方案通常会失效,让我们看一些常见的DoE方案:1、网格搜索法(Grid)实现原理:将
    康谋 2025-02-27 10:00 253浏览
  • 应用趋势与客户需求,AI PC的未来展望随着人工智能(AI)技术的日益成熟,AI PC(人工智能个人电脑)逐渐成为消费者和企业工作中的重要工具。这类产品集成了最新的AI处理器,如NPU、CPU和GPU,并具备许多智能化功能,为用户带来更高效且直观的操作体验。AI PC的目标是提升工作和日常生活的效率,通过深度学习与自然语言处理等技术,实现更流畅的多任务处理、实时翻译、语音助手、图像生成等功能,满足现代用户对生产力和娱乐的双重需求。随着各行各业对数字转型需求的增长,AI PC也开始在各个领域中显示
    百佳泰测试实验室 2025-02-27 14:08 261浏览
  •         近日,广电计量在聚焦离子束(FIB)领域编写的专业著作《聚焦离子束:失效分析》正式出版,填补了国内聚焦离子束领域实践性专业书籍的空白,为该领域的技术发展与知识传播提供了重要助力。         随着芯片技术不断发展,芯片的集成度越来越高,结构也日益复杂。这使得传统的失效分析方法面临巨大挑战。FIB技术的出现,为芯片失效分析带来了新的解决方案。它能够在纳米尺度上对芯片进行精确加工和分析。当芯
    广电计量 2025-02-28 09:15 132浏览
  • 请移步 gitee 仓库 https://gitee.com/Newcapec_cn/LiteOS-M_V5.0.2-Release_STM32F103_CubeMX/blob/main/Docs/%E5%9F%BA%E4%BA%8ESTM32F103RCT6%E7%A7%BB%E6%A4%8DLiteOS-M-V5.0.2-Release.md基于STM32F103RCT6移植LiteOS-M-V5.0.2-Release下载源码kernel_liteos_m: OpenHarmon
    逮到一只程序猿 2025-02-27 08:56 202浏览
  • Matter 协议,原名 CHIP(Connected Home over IP),是由苹果、谷歌、亚马逊和三星等科技巨头联合ZigBee联盟(现连接标准联盟CSA)共同推出的一套基于IP协议的智能家居连接标准,旨在打破智能家居设备之间的 “语言障碍”,实现真正的互联互通。然而,目标与现实之间总有落差,前期阶段的Matter 协议由于设备支持类型有限、设备生态协同滞后以及设备通信协议割裂等原因,并未能彻底消除智能家居中的“设备孤岛”现象,但随着2025年的到来,这些现象都将得到完美的解决。近期,
    华普微HOPERF 2025-02-27 10:32 227浏览
  • RGB灯光无法同步?细致的动态光效设定反而成为产品客诉来源!随着科技的进步和消费者需求变化,电脑接口设备单一功能性已无法满足市场需求,因此在产品上增加「动态光效」的形式便应运而生,藉此吸引消费者目光。这种RGB灯光效果,不仅能增强电脑周边产品的视觉吸引力,还能为用户提供个性化的体验,展现独特自我风格。如今,笔记本电脑、键盘、鼠标、鼠标垫、耳机、显示器等多种电脑接口设备多数已配备动态光效。这些设备的灯光效果会随着音乐节奏、游戏情节或使用者的设置而变化。想象一个画面,当一名游戏玩家,按下电源开关,整
    百佳泰测试实验室 2025-02-27 14:15 140浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦