OpenCV元素矩阵乘法

时间:2014-04-25 21:23:11

标签: c++ opencv

OpenCV docsA.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;

给出:

339
339
571
571

然后:

Mat prod = gaussian_weight_pyramids[i][l].mul(laplacian_pyramids[i][numLevels - 1 - l]);

给出错误。我尝试了Mat::multiply类似的效果。

2 个答案:

答案 0 :(得分:6)

我建议将单个频道转换为三个频道:

    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

但是如果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);

答案 1 :(得分:3)

这种错误可能有两个原因:不同的通道数或不同类型的数据(例如,如果第一个矩阵包含unsigned char,第二个矩阵包含unsigned short)。当然可能有两个原因。通常有3种类型的解决方案可以解决您遇到的问题:

1)编写您自己的'for'循环,它将执行您需要的操作。您不会受益于OpenCV函数中可能存在的优化,但其他解决方案将有自己的开销。您可以看到有关如何以有效方式访问像素的this tutorial

2)使用'merge'或'convertTo'之类的函数来创建相同类型和数量的通道的输入。有关代码示例,请参阅@marol发布的答案。在此解决方案中,主要开销是数据副本。这意味着额外的时间和空间。如果要对两个图像执行多个操作,这是合理的解决方案。但如果你只需要简单的乘法就不会有效。

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);

这样,您只使用OpenCV内置函数而无需复制开销。但我怀疑这将比解决方案1更快,因为解决方案-1在内存访问方面更有效。

在任何情况下,你都不会有一个很好的清洁操作,只需要一行:(