最近遇到一个问题,现在从摄像机取出的图片是yuv[4:2:2]格式的,我需要把它转化为opencv中的mat格式,发现用opencv的cvtColor()函数进行转化时cpu消耗很大,为了减小cpu占用,需要改用公式法来将yuv422格式转化为mat。
查阅很多资料,在yuv422转mat格式的时候,需要注意yuv422的两种打包格式:YUYV和UYVY。
我这里来源数据YUV打包格式是YUYV,但是我找的公式代码好像是UYVY的,于是乎查看存储图片整体是有的,但是颜色只有粉色和绿色,这个代码如下:
void yuv422_to_mat(const unsigned char* yuv422_data, int width, int height, cv::Mat& mat) {
mat.create(height, width, CV_8UC3);
int yuv_index = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x += 2) {
int u = yuv422_data[yuv_index++];
int y1 = yuv422_data[yuv_index++];
int v = yuv422_data[yuv_index++];
int y2 = yuv422_data[yuv_index++];
int r1 = y1 + 1.402 * (v - 128);
int g1 = y1 - 0.34414 * (u - 128) - 0.71414 * (v - 128);
int b1 = y1 + 1.772 * (u - 128);
int r2 = y2 + 1.402 * (v - 128);
int g2 = y2 - 0.34414 * (u - 128) - 0.71414 * (v - 128);
int b2 = y2 + 1.772 * (u - 128);
mat.at<cv::Vec3b>(y, x)[0] = cv::saturate_cast<unsigned char>(b1);
mat.at<cv::Vec3b>(y, x)[1] = cv::saturate_cast<unsigned char>(g1);
mat.at<cv::Vec3b>(y, x)[2] = cv::saturate_cast<unsigned char>(r1);
mat.at<cv::Vec3b>(y, x + 1)[0] = cv::saturate_cast<unsigned char>(b2);
mat.at<cv::Vec3b>(y, x + 1)[1] = cv::saturate_cast<unsigned char>(g2);
mat.at<cv::Vec3b>(y, x + 1)[2] = cv::saturate_cast<unsigned char>(r2);
}
}
}
发现这个图片不对劲后,我又继续开始找代码,以下代码可以正确的将yuv422数据[打包格式YUVY]转化为opencv的mat格式:
void yuyv422_to_mat(const unsigned char* yuyv_data, int width, int height, cv::Mat& mat) {
mat.create(height, width, CV_8UC3);
int yuyv_index = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x += 2) {
int y1 = yuyv_data[yuyv_index++];
int u = yuyv_data[yuyv_index++];
int y2 = yuyv_data[yuyv_index++];
int v = yuyv_data[yuyv_index++];
int r1 = y1 + 1.13983 * (v - 128);
int g1 = y1 - 0.39465 * (u - 128) - 0.58060 * (v - 128);
int b1 = y1 + 2.03211 * (u - 128);
int r2 = y2 + 1.13983 * (v - 128);
int g2 = y2 - 0.39465 * (u - 128) - 0.58060 * (v - 128);
int b2 = y2 + 2.03211 * (u - 128);
mat.at<cv::Vec3b>(y, x)[0] = cv::saturate_cast<unsigned char>(b1);
mat.at<cv::Vec3b>(y, x)[1] = cv::saturate_cast<unsigned char>(g1);
mat.at<cv::Vec3b>(y, x)[2] = cv::saturate_cast<unsigned char>(r1);
mat.at<cv::Vec3b>(y, x + 1)[0] = cv::saturate_cast<unsigned char>(b2);
mat.at<cv::Vec3b>(y, x + 1)[1] = cv::saturate_cast<unsigned char>(g2);
mat.at<cv::Vec3b>(y, x + 1)[2] = cv::saturate_cast<unsigned char>(r2);
}
}
}