使用 OpenCV 3.0 将颜色矩阵应用于 RGB 图像的最快方法?
Fastest way to apply color matrix to RGB image using OpenCV 3.0?
我有一张表示为 OpenCV Mat 对象的彩色图像(C++,图像类型 CV_32FC3)。我有一个颜色校正矩阵,我想将其应用于 RGB 彩色图像的每个像素(或使用 OpenCV 约定的 BGR,在这里无关紧要)。色彩校正矩阵为 3x3。
我可以轻松地遍历像素并创建表示 RGB 的向量 v (3x1),然后计算 M*v,但这对于我的实时视频应用程序来说太慢了。
cv::cvtColor 函数速度很快,但似乎不允许自定义颜色转换。
http://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html#cvtcolor
类似于以下内容,但我使用的是 OpenCV for C++,而不是 Python。
Apply transformation matrix to pixels in OpenCV image
基本上,链接的答案使用 reshape
将尺寸 m x n
的 CV_32FC3
垫子转换为尺寸 (mn) x 3
的 CV_32F
垫子。之后,矩阵的每一行恰好包含一个像素的颜色通道。然后,您可以应用通常的矩阵乘法来获得一个新的垫子,然后 reshape
将其恢复为具有三个通道的原始形状。
注意:可能值得注意的是opencv的默认颜色space是BGR,不是RGB。
这是使用 cv::reshape 的代码。它对我的应用来说足够快:
#define WIDTH 2048
#define HEIGHT 2048
...
Mat orig_img = Mat(HEIGHT, WIDTH, CV_32FC3);
//put some data in orig_img somehow ...
/*The color matrix
Red:RGB; Green:RGB; Blue:RGB
1.8786 -0.8786 0.0061
-0.2277 1.5779 -0.3313
0.0393 -0.6964 1.6321
*/
float m[3][3] = {{1.6321, -0.6964, 0.0393},
{-0.3313, 1.5779, -0.2277},
{0.0061, -0.8786, 1.8786 }};
Mat M = Mat(3, 3, CV_32FC1, m).t();
Mat orig_img_linear = orig_img.reshape(1, HEIGHT*WIDTH);
Mat color_matrixed_linear = orig_img_linear*M;
Mat final_color_matrixed = color_matrixed_linear.reshape(3, HEIGHT);
上面有几点需要注意:评论区中的颜色矩阵是我通常应用于 RGB 图像的颜色矩阵。在定义浮点数组 m 时,我将第 1 行和第 3 行以及第 1 列和第 3 列切换为 OpenCV 的 BGR 排序。颜色矩阵也必须转置。通常颜色矩阵应用为 M* v = v_new,其中 M 是 3x3,v 是 3x1,但这里我们做的是 vT *MT = v_newT 以避免必须转置每个 3 通道像素。
我有一张表示为 OpenCV Mat 对象的彩色图像(C++,图像类型 CV_32FC3)。我有一个颜色校正矩阵,我想将其应用于 RGB 彩色图像的每个像素(或使用 OpenCV 约定的 BGR,在这里无关紧要)。色彩校正矩阵为 3x3。
我可以轻松地遍历像素并创建表示 RGB 的向量 v (3x1),然后计算 M*v,但这对于我的实时视频应用程序来说太慢了。
cv::cvtColor 函数速度很快,但似乎不允许自定义颜色转换。 http://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html#cvtcolor
类似于以下内容,但我使用的是 OpenCV for C++,而不是 Python。 Apply transformation matrix to pixels in OpenCV image
基本上,链接的答案使用 reshape
将尺寸 m x n
的 CV_32FC3
垫子转换为尺寸 (mn) x 3
的 CV_32F
垫子。之后,矩阵的每一行恰好包含一个像素的颜色通道。然后,您可以应用通常的矩阵乘法来获得一个新的垫子,然后 reshape
将其恢复为具有三个通道的原始形状。
注意:可能值得注意的是opencv的默认颜色space是BGR,不是RGB。
这是使用 cv::reshape 的代码。它对我的应用来说足够快:
#define WIDTH 2048
#define HEIGHT 2048
...
Mat orig_img = Mat(HEIGHT, WIDTH, CV_32FC3);
//put some data in orig_img somehow ...
/*The color matrix
Red:RGB; Green:RGB; Blue:RGB
1.8786 -0.8786 0.0061
-0.2277 1.5779 -0.3313
0.0393 -0.6964 1.6321
*/
float m[3][3] = {{1.6321, -0.6964, 0.0393},
{-0.3313, 1.5779, -0.2277},
{0.0061, -0.8786, 1.8786 }};
Mat M = Mat(3, 3, CV_32FC1, m).t();
Mat orig_img_linear = orig_img.reshape(1, HEIGHT*WIDTH);
Mat color_matrixed_linear = orig_img_linear*M;
Mat final_color_matrixed = color_matrixed_linear.reshape(3, HEIGHT);
上面有几点需要注意:评论区中的颜色矩阵是我通常应用于 RGB 图像的颜色矩阵。在定义浮点数组 m 时,我将第 1 行和第 3 行以及第 1 列和第 3 列切换为 OpenCV 的 BGR 排序。颜色矩阵也必须转置。通常颜色矩阵应用为 M* v = v_new,其中 M 是 3x3,v 是 3x1,但这里我们做的是 vT *MT = v_newT 以避免必须转置每个 3 通道像素。