上回对YUV文件进行了简单的介绍,下面主要是项目中的部分实验内容,首先生成YUV文件,没有文件我就用RGB转换,很点单opencv中有现成的,转化成420格式,但是转化后需要我们按照420规则保存到YUV文件中,具体代码是:
Mat src = imread("1.bmp");
Mat dst;
cvtColor(src, dst, CV_BGR2YUV_I420);
int length = src.cols*src.rows * 3 / 2;
uchar *pBufY = new uchar[length];
errno_t er;
FILE *fp;
er = fopen_s(&fp, "result_288.yuv", "w+");
if (!fp)
{
printf("pFileOut open error \n");
system("pause");
exit(-1);
}
memcpy(pBufY, dst.data, length*sizeof(uchar));
fwrite(pBufY, length*sizeof(uchar), 1, fp);
fclose(fp);
delete pBufY;
其中主要是fopen_s和fwrite的结合还有memcpy,会用这个就行了。
接着我进行了将8位的YUV转化生16YUV,在转化的同时我又进行了插值放大和增强。具体代码:
YUV sg;
errno_t err;
FILE *pFile;
err = fopen_s(&pFile, "result.yuv", "rb");//读取8位图像
if (pFile == 0) return;
Mat imgY;
int len = Width*Height;
imgY.create(Size(Width, Height), CV_16UC3);
uchar *Y = new uchar[len];
uchar *U = new uchar[len / 4];
uchar *V = new uchar[len / 4];
_fseeki64(pFile, 0, SEEK_SET);
fread(Y, len, 1, pFile);
fread(U, 1, len / 4, pFile);
fread(V, 1, len / 4, pFile);
//foo(Y, U, V, src);
Mat imageY = sg.uint8to16(Y, Width, Height);
Mat imageU = sg.uint8to16(U, Width / 2, Height / 2);
Mat imageV = sg.uint8to16(V, Width / 2, Height / 2);
float amount = 1;
int threshold = 0;
resize(imageY, imageY, Size(Width * 2, Height * 2), 0, 0, 2);
resize(imageU, imageU, Size(imageU.cols * 2, imageU.rows * 2), 0, 0, 2);
resize(imageV, imageV, Size(imageV.cols * 2, imageV.rows * 2), 0, 0, 2);
Mat imageBlur;
GaussianBlur(imageY, imageBlur, Size(0, 0), 3, 3, 4);
Mat lowcontrastmask = abs(imageY - imageBlur) < threshold;
Mat imgDst = imageY*(1 + amount) + imageBlur * (-amount);
imageY.copyTo(imgDst, lowcontrastmask);
////////////////////////////////////////////
// save
////////////////////////////////////////////
int len2 = imgDst.cols*imgDst.rows;
UINT16 *pBufy = new UINT16[len2 * 3 / 2];
memcpy(pBufy, imgDst.data, len2*sizeof(UINT16));
memcpy(pBufy + len2, imageU.data, len2*sizeof(UINT16) / 4);
memcpy(pBufy + len2 * 5 / 4, imageV.data, len2*sizeof(UINT16) / 4);
errno_t err1;
FILE *pFiles;
err1 = fopen_s(&pFiles, "result_576.yuv", "wb+");
if (!pFiles)
{
printf("FileOut open error \n");
system("pause");
exit(-1);
}
fwrite(pBufy, len2 * 3 * sizeof(UINT16) / 2, 1, pFiles);
fclose(pFiles);
delete pBufy;
这里只讨论转化过程和存储时注意的事项,忘记一个事情就是转化代码没放上去
Mat YUV::uint8to16(uchar *Y, int width, int height)
{
IplImage *img = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);
cvSetData(img, Y, width);
Mat image(img, 0);
image.convertTo(image, CV_16UC1, 257.0);
return image;
}
保存的时候注意memcpy是按照其实地址,按照字节为单位进行拷贝,其中长度为size,所以我在保存Y之后,需要偏移Y长度的地址,再保持U,最后V也是这个道理,由于16位是2个字节,不要忘记加上去。对于16位的yuv需要下载的YUV播放器的支持,还好同事帮忙给了一个,成功显示。
这周任务完成,估计下次就写反卷积算法了,少玩点,多学点。