I have a color image represented as an OpenCV Mat object (C++, image type CV_32FC3). I have a color correction matrix that I want to apply to each pixel of the RGB color image (or BGR using OpenCV convention, doesn't matter here). The color correction matrix is 3x3.
I could easily iterate over the pixels and create a vector v (3x1) representing RGB, and then compute M*v, but this would be too slow for my real-time video application.
The cv::cvtColor function is fast, but does not seem to allow for custom color transformations.
http://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html#cvtcolor
Similar to the following, but I am using OpenCV for C++, not Python.
Apply transformation matrix to pixels in OpenCV image
Basically the linked answer uses reshape
to convert your CV_32FC3
mat of size m x n
to a CV_32F
mat of size (mn) x 3
. After that, each row of the matrix contains exactly color channels of one pixel. You can then apply usual matrix multiplication to obtain a new mat and reshape
it back to the original shape with three channels.
Note: It may be worth noticing that the default color space of opencv is BGR, not RGB.
Here's the code that worked using cv::reshape. It was fast enough for my application:
#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);
A few things to note from the above: The color matrix in the comment block is the one I would ordinarily apply to an RGB image. In defining the float array m, I switched rows 1 and 3, and columns 1 and 3 for OpenCV's BGR ordering. The color matrix also must be transposed. Usually a color matrix is applied as M* v = v_new, where M is 3x3 and v is 3x1 but here we are doing vT *MT = v_newT to avoid having to transpose each 3-channel pixel.