我正在尝试在opencv中执行RGB颜色混合操作.我的图像包含在MxNx3 Mat中.我想用3x3矩阵多次这个.在Matlab中,我执行以下操作:*将图像从MxNx3展平为MNx3*将MNx3矩阵乘以3x3颜色混合矩阵*重塑为MxNx3
在Opencv中我想做以下事情:
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);
}
Run Code Online (Sandbox Code Playgroud)
这会编译但会生成异常:
OpenCV错误:输入参数的大小不匹配(该操作既不是'rray op array'(其中数组具有相同的大小和相同的通道数),也不是'array op scalar',也不是'scalar op array')在arithm_op中,文件C:/ slave/WinI nstallerMegaPack/src/opencv/modules/core/src/arithm.cpp,第1253行终止在抛出'cv :: Exception'的实例后调用
what():C:/ slave/WinInstallerMegaPack/src/opencv/modules/core/src/arithm.cpp:1253:错误:( - 209)该操作既不是'数组操作数组'(其中数组具有相同的大小和相同的通道数),也不是'函数arithm_op中的数组操作标量','sca lar op array'此应用程序已请求Runtime以不寻常的方式终止它.有关更多信息,请联系应用程序的支持团队.
更新1:
这是似乎有用的代码:
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;
}
Run Code Online (Sandbox Code Playgroud)
但结果图像失真.如果我跳过两个矩阵的乘法并且只是分配
mixedImage = flatFloatImage
Run Code Online (Sandbox Code Playgroud)
生成的图像看起来很好(只是没有颜色混合).所以我一定做错了什么,但我已经接近了.
我在这里看到了几件事:
为了缩放系数,OpenCV支持乘以标量,所以不multiply(rgbMixMat, 1, rgbMixMat, 256);应该直接进行rgbMixMat = 256 * rgbMixMat;.
如果这是您的所有代码,则无法正确初始化或分配值imData,因此该行Mat temp = imData.reshape(0, 1);可能会崩溃.
假设这imData是一个MxNx3(3通道Mat),您想要将其重塑为MNx3(1通道).根据文档,当你写的时候你Mat temp = imData.reshape(0, 1);说你希望通道的数量保持不变,而行应该是1.相反,它应该是:
Mat myData = Mat::ones(100, 100, CV_32FC3); // 100x100x3 matrix
Mat myDataReshaped = myData.reshape(1, myData.rows*myData.cols); // 10000x3 matrix
为什么选择转置temp = temp.t();?
在您编写时multiply(temp, rgbMixMat, mixData);,这是每个元素的产品.你想要矩阵产品,所以你只需要做mixData = myDataReshaped * rgbMixMat;(然后重塑那个).
编辑:如果你不使用转置它会崩溃,因为你做的imData.reshape(1, 3);不是imData.reshape(1, imData.rows);
尝试
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);
}
Run Code Online (Sandbox Code Playgroud)