一、镜像烧写与环境搭建
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的图片的原因。
后续可以使用更多图片进行量化,希望能够有更好的结果。
|