UPDATE has a new version of the code: https://github.com/chelyaev/opencv-yuv
I am sending a code that will read a single YUV 4: 2: 0 file. You can directly apply this to most YUV files (just keep reading from the same FILE object). The exception to this applies to working with YUV files with a header (usually they have the extension *.y4m ). If you want to deal with such files, you have two options:
- Write your own function to use the header data from the
FILE object before using the code below - Separate captions from * .y4m images (using
ffmpeg or a similar tool). This is the option that I prefer, since it is the simplest.
It will also not work for any other form of YUV format (non-planar miscellaneous thinning of color). As @Stephane noted, there are many such formats (and most of them do not have identification headers), so OpenCV probably does not support them out of the box.
But working with them is quite simple:
- Start with the image and its size (this is necessary when reading the YUV file).
- Read brightness and color in 3 separate images.
- High-quality color images 2 times to compensate for thinning color. Note that there are actually several ways to compensate for color thinning. Upsampling is simply the easiest
- Combine in YUV image. If you want to use RGB, you can use
cvCvtColor .
Finally, the code:
IplImage * cvLoadImageYUV(FILE *fin, int w, int h) { assert(fin); IplImage *py = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1); IplImage *pu = cvCreateImage(cvSize(w/2,h/2), IPL_DEPTH_8U, 1); IplImage *pv = cvCreateImage(cvSize(w/2,h/2), IPL_DEPTH_8U, 1); IplImage *pu_big = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1); IplImage *pv_big = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1); IplImage *image = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 3); IplImage *result = NULL; assert(py); assert(pu); assert(pv); assert(pu_big); assert(pv_big); assert(image); for (int i = 0; i < w*h; ++i) { int j = fgetc(fin); if (j < 0) goto cleanup; py->imageData[i] = (unsigned char) j; } for (int i = 0; i < w*h/4; ++i) { int j = fgetc(fin); if (j < 0) goto cleanup; pu->imageData[i] = (unsigned char) j; } for (int i = 0; i < w*h/4; ++i) { int j = fgetc(fin); if (j < 0) goto cleanup; pv->imageData[i] = (unsigned char) j; } cvResize(pu, pu_big, CV_INTER_NN); cvResize(pv, pv_big, CV_INTER_NN); cvMerge(py, pu_big, pv_big, NULL, image); result = image; cleanup: cvReleaseImage(&pu); cvReleaseImage(&pv); cvReleaseImage(&py); cvReleaseImage(&pu_big); cvReleaseImage(&pv_big); if (result == NULL) cvReleaseImage(&image); return result; }
misha
source share