OpenCV一系列色域转换函数的验证。
(cv::COLOR_RGB2YUV_YV12 / cv::COLOR_RGB2YUV_I420) + libyuv::I420ToRGB24
按照fourcc的定义,YV12属于Planar YUV Formats中的一种,yuv是分开存储的(看作三个独立的内存块),但是在内存上又是连续的,即YYYYYYYY…..VVVVVVV….UUUUUUUU…..
而I420也属于Planar YUV Formats的一种,但其排列为YYYYYYYY…..UUUUUUUU….VVVVVVVV…..
采用代码进行测试,发现cv上定义的YV12和I420好像是反过来了,因为:
- libyuv是由Google开发的,在其页面中也描述了它是使用FOURCC来对色域空间进行描述,所以认为I420ToRGB24中的I420种yuv的顺序确为YYYYYYYY…..VVVVVVV….UUUUUUUU…..
- 而事实上采用 cv::COLOR_RGB2YUV_YV12 + libyuv::I420ToRGB24 得到的图像是正确的BGR,使用 cv::imshow 可以正确显示此图像颜色
- 采用 cv::COLOR_RGB2YUV_I420 + libyuv::I420ToRGB24 得到的图像是RGB,使用imshow之后图像是BGR的颜色
#include <opencv2/opencv.hpp>
#include "libyuv.h"
int main() {
cv::Mat img = cv::imread("test.jpeg");
cv::Mat yuv_yv12_img;
cv::cvtColor(img, yuv_yv12_img, cv::COLOR_RGB2YUV_YV12);
// cv::cvtColor(img, yuv_yv12_img, cv::COLOR_RGB2YUV_I420);
int width = img.cols;
int height = img.rows;
// 获取Y、U和V的指针
const uint8_t* y_data = yuv_yv12_img.data;
const uint8_t* u_data = yuv_yv12_img.data + width * height;
const uint8_t* v_data = yuv_yv12_img.data + width * height + width * height / 4;
cv::Mat bgr_img(height, width, CV_8UC3);
uint8_t* bgr_data = bgr_img.data;
libyuv::I420ToRGB24(y_data, width,
u_data, width / 2,
v_data, width / 2,
bgr_data, width * 3,
width, height);
// libyuv::I420ToRGB24(y_data, width,
// v_data, width / 2,
// u_data, width / 2,
// bgr_data, width * 3,
// width, height);
cv::imshow("RGB Image", bgr_img);
// cv::imshow("RGB Image", img);
cv::waitKey(0);
return 0;
}