完整代码就不贴上来了,讲一下实现思路:
ffmpeg解码出来的视频数据是yuv格式,假设为AV_PIX_FMT_YUV420P,后续的图像处理一般都是RGB格式的,而opencv中mat中需要存储成RGB格式,所以就需要从yuv到rgb或者bgr的转换。ffmpeg提供了相应的转换API函数:下面代码中m_width, m_height是原图像宽度与高度,AV_PIX_FMT_BGR24是要转换成的图像数据格式,通过avpicture_get_size()函数获取图像的数据占用空间大小,并使用av_malloc()分配一个m_bgrBuffer。将m_bgrBuffer挂到m_pFrameBGR结构体上,并设置好格式转换上下文sws_getContext()。这些都是在解码之前做好初始化工作,当然不要忘记释放内存,以免内存泄漏。
AVFrame* m_pFrameBGR; // 人脸识别用
uint8_t* m_bgrBuffer;
int m_bgrBufferSize;
SwsContext* m_ConvertCtxYUV2BGR;
m_pFrameBGR = NULL;
m_bgrBuffer = NULL;
m_ConvertCtxYUV2BGR = NULL;
m_pFrameBGR = av_frame_alloc();
m_bgrBufferSize = avpicture_get_size(AV_PIX_FMT_BGR24, m_width, m_height);
m_bgrBuffer = (uint8_t *)av_malloc(m_bgrBufferSize * sizeof(uint8_t));
avpicture_fill((AVPicture *)m_pFrameBGR, m_bgrBuffer, AV_PIX_FMT_BGR24, m_width, m_height);
m_ConvertCtxYUV2BGR = sws_getContext(m_width, m_height, AV_PIX_FMT_YUV420P, m_width, m_height, AV_PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);
解码后能得到yuv数据,然后使用ffmpeg的sws_scale()接口函数实现YUV格式的m_frameV到BGR格式的m_pFrameBGR的转换,数据保存在缓冲m_bgrBuffer中。我的工程是解码一个线程,人脸识别一个线程,所以m_bgrBuffer和m_bgrBufferSize需要回调出去,把数据交给人脸识别线程处理。
yuv数据转换到BGR格式数据:
sws_scale(m_ConvertCtxYUV2BGR, (uint8_t const * const *)m_frameV->data, m_frameV->linesize, 0, nHeight, m_pFrameBGR->data, m_pFrameBGR->linesize)
人脸识别线程得到bgr数据后,保存成mat格式,然后再转成灰度图:
Mat matGray, matBgr;
matBgr = cv::Mat::zeros(pstYDataParam->nHeight, pstYDataParam->nWidth, CV_8UC3);
memcpy(matBgr.data, pstYDataParam->bgrBuffer, pstYDataParam->bgrBufferSize);
cvtColor(matBgr, matGray, CV_BGR2GRAY);
灰度图保存图片:
// 保存图片
bool bFlag = imwrite("f:/1.bmp", matGray);
本文借鉴于:https://www.cnblogs.com/riddick/p/7719190.html