Ê×Ïȸø³ö¹¤³Ì´ò°ü²Ö¿âµØÖ·£¬²Î¿¼¹ÙÍøyolov5-rtspʾÀý
git@github.com:LitchiCheng/RV1106_Linux.git
°üº¬ÄÚÈÝÈçÏ£º
1. v4l2·â×°µ÷Óÿ⹤³Ì
2. st7735 LCD²¥·Åbadapple¹¤³Ì
3. MNIST¶àÊý×Öʵʱʶ±ð¹¤³Ì
4. rkrtspÍÆÁ÷²âÊÔ¹¤³Ì
5. rkmpi csiÉãÏñÍ·²âÊÔ¹¤³Ì
6. yolov5µ¥Ö¡Ê¶±ð¹¤³Ì
ÈçÏÂÖ±½Ó½éÉÜMNIST¶àÊý×Öʵʱʶ±ð˼·£º
- ʹÓÃrkmpi¿â½øÐÐframeµÄץȡ
- ʹÓÃopencv-mobile¿â½øÐе¥Ö¡frame½øÐд¦Àí£¬Í¨¹ý¶þÖµ»¯¡¢·´Ïà¡¢¸¯Ê´¡¢ÅòÕ͵ȴ¦Àí£¬»ñµÃ¶à¸öÊý×ֵĿòѡλÖÃ
- ʹÓÃmnistѵÁ·ÇÒת»»ºóµÄrknnÄ£Ð͵¥¶À¶Ô¿òѡλÖõÄͼƬ½øÐÐÍÆÀí£¬µÃµ½¸Ã¿òѡλÖõĸÅÂÊÒÔ¼°Êý×Ö
- ÔÚframeÉÏͨ¹ýopencv-mobile½øÐл¿òÒÔ¼°±ê¼ÇÊý×Ö¼°¸ÅÂÊ
- ʹÓÃrkrtsp½øÐÐÍÆÁ÷
ÈçÏÂΪ´úÂë¹Ø¼ü²¿·Ö
Ò»¡¢»ñÈ¡frame¡¢´¦Àí¡¢ÍÆÀí¡¢±ê¼Ç
void *data = RK_MPI_MB_Handle2VirAddr(stVpssFrame.stVFrame.pMbBlk);
cv::Mat frame(height,width,CV_8UC3,data);
std::vector<cv::Rect> rects;
std::vector<detect_result> detect_results;
std::vector<cv::Mat> sub_pics;
rects = find_contour(frame, sub_pics);
for(int i = 0; i < rects.size(); i++){
if (rects[i].area() > 0){
inference_mnist_model(&rknn_app_ctx, sub_pics[i], detect_results);
if (!detect_results.empty()){
detect_result result = detect_results.back();
//ÂÌ¿ò£¬thicknessΪ1
cv::rectangle(frame, rects[i], cv::Scalar(0, 255, 0), 1);
//ºì×Ö£¬fontscaleΪ1£¬thicknessΪ1
cv::putText(frame, std::to_string(result.num), cv::Point(rects[i].x, rects[i].y + 10),
cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255, 0, 0), 1);
//À¶×Ö£¬fontscaleΪ1£¬thicknessΪ1
cv::putText(frame, std::to_string(result.probability), cv::Point(rects[i].x+ 30, rects[i].y + 10),
cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 0, 255), 1);
detect_results.pop_back();
}
}
}
¶þ¡¢µ¥Ö¡Í¼Ïñ´¦Àí
std::vector<cv::Rect> find_contour(const cv::Mat &image, std::vector<cv::Mat>& sub_pics) {
// Ô¤´¦ÀíͼÏñ
cv::Mat gray, edged, org_clone;
org_clone = image.clone();
// ת³É»Ò¶Èͼ
cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);
// ·´Ïà»Ò¶Èͼ
edged = ~gray;
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
// ±ßÔµÅòÕÍ
cv::dilate(edged, edged, kernel);
// ¸¯Ê´
cv::erode(edged, edged, kernel);
// ¶þÖµ»¯
cv::threshold(edged, edged, 127, 0, cv::THRESH_TOZERO);
// ÓÃÀ´´æÕÒµ½µÄÂÖÀª
std::vector<std::vector<cv::Point>> contours;
cv::findContours(edged, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
std::vector<cv::Rect> borders;
for(auto contour: contours){
cv::Rect bounding_box = cv::boundingRect(contour);
//µ±Ç°¾ØÐοò´óÓÚ30²ÅʹÓÃ
if (cv::contourArea(contour) > 30) {
//À©´ó¾ØÐοò£¬ÒÔ·ÀÊý×Ö±»½Ø¶Ï
bounding_box.x = std::max(0, bounding_box.x - 10);
bounding_box.y = std::max(0, bounding_box.y - 10);
bounding_box.width = std::min(image.cols - bounding_box.x, bounding_box.width + 20);
bounding_box.height = std::min(image.rows - bounding_box.y, bounding_box.height + 20);
borders.push_back(bounding_box);
cv::Mat postsub;
cv::Mat sub = edged(bounding_box);
// À©´óÊý×ÖÂÖÀª
cv::threshold(sub, sub, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
// // ½«Í¼Æ¬´óСµ÷ÕûΪ28
cv::resize(sub, postsub, cv::Size(28, 28), 0, 0, cv::INTER_AREA);
sub_pics.push_back(postsub);
}
}
return borders;
}
Èý¡¢ÍÆÀíº¯Êý
static float deqnt_affine_to_f32(int8_t qnt, int32_t zp, float scale) { return ((float)qnt - (float)zp) * scale; }
int inference_mnist_model(rknn_app_context_t* app_ctx, cv::Mat &frame, std::vector<detect_result>& results)
{
int ret;
int width = app_ctx->input_attrs[0].dims[2];
int stride = app_ctx->input_attrs[0].w_stride;
if (width == stride){
memcpy(app_ctx->input_mems[0]->virt_addr, frame.data, width * app_ctx->input_attrs[0].dims[1] * app_ctx->input_attrs[0].dims[3]);
}else{
int height = app_ctx->input_attrs[0].dims[1];
int channel = app_ctx->input_attrs[0].dims[3];
// copy from src to dst with stride
uint8_t *src_ptr = frame.data;
uint8_t *dst_ptr = (uint8_t *)app_ctx->input_mems[0]->virt_addr;
// width-channel elements
int src_wc_elems = width * channel;
int dst_wc_elems = stride * channel;
for (int h = 0; h < height; ++h){
memcpy(dst_ptr, src_ptr, src_wc_elems);
src_ptr += src_wc_elems;
dst_ptr += dst_wc_elems;
}
}
ret = rknn_run(app_ctx->rknn_ctx, nullptr);
if (ret < 0) {
printf("rknn_run fail! ret=%d\n", ret);
return -1;
}
#define DETECT_NUM_SIZE 10
// Post Process
uint8_t *output= (uint8_t*)malloc(sizeof(uint8_t) * DETECT_NUM_SIZE);
float *out_fp32 = (float*)malloc(sizeof(float) * DETECT_NUM_SIZE);
output = (uint8_t *)app_ctx->output_mems[0]->virt_addr;
int32_t zp = app_ctx->output_attrs[0].zp;
float scale = app_ctx->output_attrs[0].scale;
//·´Á¿»¯Îª¸¡µãÊý
for(int i = 0; i < DETECT_NUM_SIZE; i ++)
out_fp32[i] = deqnt_affine_to_f32(output[i],zp,scale);
//¹éÒ»»¯
float sum = 0;
for(int i = 0; i < DETECT_NUM_SIZE; i++)
sum += out_fp32[i] * out_fp32[i];
float norm = sqrt(sum);
for(int i = 0; i < DETECT_NUM_SIZE; i++)
out_fp32[i] /= norm;
//¶Ô¸ÅÂʽøÐÐÅÅÐò
float max_probability = -1.0;
int detect_num = -1;
for (int i = 0; i < DETECT_NUM_SIZE; ++i){
if (out_fp32[i] > max_probability){
max_probability = out_fp32[i];
detect_num = i;
}
}
//½á¹ûÈëÁÐ
results.push_back({detect_num, max_probability});
return 0;
}
¹¤³Ì±àÒë
cd MNIST
mkdri build
cd build
cmake ..
make
make install
scp -r ../rtsp_mnist_test root@xxx.xxx.xxx.xxx:~
Ä¿±ê°åÔËÐÐ
killall rkipc
cd rtsp_mnist_test
./rtsp_mnist model/mnist.rknn
VLCÀÁ÷ʵʱÏÔʾ
ÊÓƵµØÖ·