先说结论, 不同色彩空间的转换矩阵不能混用, 否则一定会出现负数或者超过1 的情况
测试代买
constant.h
const float rgb2yuv_2020[] = { 0.2627, 0.6780, 0.0593, -0.1396, -0.3604, 0.5000, 0.5000, -0.4598, -0.0402 }; const float rgb2yuv_2020_invert[] = { 1, 0, 1.4746, 1, -0.1646, -0.5714, 1, 1.8814, 0 }; // //"BT601 625 D65" //Input : // r = (0.64, 0.33) // g = (0.29, 0.60) // b = (0.15, 0.06) // w = (0.3127, 0.3290) // // Output : // RGB2YUV Matrix : //0.2220, 0.7067, 0.0713 //- 0.1195, -0.3805, 0.5000 //0.5000, -0.4542, -0.0458 // //YUV2RGB Matrix : //1, 0, 1.5560 //1, -0.1875, -0.4888 //1, 1.8573, 0 // //"BT601 525 D65" //Input : // r = (0.63, 0.34) // g = (0.31, 0.595) // b = (0.155, 0.070) // w = (0.3127, 0.3290) // // Output : // RGB2YUV Matrix : //0.2124, 0.7011, 0.0866 //- 0.1163, -0.3837, 0.5000 //0.5000, -0.4450, -0.0550 // //YUV2RGB Matrix : //1, 0, 1.5752 //1, -0.2256, -0.4772 //1, 1.8269, 0 const float rgb2yuv_709[] = { 0.2126, 0.7152, 0.0722, -0.1146, -0.3854, 0.5000, 0.5000, -0.4542, -0.0458 }; const float rgb2yuv_709_invert[] = { 1, 0, 1.5747, 1, -0.1873, -0.4682, 1, 1.8556, 0 }; const float rgb2yuv_ntsc[] = { 0.2989, 0.5866, 0.1145, -0.1688, -0.3312, 0.5000, 0.5000, -0.4184, -0.0816 }; const float rgb2yuv_ntsc_invert[] = { 1, 0, 1.4022, 1, -0.3456, -0.7145, 1, 1.7710, 0 }; inline void mul32f_3x3(const float* matrix, float* in, float* out) { out[0] = matrix[0] * in[0] + matrix[1] * in[1] + matrix[2] * in[2]; out[1] = matrix[3] * in[0] + matrix[4] * in[1] + matrix[5] * in[2]; out[2] = matrix[6] * in[0] + matrix[7] * in[1] + matrix[8] * in[2]; }
main.cpp
#include "constant.h" #include <stdio.h> int check_rgb_to_rgb( const float * rgb2yuv_coeffs, const float* yuv2rgb_coeffs, float* rgb) { float rgbout[3]; int res = 0; const float delta = 0.001f; mul32f_3x3(rgb2yuv_coeffs, rgb, rgbout); mul32f_3x3(yuv2rgb_coeffs, rgbout, rgb); if (rgb[0] < -delta || rgb[1] < -delta || rgb[2] < -delta) { res = -1; } if (rgb[0] > 1 + delta || rgb[1] > 1 + delta || rgb[2] > 1 + delta) { res = -2; } if(res!=0) printf("SRC :%.4f %.4f %.4f DST:%.4f %.4f %.4f ", rgb[0], rgb[1], rgb[2], rgbout[0], rgbout[1], rgbout[2]); return res; } const float* rgb2yuv_coeffs[] = { rgb2yuv_709, rgb2yuv_2020, rgb2yuv_ntsc }; const float* rgb2yuv_coeffs_invert[] = { rgb2yuv_709_invert, rgb2yuv_2020_invert, rgb2yuv_ntsc_invert }; bool check(int rgb2yuv_id, int rgb2yuv_id_invert) { for (int i = 0; i < 256; ++i) { for (int j = 0; j < 256; ++j) { for (int k = 0; k < 256; ++k) { float in[] = { i / 255.0f, j / 255.0f, k / 255.0f }; int is_bad_coeffs = check_rgb_to_rgb(rgb2yuv_coeffs[rgb2yuv_id], rgb2yuv_coeffs_invert[rgb2yuv_id_invert], in); if (is_bad_coeffs) { return false; } } } } return true; } int main() { int errflag = 0; float nb_colorspace = sizeof(rgb2yuv_coeffs) / sizeof(rgb2yuv_coeffs[0]); for (int ci = 0; ci != nb_colorspace; ++ci) { for (int co = 0; co != nb_colorspace; ++co) { bool res = check(ci, co); printf("Check res:%d rgb2yuv:%d yuv2rgb:%d ", res, ci, co); } } }