如何在 OpenCV 中的 CV_32FC1 和 CV_32FC3 图像之间进行像素倍增

How can I do pixel-wise multiple between CV_32FC1 and CV_32FC3 images in OpenCV

我正在使用 OpenCV 在 2 维图像 A(CV_32FC1) 和另一个 3 维图像 B(CV_32FC3) 之间进行像素乘法,即 imageA 像素乘法imageB 的每个 R\G\B 通道。这与沿第 3 个方向将 imageA 广播到 3 维,然后按像素与 imageB 广播相同。 现在,我通过:

vector<Mat> temp{imageA, imageA, imageA};   // imageA is CV_32FC1
merge(temp, sampA);                         // sameA is CV_32FC3 now, and each channel is same as imageA
Out = imageB.mul(sampA);                    // imageB is CV_32FC3, and do pixel-wise with sameA

我的问题是: 我可以有另一种更有效的方法来使用 OpenCV 实现这个目的吗?比如OpenCV中的一个函数。

我知道这与MXNet中的"Broadcast"相同,即沿第3个方向将2维图像广播到3维图像,结果的每个通道与输入2维相同图片。

提前致谢:-)

您的做法是 memory-ineffective,但理论上是正确的。调用 A.convertTo(A, CV_32FC3);不幸的是不会工作。最有效的方法是调用

cv::cvtColor(A, A, CV_GRAY2BGR);

这将复制或重新分配内存,但以一种比您当前应用的方式稍微更有效的方式(无需为 cv::Mats 创建额外的 headers 作为向量中的视图)。

OpenCV之所以不支持这种乘法是因为底层使用了Intel IPP库,IPP也不支持这种乘法。这正是 OpenCV 中用于每个元素矩阵乘法的内容: https://software.intel.com/en-us/ipp-dev-reference-mul。基本上 A 和 B 中的数据大小必须相同才能使这些函数中的任何一个起作用,此外,假设 A 和 B 是连续的,因此在您的情况下,重新分配或复制是必要的。

这是我对 CV_32FC3 和 CV_32FC1

进行乘法运算的代码
Mat matmul32F(Mat& bgr, Mat& mask)
{
    assert(bgr.type() == CV_32FC3 && mask.type() == CV_32FC1 && bgr.size() == mask.size());
    int H = bgr.rows;
    int W = bgr.cols;
    Mat dst(bgr.size(), bgr.type());

    if (bgr.isContinuous() && mask.isContinuous())
    {
        W *= H;
        H = 1;
    }

    for( int i = 0; i < H; ++i)
    {
        float* pdst = ((float*)dst.data)+i*W*3;
        float* pbgr = ((float*)bgr.data)+i*W*3;
        float* pmask = ((float*)mask.data) + i*W;
        for ( int j = 0; j < W; ++j)
        {
            (*pdst++) = (*pbgr++) *(*pmask);
            (*pdst++) = (*pbgr++) *(*pmask);
            (*pdst++) = (*pbgr++) *(*pmask);
            pmask+=1;
        }
    }
    return dst;
}

最有效的方法是自己迭代。

I test three method for :

A: use merge and mul

B: use cvtColor and mul

C: loop sing pointer and mutiply by hand.

至于时间成本,大多数情况下,A ≈ B ≈ 2 x C。典型的时间成本是:

Test A: 3.23E-03 s
Test B: 3.26E-03 s
Test C: 1.85E-03 s