ffmpeg解码后的yuv420P数据保存为opencv中mat格式(灰度图),最后保存为.bmp文件

完整代码就不贴上来了,讲一下实现思路:

 

       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

 

 

 

你可能感兴趣的:(OpenCV,FFmpeg,视音频)