基于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相关的资讯.
评论
  • 一个真正的质量工程师(QE)必须将一件产品设计的“意图”与系统的可制造性、可服务性以及资源在现实中实现设计和产品的能力结合起来。所以,可以说,这确实是一种工程学科。我们常开玩笑说,质量工程师是工程领域里的「侦探」、「警察」或「律师」,守护神是"墨菲”,信奉的哲学就是「墨菲定律」。(注:墨菲定律是一种启发性原则,常被表述为:任何可能出错的事情最终都会出错。)做质量工程师的,有时会不受欢迎,也会被忽视,甚至可能遭遇主动或被动的阻碍,而一旦出了问题,责任往往就落在质量工程师的头上。虽然质量工程师并不负
    优思学院 2025-01-09 11:48 14浏览
  • 在智能网联汽车中,各种通信技术如2G/3G/4G/5G、GNSS(全球导航卫星系统)、V2X(车联网通信)等在行业内被广泛使用。这些技术让汽车能够实现紧急呼叫、在线娱乐、导航等多种功能。EMC测试就是为了确保在复杂电磁环境下,汽车的通信系统仍然可以正常工作,保护驾乘者的安全。参考《QCT-基于LTE-V2X直连通信的车载信息交互系统技术要求及试验方法-1》标准10.5电磁兼容试验方法,下面将会从整车功能层面为大家解读V2X整车电磁兼容试验的过程。测试过程揭秘1. 设备准备为了进行电磁兼容试验,技
    北汇信息 2025-01-09 11:24 7浏览
  • 本文介绍编译Android13 ROOT权限固件的方法,触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。关闭selinux修改此文件("+"号为修改内容)device/rockchip/common/BoardConfig.mkBOARD_BOOT_HEADER_VERSION ?= 2BOARD_MKBOOTIMG_ARGS :=BOARD_PREBUILT_DTB
    Industio_触觉智能 2025-01-08 00:06 100浏览
  • 光伏逆变器是一种高效的能量转换设备,它能够将光伏太阳能板(PV)产生的不稳定的直流电压转换成与市电频率同步的交流电。这种转换后的电能不仅可以回馈至商用输电网络,还能供独立电网系统使用。光伏逆变器在商业光伏储能电站和家庭独立储能系统等应用领域中得到了广泛的应用。光耦合器,以其高速信号传输、出色的共模抑制比以及单向信号传输和光电隔离的特性,在光伏逆变器中扮演着至关重要的角色。它确保了系统的安全隔离、干扰的有效隔离以及通信信号的精准传输。光耦合器的使用不仅提高了系统的稳定性和安全性,而且由于其低功耗的
    晶台光耦 2025-01-09 09:58 10浏览
  • 村田是目前全球量产硅电容的领先企业,其在2016年收购了法国IPDiA头部硅电容器公司,并于2023年6月宣布投资约100亿日元将硅电容产能提升两倍。以下内容主要来自村田官网信息整理,村田高密度硅电容器采用半导体MOS工艺开发,并使用3D结构来大幅增加电极表面,因此在给定的占位面积内增加了静电容量。村田的硅技术以嵌入非结晶基板的单片结构为基础(单层MIM和多层MIM—MIM是指金属 / 绝缘体/ 金属) 村田硅电容采用先进3D拓扑结构在100um内,使开发的有效静电容量面积相当于80个
    知白 2025-01-07 15:02 147浏览
  • By Toradex 秦海1). 简介嵌入式平台设备基于Yocto Linux 在开发后期量产前期,为了安全以及提高启动速度等考虑,希望将 ARM 处理器平台的 Debug Console 输出关闭,本文就基于 NXP i.MX8MP ARM 处理器平台来演示相关流程。 本文所示例的平台来自于 Toradex Verdin i.MX8MP 嵌入式平台。  2. 准备a). Verdin i.MX8MP ARM核心版配合Dahlia载板并
    hai.qin_651820742 2025-01-07 14:52 113浏览
  • 根据环洋市场咨询(Global Info Research)项目团队最新调研,预计2030年全球无人机锂电池产值达到2457百万美元,2024-2030年期间年复合增长率CAGR为9.6%。 无人机锂电池是无人机动力系统中存储并释放能量的部分。无人机使用的动力电池,大多数是锂聚合物电池,相较其他电池,锂聚合物电池具有较高的能量密度,较长寿命,同时也具有良好的放电特性和安全性。 全球无人机锂电池核心厂商有宁德新能源科技、欣旺达、鹏辉能源、深圳格瑞普和EaglePicher等,前五大厂商占有全球
    GIRtina 2025-01-07 11:02 128浏览
  • 在过去十年中,自动驾驶和高级驾驶辅助系统(AD/ADAS)软件与硬件的快速发展对多传感器数据采集的设计需求提出了更高的要求。然而,目前仍缺乏能够高质量集成多传感器数据采集的解决方案。康谋ADTF正是应运而生,它提供了一个广受认可和广泛引用的软件框架,包含模块化的标准化应用程序和工具,旨在为ADAS功能的开发提供一站式体验。一、ADTF的关键之处!无论是奥迪、大众、宝马还是梅赛德斯-奔驰:他们都依赖我们不断发展的ADTF来开发智能驾驶辅助解决方案,直至实现自动驾驶的目标。从新功能的最初构思到批量生
    康谋 2025-01-09 10:04 8浏览
  •  在全球能源结构加速向清洁、可再生方向转型的今天,风力发电作为一种绿色能源,已成为各国新能源发展的重要组成部分。然而,风力发电系统在复杂的环境中长时间运行,对系统的安全性、稳定性和抗干扰能力提出了极高要求。光耦(光电耦合器)作为一种电气隔离与信号传输器件,凭借其优秀的隔离保护性能和信号传输能力,已成为风力发电系统中不可或缺的关键组件。 风力发电系统对隔离与控制的需求风力发电系统中,包括发电机、变流器、变压器和控制系统等多个部分,通常工作在高压、大功率的环境中。光耦在这里扮演了
    晶台光耦 2025-01-08 16:03 80浏览
  • 「他明明跟我同梯进来,为什么就是升得比我快?」许多人都有这样的疑问:明明就战绩也不比隔壁同事差,升迁之路却比别人苦。其实,之间的差异就在于「领导力」。並非必须当管理者才需要「领导力」,而是散发领导力特质的人,才更容易被晓明。许多领导力和特质,都可以通过努力和学习获得,因此就算不是天生的领导者,也能成为一个具备领导魅力的人,进而被老板看见,向你伸出升迁的橘子枝。领导力是什么?领导力是一种能力或特质,甚至可以说是一种「影响力」。好的领导者通常具备影响和鼓励他人的能力,并导引他们朝着共同的目标和愿景前
    优思学院 2025-01-08 14:54 82浏览
  • 故障现象一辆2017款东风风神AX7车,搭载DFMA14T发动机,累计行驶里程约为13.7万km。该车冷起动后怠速运转正常,热机后怠速运转不稳,组合仪表上的发动机转速表指针上下轻微抖动。 故障诊断 用故障检测仪检测,发动机控制单元中无故障代码存储;读取发动机数据流,发现进气歧管绝对压力波动明显,有时能达到69 kPa,明显偏高,推断可能的原因有:进气系统漏气;进气歧管绝对压力传感器信号失真;发动机机械故障。首先从节气门处打烟雾,没有发现进气管周围有漏气的地方;接着拔下进气管上的两个真空
    虹科Pico汽车示波器 2025-01-08 16:51 92浏览
  • 1月7日-10日,2025年国际消费电子产品展览会(CES 2025)盛大举行,广和通发布Fibocom AI Stack,赋智千行百业端侧应用。Fibocom AI Stack提供集高性能模组、AI工具链、高性能推理引擎、海量模型、支持与服务一体化的端侧AI解决方案,帮助智能设备快速实现AI能力商用。为适应不同端侧场景的应用,AI Stack具备海量端侧AI模型及行业端侧模型,基于不同等级算力的芯片平台或模组,Fibocom AI Stack可将TensorFlow、PyTorch、ONNX、
    物吾悟小通 2025-01-08 18:17 10浏览
  • 根据环洋市场咨询(Global Info Research)项目团队最新调研,预计2030年全球中空长航时无人机产值达到9009百万美元,2024-2030年期间年复合增长率CAGR为8.0%。 环洋市场咨询机构出版了的【全球中空长航时无人机行业总体规模、主要厂商及IPO上市调研报告,2025-2031】研究全球中空长航时无人机总体规模,包括产量、产值、消费量、主要生产地区、主要生产商及市场份额,同时分析中空长航时无人机市场主要驱动因素、阻碍因素、市场机遇、挑战、新产品发布等。报告从中空长航时
    GIRtina 2025-01-09 10:35 6浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦