312|1

8

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

#AI挑战营终点站#手写数字识别模型部署 [复制链接]

一、镜像烧写与环境搭建

1、镜像烧写

https://wiki.luckfox.com/zh/Luckfox-Pico/Luckfox-Pico-prepare提供了ubuntu的镜像和buildroot镜像,这里我选择了buildroot镜像,参考SPI NAND Flash 镜像烧录 | LUCKFOX WIKI中的步骤即可完成烧写

 

2、开发环境搭建

参考SDK 环境部署(PC端) | LUCKFOX WIKI完成环境搭建

启动一个交互式的容器,使用名为 "luckfox",并将本地主机上的 SDK 目录映射到容器内的 /home 目录,最后以 Bash shell 运行(只需执行一次)

sudo docker run -it --name luckfox -v /home/jiang/luckfox-pico:/home luckfoxtech/luckfox_pico:1.0 /bin/bash

打开名为"luckfox"的docker环境

sudo docker start -ai luckfox

 在这个环境下可以编译镜像文件,不过耗时过长,我就跳过了,后面例程的编译要在这个环境下进行

二、例程编译

该例程来自

链接已隐藏,如需查看请登录或者注册
,感谢这位大佬的开源。

进入目录后运行如下命令即可完成编译

export LUCKFOX_SDK_PATH=/home
mkdir build
cd build
cmake ..
make && make install

该例程主函数while循环中的代码如下: 

// get vpss frame
s32Ret = RK_MPI_VPSS_GetChnFrame(0, 0, &stVpssFrame, -1);
if (s32Ret == RK_SUCCESS)
{
	void *data = RK_MPI_MB_Handle2VirAddr(stVpssFrame.stVFrame.pMbBlk);
	
	// 复制一个帧,然后使用模型推理
	cv::Mat frame(height, width, CV_8UC3, data);
	
	// 在图像中找到数字的轮廓
	cv::Rect digit_rect = find_digit_contour(frame);
	if (digit_rect.area() > 0)
	{
		cv::Mat digit_region = frame(digit_rect);
		cv::Mat preprocessed = preprocess_digit_region(digit_region);

		// 运行推理
		run_inference(&app_mnist_ctx, preprocessed);
		
		// 从predictions_queue中获取预测到的数字和其对应的概率
		if (!predictions_queue.empty())
		{
			Prediction prediction = predictions_queue.back();
			
			cv::rectangle(frame, digit_rect, cv::Scalar(0, 255, 0), 2);
			// 在图像上显示预测结果,显示字号为1,颜色为红色,粗细为2
			cv::putText(frame, std::to_string(prediction.digit), cv::Point(digit_rect.x, digit_rect.y - 10),
						cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255, 0, 0), 2);
			// 在图像上显示预测概率
			cv::putText(frame, std::to_string(prediction.probability), cv::Point(digit_rect.x+ 30, digit_rect.y - 10),
						cv::FONT_HERSHEY_SIMPLEX, 0.7, cv::Scalar(230, 0, 0), 2);

			// 打印预测到的数字和其对应的概率
			// printf("****** Predicted digit: %d, Probability: %.2f ******\n", prediction.digit, prediction.probability);
			// 从predictions_queue中删除最旧的元素
			predictions_queue.pop_back();
		}

	}

	sprintf(fps_text, "fps:%.2f", fps);
	cv::putText(frame, fps_text,
				cv::Point(40, 40),
				cv::FONT_HERSHEY_SIMPLEX, 1,
				cv::Scalar(0, 255, 0), 2);
	memcpy(data, frame.data, width * height * 3);
}

// send stream
// encode H264
RK_MPI_VENC_SendFrame(0, &stVpssFrame, -1);
// rtsp
s32Ret = RK_MPI_VENC_GetStream(0, &stFrame, -1);
if (s32Ret == RK_SUCCESS)
{
	if (g_rtsplive && g_rtsp_session)
	{
		// printf("len = %d PTS = %d \n",stFrame.pstPack->u32Len, stFrame.pstPack->u64PTS);
		void *pData = RK_MPI_MB_Handle2VirAddr(stFrame.pstPack->pMbBlk);
		rtsp_tx_video(g_rtsp_session, (uint8_t *)pData, stFrame.pstPack->u32Len,
						stFrame.pstPack->u64PTS);
		rtsp_do_event(g_rtsplive);
	}
	RK_U64 nowUs = TEST_COMM_GetNowUs();
	fps = (float)1000000 / (float)(nowUs - stVpssFrame.stVFrame.u64PTS);
}

// release frame
s32Ret = RK_MPI_VPSS_ReleaseChnFrame(0, 0, &stVpssFrame);
if (s32Ret != RK_SUCCESS)
{
	RK_LOGE("RK_MPI_VI_ReleaseChnFrame fail %x", s32Ret);
}
s32Ret = RK_MPI_VENC_ReleaseStream(0, &stFrame);
if (s32Ret != RK_SUCCESS)
{
	RK_LOGE("RK_MPI_VENC_ReleaseStream fail %x", s32Ret);
}

这里在拿到一帧图像后,应用形态学操作得到数字的位置,再用神经网络对该数字进行分类。

三、实验结果

将编译生成的`luckfox_rtsp_mnist_dir`文件夹上传到开发板上,进入该文件夹,运行以下命令

./luckfox_rtsp_mnist model/best.rknn

实验结果见附件result.mp4

可以看出模型能够准确识别0,2,3,4,5,识别效果不够理想。模型将7,8,9都识别成了3,可能是因为我量化只用了一张类别为3的图片的原因。

后续可以使用更多图片进行量化,希望能够有更好的结果。

result.mp4 (23.53 MB, 下载次数: 2)
result

 

最新回复

可以直接上传视频显示,效果可能会更好,附件只能下载看了   详情 回复 发表于 2024-6-1 15:23
点赞 关注

回复
举报

6060

帖子

6

TA的资源

版主

沙发
 

可以直接上传视频显示,效果可能会更好,附件只能下载看了

 
个人签名

在爱好的道路上不断前进,在生活的迷雾中播撒光引

 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表