Convert raw YUV i420 to cv::Mat

  1. Take an image. For example Lenna
  2. Install OpenCV 2.3 and FFmpeg
  3. Read what are YUV planar format
  4. Get the Makefile and source code.
  5. make raw && make && ./raw2Mat
Makefile
IMG = Lenna.png
WIDTH = 512
HEIGHT = 512
 
OBJS += raw2mat.o
 
CFLAGS += -g -Wall
CFLAGS += -DWIDTH=$(WIDTH) -DHEIGHT=$(HEIGHT)
CFLAGS += `pkg-config --cflags opencv`
LDFLAGS += `pkg-config --libs opencv`
 
PRGLD = $(CXX)
 
%.o: %.c $(DEPS)
        $(CC) -c -o $@ $< $(CFLAGS)
 
%.o: %.cpp $(DEPS)
        $(CXX) -c -o $@ $< $(CFLAGS)
 
 
raw2Mat: $(OBJS)
        $(PRGLD) -o $@ $^ $(CFLAGS) $(LDFLAGS)
 
raw:
        @echo "more format: ffmpeg -pix_fmt list"
        ffmpeg -i $(IMG) -f rawvideo -pix_fmt yuv420p -y img.raw
raw2mat.cpp
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
 
#define YUV_SIZE(W, H) ((W * H * 3) / 2)
 
int main(void) {
  const int width = WIDTH;
  const int height = HEIGHT;
  const int stride = WIDTH;
  const int buff_size = YUV_SIZE(width, height);
  unsigned char* buff;
  buff = new unsigned char[buff_size];
  {
    int fd = open("img.raw", O_RDONLY);
    if (fd == -1) {
      perror(NULL);
      exit(1);
    }
    int err = read(fd, buff, sizeof(unsigned char) * buff_size);
    assert(err == buff_size * sizeof(unsigned char));
    close(fd);
  }
  cv::Mat Y, U, V;
  {
    unsigned char* v_ptr = buff + stride * height;
    unsigned char* u_ptr = v_ptr + ((stride>>1) * (height>>1));
    Y = cv::Mat(width, height, CV_8UC1, buff, stride);
    U = cv::Mat(width>>1, height>>1, CV_8UC1, u_ptr, stride>>1);
    V = cv::Mat(width>>1, height>>1, CV_8UC1, v_ptr, stride>>1);
  }
 
  cv::Mat U2, V2;
  cv::resize(U, U2, cv::Size(0, 0), 2, 2, cv::INTER_LINEAR);
  cv::resize(V, V2, cv::Size(0, 0), 2, 2, cv::INTER_LINEAR);
 
  cv::Mat plans[] =  {Y, U2, V2};
  cv::Mat YUV;
  cv::merge(plans, 3, YUV);
 
  cv::Mat RGB;
  cv::cvtColor(YUV, RGB, CV_YCrCb2BGR);
 
  cv::namedWindow("Y", CV_WINDOW_AUTOSIZE);
  cv::namedWindow("U", CV_WINDOW_AUTOSIZE);
  cv::namedWindow("V", CV_WINDOW_AUTOSIZE);
 
  cv::imshow("Y", Y);  cv::imshow("U", U);  cv::imshow("V", V);
 
  /* create a window */
  cv::namedWindow("image", CV_WINDOW_AUTOSIZE);
  /* display the image */
  cv::imshow("image", RGB);
  /* wait until user press a key */
  cv::waitKey(0);
  /* free memory */
  cv::destroyWindow("image");
  cv::destroyWindow("Y");
  cv::destroyWindow("U");
  cv::destroyWindow("V");
 
  delete[] buff;
  return 0;
}
Print/export