NV21属于YUV420格式,是一种two-plane模式,即Y和UV分为两个Plane,但是UV(CbCr)为交错存储,每四个Y共用一组UV分量。 ,即Y'00、Y'01、Y'10、Y'11共用Cr00、Cb00。所以,他的容量应该是 y:u:v=4:1:1,即rgb容量的一半。
处理的大概流程是,分离y通道和uv通道,然后对uv通道缩放至正常大小后,分离uv通道,然后合并y,u,v三个通道,最后调用转换函数转换为rgb的图像
下面先给出javacv的测试代码
public static IplImage TransNV21TOIplImage(byte[] buff, int height, int width) {
//拆分数组,氛围y数组和uv数组
byte[] y = new byte[width * height];
byte[] uv = new byte[width * height / 2];
int index = 0;
System.arraycopy(buff, index, y, 0, width * height);
index += width * height;
System.arraycopy(buff, index, uv, 0, width * height / 2);
//定义一个y通道的图像和一个uv双通道的图像
IplImage yimg = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
IplImage uvimg = cvCreateImage(cvSize(width / 2, height / 2),
IPL_DEPTH_8U, 2);
yimg.imageData().put(y);
uvimg.imageData().put(uv);
//将uv通道的图像从1/4大小,缩放到正常大小
IplImage fulluvimg = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 2);
cvResize(uvimg, fulluvimg, CV_INTER_LINEAR);
cvReleaseImage(uvimg);
//分离uv通道,用于下一步合并y通道
IplImage uuimg = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
IplImage vvimg = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
cvSplit(fulluvimg, uuimg, vvimg, null, null);
//将y,u,v通道合并
IplImage yuvimg = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3);
cvMerge(yimg, uuimg, vvimg, null, yuvimg);
//将yuv格式转换为常用的rgb格式
IplImage rgbimg = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3);
cvCvtColor(yuvimg, rgbimg, CV_YCrCb2BGR);
return rgbimg;
}
IplImage* TransNV21TOBGR(char* buff, int height, int width) {
IplImage* yimg = cvCreateImageHeader(cvSize(width, height), IPL_DEPTH_8U, 1);
IplImage* uvimg = cvCreateImageHeader(cvSize(width / 2, height / 2),
IPL_DEPTH_8U, 2);
cvSetData(yimg, buff, width);
cvSetData(uvimg, buff + width * height, width);
IplImage* fulluvimg = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 2);
cvResize(uvimg, fulluvimg, CV_INTER_LINEAR);
cvReleaseImageHeader(&uvimg);
IplImage* uimg = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
IplImage* vimg = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
cvSplit(fulluvimg, uimg, vimg, NULL, NULL);
cvReleaseImage(&fulluvimg);
IplImage* ycrcbimage = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U,
3);
cvMerge(yimg, uimg, vimg, NULL, ycrcbimage);
cvReleaseImageHeader(&yimg);
cvReleaseImage(&uimg);
cvReleaseImage(&vimg);
IplImage* rgbimg = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3);
cvCvtColor(ycrcbimage, rgbimg, CV_YCrCb2BGR);
cvReleaseImage(&ycrcbimage);
return rgbimg;
}