opencvimage-processingmatrix-multiplication

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


I am working on do a pixel-wise multiple between a 2-dimension imageA(CV_32FC1) with another 3-dimension imageB(CV_32FC3) with OpenCV, i.e. imageA pixel-wise multiply each R\G\B channel of imageB. This is same as broadcast imageA to 3-dimension along the 3-th direction, then pixel-wise with imageB. Now, I do it by:

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

My Question is: Can I have another more effective way to do this purpose with OpenCV? Such like a function in OpenCV.

I know this is same as "Broadcast" in MXNet, i.e. broadcast a 2-dimension image to 3-dimension image along the 3-th direction, and each channel of result is same the input 2-dimension image.

Thanks in advance :-)


Solution

  • Here is my code to do multiply for CV_32FC3 and 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;
    }
    

    Most efficient way to is iteration by yourself.

    I test three method for :

    A: use merge and mul

    B: use cvtColor and mul

    C: loop sing pointer and mutiply by hand.

    As for time costing, in most case, A ≈ B ≈ 2 x C . A typical time costing is:

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