3D matrix multiplication in opencv for RGB color mixing

I am trying to perform an RGB color mixing operation in opencv. I have an image contained in an MxNx3 Mat. I would like it to be somewhat with a 3x3 matrix. In Matlab, I do the following: * Smooth the image from MxNx3 to MNx3 * multiply the MNx3 matrix by the 3x3 color mixing matrix * reformat it back to MxNx3

In Opencv, I would like to do the following:

void RGBMixing::mixColors(Mat &imData, Mat &rgbMixData) { float rgbmix[] = {1.4237, -0.12364, -0.30003, -0.65221, 2.1936, -0.54141, -0.38854, -0.47458, 1.8631}; Mat rgbMixMat(3, 3, CV_32F, rgbmix); // Scale the coefficents multiply(rgbMixMat, 1, rgbMixMat, 256); Mat temp = imData.reshape(0, 1); temp = temp.t(); multiply(temp, rgbMixMat, rgbMixData); } 

This compiles, but throws an exception:

OpenCV error: the sizes of the input arguments do not match (the operation is neither an “rray op array” (where the arrays are the same size and the same number of channels), neither an “op scalar array” nor a “scalar op array ') in the arithm_op file, file C: / slave / WinI nstallerMegaPack / src / opencv / modules / core / src / arithm.cpp, line 1253 terminate call after calling the instance 'cv :: Exception'
which (): C: /slave/WinInstallerMegaPack/src/opencv/modules/core/src/arithm.cpp: 1253: error: (-209) The operation is not an “op array” (where the arrays are the same size and the same number channels), as well as 'array op scalar', or 'sca lar op array' in the arithm_op function

This application requested Runtime to complete it in an Unusual way. Contact customer support information.


Update 1:

This is the code that works:

 void RGBMixing::mixColors(Mat &imData, Mat&rgbMixData) { Size tempSize; uint32_t channels; float rgbmix[] = {1.4237, -0.12364, -0.30003, -0.65221, 2.1936, -0.54141, -0.38854, -0.47458, 1.8631}; Mat rgbMixMat(3, 3, CV_32F, rgbmix); Mat flatImage = imData.reshape(1, 3); tempSize = flatImage.size(); channels = flatImage.channels(); cout << "temp channels: " << channels << " Size: " << tempSize.width << " x " << tempSize.height << endl; Mat flatFloatImage; flatImage.convertTo(flatFloatImage, CV_32F); Mat mixedImage = flatFloatImage.t() * rgbMixMat; mixedImage = mixedImage.t(); rgbMixData = mixedImage.reshape(3, 1944); channels = rgbMixData.channels(); tempSize = rgbMixData.size(); cout << "temp channels: " << channels << " Size: " << tempSize.width << " x " << tempSize.height << endl; } 

But the resulting image is distorted. If I skip the multiplication of two matrices and just assign

 mixedImage = flatFloatImage 

The resulting image looks great (just not mixed with color). So I have to do something wrong, but I'm getting closer.

+4
source share
1 answer

I see a couple of things here:

  • To scale coefficients, OpenCV supports scalar multiplication, so instead of multiply(rgbMixMat, 1, rgbMixMat, 256); you must do directly rgbMixMat = 256 * rgbMixMat; .

  • If this is your code, you incorrectly initialize or assign the values ​​of imData , therefore the line Mat temp = imData.reshape(0, 1); will probably work.

  • Assuming imData is MxNx3 (3-channel Mat), you want to change it to MNx3 (1 channel). According to the documentation , when you write Mat temp = imData.reshape(0, 1); , you say that you want the number of channels to remain unchanged, and the line should be 1. Instead, it should be:

    Mat myData = Mat::ones(100, 100, CV_32FC3); // 100x100x3 matrix

    Mat myDataReshaped = myData.reshape(1, myData.rows*myData.cols); // 10000x3 matrix

  • Why do you take transposition temp = temp.t(); ?

  • When you write multiply(temp, rgbMixMat, mixData); , this is for every product item . You need a matrix product, so you just need to do mixData = myDataReshaped * rgbMixMat; (and then change it).

Edit: Failure if you are not using transpose because you are executing imData.reshape(1, 3); instead of imData.reshape(1, imData.rows);

Try

 void RGBMixing::mixColors(Mat &imData, Mat&rgbMixData) { Size tempSize; uint32_t channels; float rgbmix[] = {1.4237, -0.12364, -0.30003, -0.65221, 2.1936, -0.54141, -0.38854, -0.47458, 1.8631}; Mat rgbMixMat(3, 3, CV_32F, rgbmix); Mat flatImage = imData.reshape(1, imData.rows*imData.cols); Mat flatFloatImage; flatImage.convertTo(flatFloatImage, CV_32F); Mat mixedImage = flatFloatImage * rgbMixMat; rgbMixData = mixedImage.reshape(3, imData.rows); } 
+5
source

Source: https://habr.com/ru/post/1437230/


All Articles