目前在用声网的 视频通话SDK 制作一款会议系统软件,将来可能要加入人脸的一些操作,因此就想到了opencv,并且声网SDK 也提供了原始的视频帧 回调函数,所以在此基础上集成opencv 是可以的。
主要的操作就是基于yuv420p 和 Mat类型的转换。
1,获取声网 原始视频帧 YUV420P数据.
virtual bool onCaptureVideoFrame(VideoFrame& videoFrame) override
2,YUV420P 转Mat
//1 yuv 转 BGR
cv::Mat yuvImg;
yuvImg.create(height*3/2, width, CV_8UC1);
cv::Mat rgbImg;
CopyYUVToImage(yuvImg.data,pY,pU,pV,width,height);
cv::cvtColor(yuvImg, rgbImg, CV_YUV2BGR_I420);
3,对Mat 进行人俩检测
//2 face detect
Mat image_gray;
cvtColor(rgbImg,image_gray,CV_BGR2GRAY);//转为灰度图
equalizeHist(image_gray,image_gray);//直方图均化 增强对比度
vector<cv::Rect> faceRect;
m_face_cascade.detectMultiScale(image_gray, faceRect, 1.1, 2, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));
for (size_t i = 0; i < faceRect.size(); i++)
{
rectangle(rgbImg, faceRect[i], Scalar(0, 0, 255));
}
4,Mat 转YUV420P
//3 BGR 转YUV
cv::Mat dstYuvImage;
cv::cvtColor(rgbImg, dstYuvImage, CV_BGR2YUV_I420);
CopyImageToYUV(pY,pU,pV,dstYuvImage.data,width,height);
5,关键函数,最关键的部分
void CopyYUVToImage(uchar * dst, uint8_t *pY, uint8_t *pU, uint8_t *pV, int width, int height)
{
uint32_t size = width * height;
memcpy(dst, pY, size);
memcpy(dst + size, pU, size / 4);
memcpy(dst + size + size / 4, pV, size / 4);
}
void CopyImageToYUV(uint8_t *pY, uint8_t *pU, uint8_t *pV, uchar * src ,int width, int height)
{
uint32_t size = width * height;
memcpy(pY, src, size);
memcpy(pU, src + size, size / 4);
memcpy(pV, src + size + size / 4, size / 4);
}
效果:
目前使用 debug 32位 测试,卡成了狗,稍后换成64位 并使用这个libfacedetection 库试一下效果