ffmpeg对接darknet解码与检测方式优选


方法一: 从ffmpeg 生成bgr => cv::mat => image_t , 调用detect

1, 解码线程, 解码rtsp协议 264格式流 生成 w = 1280 h = 720 yuv420p 
2, 通过 sws_scale函数将 yuv420p 缩小成 w = 1280 h = 720 AV_PIX_FMT_BGR24 格式
3, 通过opencv的IplImage 将数据传到物体检测线程
     IplImage* pImg = cvCreateImage(cvSize(avctx->width, avctx->height), 8, 3);
     memcpy(pImg->imageData, rgbBuf, rgbBufSize);
4, 检测线程通过调用detect函数进行检测.
    std::vector detect(cv::Mat mat, float thresh = 0.2, bool use_mean = false)
   这个以mat为参数的detect 中有如下循环

                    for (int y = 0; y < h; ++y) {
                        for (int k = 0; k < c; ++k) {
                            for (int x = 0; x < w; ++x) {
                              im.data[k*w*h + y*w + x] = data[y*step + x*c + k] / 255.0f;
                            }
                        }
                    }

优点:
与以前人脸识别做法一样, 借用opencv, 开发方便
缺点:
相比方法二, 多一次非多层嵌套的大图copy. 但时间极少.


方法二: 从ffmpeg 生成bgr,  缩小后, 直接对接 image_t结构
1, 解码线程, 解码rtsp协议 264格式流 生成 w = 1280 h = 720 yuv420p 
2, 通过 sws_scale函数将 yuv420p 缩小成 w = 416 h = 416 AV_PIX_FMT_BGR24 格式

3, 组建image_t 结构, 并传入物体检测线程
                    int w = m_dst_w; //416 
                    int h = m_dst_h; //416 
                    int c = m_dst_c; //3
                    image_t im = my_make_image_custom(w, h, c);
                    unsigned char *data = rgbBuf; 
                    int step = m_dst_w * m_dst_c;

                    for (int y = 0; y < h; ++y) {
                        for (int k = 0; k < c; ++k) {
                            for (int x = 0; x < w; ++x) {
                              im.data[k*w*h + y*w + x] = data[y*step + x*c + k] / 255.0f;
                            }
                        }
                    }

4, 检测线程通过调用detect_resized函数进行检测.
   //auto box_list = pDetector->detect_resized(im, 1280, 720);
   auto box_list1 = pDetector->detect_resized(im, 416, 416);

优点:
省去转成cv::mat格式
缺点:
直接在解码线程缩小图片, 不能原图上传. 不符合需求


方法三: 从ffmpeg 生成bgr,  不缩小,  直接对接 image_t结构

1, 解码线程, 解码rtsp协议 264格式流 生成 w = 1280 h = 720 yuv420p 
2, 通过 sws_scale函数将 yuv420p 缩小成 w = 1280 h = 720 AV_PIX_FMT_BGR24 格式
3, 将rgb 数据copy到物体检测线程
4, 通过 sws_scale函数将 AV_PIX_FMT_BGR24 缩小成 w = 416 h = 416  AV_PIX_FMT_BGR24 格式
5, 组建image_t 结构, 并传入物体检测线程
                    int w = m_dst_w; //416 
                    int h = m_dst_h; //416 
                    int c = m_dst_c; //3
                    image_t im = my_make_image_custom(w, h, c);
                    unsigned char *data = rgbBuf; 
                    int step = m_dst_w * m_dst_c;

                    for (int y = 0; y < h; ++y) {
                        for (int k = 0; k < c; ++k) {
                            for (int x = 0; x < w; ++x) {
                              im.data[k*w*h + y*w + x] = data[y*step + x*c + k] / 255.0f;
                            }
                        }
                    }

6, 检测线程通过调用detect_resized函数进行检测.
   //auto box_list = pDetector->detect_resized(im, 1280, 720);
   auto box_list1 = pDetector->detect_resized(im, 416, 416);


总结:

虽然方法二与方法三都可以绕过 cv::mat 直接对接 image_t结构, 但都最终没绕过
                    for (int y = 0; y < h; ++y) {
                        for (int k = 0; k < c; ++k) {
                            for (int x = 0; x < w; ++x) {
                              im.data[k*w*h + y*w + x] = data[y*step + x*c + k] / 255.0f;
                            }
                        }
                    }

而非大循环的直接大图copy在当前的非嵌入式服务器上对性能影响极小. 
所以优化效果应该不明显.

而方法二在压缩线程里就做了缩小工作, 这样检测线程少一步工作. 但因为需求要保存检测原图, 不合要求.

你可能感兴趣的:(C++/C,深度学习,darknet)