一、概述
这次的项目主要是对比赛提供的资源的一次简单实践,将摄像头所识别的人脸数目传送到微信小程序上,模型是提前训练好的,在比赛的板子上进行推理,然后将识别到的人数,以json的格式传送给腾讯云物联网平台,然后由该平台注册的设备和腾讯连连小程序绑定,用户可以通过小程序看到设备周围的人数(准确的说是摄像头拍到的),适用的场景可以是一些防盗报警设备,检测到人数立即上报,该方案最初的设想是根据超声波测活动物体范围以及使用摄像头校准,能得到更加精确的结果。
二、整体架构
三、硬件部分
- 核心板采用的RT1062处理器属于i.MX RT 系列 MCU,是由 NXP 推出的跨界处理器,跨界是指该系列MCU的定位既非传统的微控制器、也非传统的微处理器,i.MX RT 系列 MCU 则综合了两者的优势,既具备高频率(最高主频600M)、高处理性能,也具备中断响应迅速、实时性高的特点。
- 1M RAM 16M SDRAM 64MB qspi flash 128MB spi flash。
- 板载Type-C接口CMSIS DAP仿真器。
- 板载PCIE接口,可扩展4G类物联网模组。
- 板载物联网俱乐部WAN Interface接口,可支持NB-IoT、WiFi、4G cat1、LoRa等模组。
- 板载物联网俱乐部E53 Interface接口,可扩展全系E53传感器。
- 板载标准24P DVP摄像头接口,可支持最高500万像素摄像头。
- 板载RGB显示接口,可转换HDMI输出。
- 板载高性能音频解码芯片,可做语音识别测试。
- 预留SD卡、用户按键、SPI Flash。
四、软件部分
工具
- 开发编译: MCUXpresso IDE v11.4.1_6260
- 烧录: NXP-MCUBootUtility
- 串口调试: sscom5.13.1
- 云上实践: 腾讯云IoT Explorer物联网平台,腾讯连连小程序
官方提供的工具可以正常编译,编程也很方便,但是我烧录的时候会出现问题,于是用了某位群大佬开发的软件NXP-MCUBootUtility 对板子烧录。官方的例程都非常好用,腾讯的文档也十分清晰,很多事情多亏了举办方大佬们才缩短了赶作业时间。
代码
利用模型推理采集的数据,检测人脸数量
代码语言:javascript复制static void APP_RGB565(void)
{
uint32_t cameraReceivedFrameAddr;
uint32_t lcdFrameAddr;
od_model_output_t output;
s_newFrameShown = false;
model_init();
uint32_t bg_color = 0x00ff0000;
for (int i=0;i< APP_IMG_HEIGHT;i )
{
for (int j=0;j<APP_IMG_WIDTH;j )
{
s_disp_frameBuffer[0][i][j]= bg_color;
}
}
g_dc.ops->setFrameBuffer(&g_dc, 0, (void *)s_disp_frameBuffer[0]);
/* For the DBI interface display, application must wait for the first
* frame buffer sent to the panel.
*/
if ((g_dc.ops->getProperty(&g_dc) & kDC_FB_ReserveFrameBuffer) == 0)
{
while (s_newFrameShown == false)
{
//tos_task_delay(1);
}
}
s_newFrameShown = true;
g_dc.ops->enableLayer(&g_dc, 0);
s_newFrameShown = true;
CAMERA_RECEIVER_Start(&cameraReceiver);
s_lcdActiveFbIdx = 0;
TOS_CPU_CPSR_ALLOC();
int x1, y1, x2, y2;
float score;
float label;
while (1)
{
int status = -1;
while (kStatus_Success != status)
{
TOS_CPU_INT_DISABLE();
status = CAMERA_RECEIVER_GetFullBuffer(&cameraReceiver, &cameraReceivedFrameAddr);
TOS_CPU_INT_ENABLE();
tos_task_delay(1);
}
uint32_t start = tos_systick_get();
model_run(cameraReceivedFrameAddr,DEMO_CAMERA_WIDTH,DEMO_CAMERA_HEIGHT,&output);
uint32_t end = tos_systick_get();
for (int i=0;i<*(output.nums);i )
{
x1 = (int)(output.boxes[0] * DEMO_CAMERA_WIDTH 0.5);
y1 = (int)(output.boxes[1] * DEMO_CAMERA_HEIGHT 0.5);
x2 = (int)(output.boxes[2] * DEMO_CAMERA_WIDTH 0.5);
y2 = (int)(output.boxes[3] * DEMO_CAMERA_HEIGHT 0.5);
score = output.scores[i];
label = output.labels[i];
if(score > 0.6){
IMAGE_DrawRect((void*)cameraReceivedFrameAddr, x1, y1, x2 - x1, y2 - y1, 0x7e0, DEMO_CAMERA_WIDTH);
}
}
mqttclient_task_send_count(*(output.nums));
/* Wait for the previous frame buffer is shown. */
while (s_newFrameShown == false)
{
tos_task_delay(1);
}
lcdFrameAddr = (uint32_t)s_disp_frameBuffer[s_lcdActiveFbIdx^1];
APP_PXP_CONV_RGB565_To_XRGB8888(cameraReceivedFrameAddr,(uint32_t)lcdFrameAddr);
TOS_CPU_INT_DISABLE();
CAMERA_RECEIVER_SubmitEmptyBuffer(&cameraReceiver, (uint32_t)cameraReceivedFrameAddr);
TOS_CPU_INT_ENABLE();
s_newFrameShown = false;
g_dc.ops->setFrameBuffer(&g_dc, 0, (void *)lcdFrameAddr);
tos_task_delay(20);
}
}
mqtt
代码语言:javascript复制#define REPORT_DATA_TEMPLATE "{"method":"report","clientToken":"00000001","params":{"Count":%d}}"
char report_buf[200];
static uint32_t send_count =0;
static uint8_t mqtt_avilid = 0;
void mqttclient_task(void)
{
int error;
int lightness = 0;
mqtt_client_t *client = NULL;
mqtt_message_t msg;
k_event_flag_t match_flag;
char host_ip[20];
memset(&msg, 0, sizeof(msg));
#ifdef USE_ESP8266
esp8266_sal_init(esp8266_port);
esp8266_join_ap("你的热点", "你的密码");
#endif
#ifdef USE_EC600S
ec600s_sal_init(HAL_UART_PORT_0);
#endif
mqtt_log_init();
client = mqtt_lease();
tos_event_create(&report_result_event, (k_event_flag_t)0u);
/* Domain Format: <your product ID>.iotcloud.tencentdevices.com */
tos_sal_module_parse_domain("设备号.iotcloud.tencentdevices.com",host_ip,sizeof(host_ip));
/*
These infomation is generated by mqtt_config_gen.py tool in "TencentOS-tinytools" directory.
*/
mqtt_set_port(client, "1883");
mqtt_set_host(client, host_ip);
mqtt_set_client_id(client, "设备号");
mqtt_set_user_name(client, "用户名");
mqtt_set_password(client, "密钥");
mqtt_set_clean_session(client, 1);
error = mqtt_connect(client);
MQTT_LOG_D("rnmqtt connect error is %#0x", error);
error = mqtt_subscribe(client, "$thing/down/property/id和设备", QOS0, tos_topic_handler);
MQTT_LOG_D("rnmqtt subscribe error is %#0x", error);
mqtt_avilid = 1;
while (1) {
tos_event_pend(&report_result_event,
report_success|report_fail,
&match_flag,
TOS_TIME_FOREVER,
TOS_OPT_EVENT_PEND_ANY | TOS_OPT_EVENT_PEND_CLR);
if (match_flag == report_success) {
printf("rnreport to Tencent IoT Explorer successrn");
}else if (match_flag == report_fail){
printf("rnreport to Tencent IoT Explorer failrn");
}
memset(&msg, 0, sizeof(msg));
snprintf(report_buf, sizeof(report_buf), REPORT_DATA_TEMPLATE, send_count);
msg.qos = QOS0;
msg.payload = (void *) report_buf;
error = mqtt_publish(client, "$thing/up/property/id和设备", &msg);
MQTT_LOG_D("rnmqtt publish error is %#0x", error);
tos_task_delay(5000);
}
}
五、总结
很荣幸能够参与这个比赛,与众多在嵌入式领域有经验的大佬一起交流,作为一名嵌入式新人确实能学到一些东西,了解到腾讯在这个领域的落地实践(感谢汪工还有其他腾讯和NXP的大佬们),虽然因为学校和实习时间的冲突,原定的学习计划泡汤了,在ddl之前的几天时间才开始交作业(哭/(ㄒoㄒ)/~~),不过这次比赛让我对TencentOS产生了极大兴趣,并打算能在接下来的闲暇时间在TencentOS社区做出一些自己的贡献。比赛虽然结束了,但是希望未来依然能有机会和各位有经验的前辈一同交流学习。
对项目的未来展望,继续完成最初的设想方案,优化识别效果和速度,利用超声波技术识别图片和真人,报文部分实现安全功能。
最后比赛的大家身体健康,工作顺利!
署名130****2604