C++ OpenCV 逐元素矩阵乘法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23303305/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
OpenCV element-wise matrix multiplication
提问by Rose Perrone
OpenCV docssay A.mul(B)
is per-element multiplication. Yet the following code produces the following output, and then gives this error:
OpenCV文档说A.mul(B)
是每元素乘法。然而,以下代码产生以下输出,然后给出此错误:
OpenCV Error: Sizes of input arguments do not match
.
.
cout << laplacian_pyramids[i][numLevels - 1 - l].rows << endl;
cout << gaussian_weight_pyramids[i][l].rows << endl;
cout << laplacian_pyramids[i][numLevels - 1 - l].cols << endl;
cout << gaussian_weight_pyramids[i][l].cols << endl;
Gives:
给出:
339
339
571
571
Then:
然后:
Mat prod = gaussian_weight_pyramids[i][l].mul(laplacian_pyramids[i][numLevels - 1 - l]);
gives the error. I tried Mat::multiply
to a similar effect.
给出错误。我试图Mat::multiply
达到类似的效果。
采纳答案by marol
I would recommend converting single channel to three channels:
我建议将单通道转换为三通道:
Mat A = Mat::zeros(100, 200, CV_32FC1);
Mat B = Mat::zeros(100, 200, CV_32FC3);
// Mat C = A.mul(B); // Sizes of input arguments do not match
Mat Afc3;
Mat t[] = {A, A, A};
merge(t, 3, Afc3);
Mat C = Afc3.mul(B); // now Afc3 has 3 channels ans it is type of 32_FC3
// we can multiply each elem in B by the same coef from A
But if B it is a CV_8UC3 type, it does not work because opencv would not allow to multiply Mats which have different types of pixels. In that case, convert 8UC3 to 32FC3 remebering to scale each pixel by 1/255.0 beacuse each pixel in 32FC3 has a value between 0.0 and 1.0 (and of course each pixel in 8UC3 has a value between 0 and 255).
但是如果 B 是 CV_8UC3 类型,它就不起作用,因为 opencv 不允许乘以具有不同类型像素的 Mats。在这种情况下,将 8UC3 转换为 32FC3,记住将每个像素按 1/255.0 缩放,因为 32FC3 中的每个像素的值都在 0.0 和 1.0 之间(当然,8UC3 中的每个像素的值都在 0 到 255 之间)。
Mat A = Mat::zeros(100, 200, CV_32FC1);
Mat B = Mat::zeros(100, 200, CV_8UC3);
// Mat C = A.mul(B);
Mat Afc3, Bfc3;
Mat t[] = {A, A, A};
merge(t, 3, Afc3);
B.convertTo(Bfc3, CV_32FC3, 1/255.0);
Mat C = Afc3.mul(Bfc3);
回答by Michael Burdinov
There can be 2 reasons for such error: different number of channels or different type of data (for example if first matrix contain unsigned char and second matrix contain unsigned short). Of course there can be both reasons. In general there 3 types of solutions for problems like the one you encountered:
这种错误可能有两个原因:不同的通道数或不同类型的数据(例如,如果第一个矩阵包含 unsigned char 而第二个矩阵包含 unsigned short)。当然,可能有两个原因。一般来说,对于您遇到的问题,有 3 种解决方案:
1) Write your own 'for' loop that will do the operation you need. You won't benefit from optimizations that might be present in OpenCV functions but other solutions will have their own overheads. You can see this tutorialabout how to access pixels in efficient way.
1) 编写您自己的“for”循环来执行您需要的操作。您不会从 OpenCV 函数中可能存在的优化中受益,但其他解决方案会有自己的开销。您可以查看有关如何以有效方式访问像素的教程。
2) Use functions like 'merge' or 'convertTo' in order to create input of same type and number of channels. See answer posted by @marol for code example. In this solution the main overhead is copy of data. That means extra time and space. This is reasonable solution if you are going to perform multiple operations with both images. But if all you need is simple multiplication it won't be very effective.
2) 使用“merge”或“convertTo”等函数来创建相同类型和数量的通道的输入。有关代码示例,请参阅@marol 发布的答案。在此解决方案中,主要开销是数据复制。这意味着额外的时间和空间。如果您要对两个图像执行多个操作,这是一个合理的解决方案。但是如果你只需要简单的乘法,它就不会很有效。
3) Use workarounds. For example if your matrices have same type but differ in number of channels you can use reshapefunction:
3) 使用变通方法。例如,如果您的矩阵类型相同但通道数不同,您可以使用reshape函数:
// two matrices of same size but different number of channels
Mat laplac(100, 200, CV_32FC3);
Mat gauss(100, 200, CV_32FC1);
// turn them into single channel matrices. they have NxM rows and 1 or 3 columns.
// note that there no copy of data. any change in them will affect original matrices
Mat laplac2 = laplac.reshape( 1, laplac.rows*laplac.cols );
Mat gauss2 = gauss.reshape( 1, gauss.rows*gauss.cols ;
// perform multiplication
laplac2.col(0) = laplac2.col(0).mul(gauss2);
laplac2.col(1) = laplac2.col(1).mul(gauss2);
laplac2.col(2) = laplac2.col(2).mul(gauss2);
This way you are using only OpenCV build-in functions without copy overhead. But I doubt that this will be any faster than solution-1, because solution-1 is more efficient in terms of memory access.
这样您就可以只使用 OpenCV 内置函数而没有复制开销。但我怀疑这会比解决方案 1 更快,因为解决方案 1 在内存访问方面更有效。
In any case you won't have nice and clean operation that takes exactly one line :(
在任何情况下,您都不会有只需要一行的漂亮而干净的操作:(