方法一: 从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
这个以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在当前的非嵌入式服务器上对性能影响极小.
所以优化效果应该不明显.
而方法二在压缩线程里就做了缩小工作, 这样检测线程少一步工作. 但因为需求要保存检测原图, 不合要求.