使用opencv处理android中的yuv420sp(NV21)图像

来源:互联网 发布:网络转载犯法吗 编辑:程序博客网 时间:2024/06/18 18:50

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;}

通常情况下android上javacv的兼容性不是特别好,所以通常采用opencv4j+ndk的方式


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;}

测试代码在处理864*480的图像时候,大概耗时500ms左右,效率不是特别高,暂时也没办法优化了

0 0
原创粉丝点击