Ask Your Question
0

How to Multiply cv::Mat with mask

asked 2015-07-14 02:57:07 -0500

Jony01 gravatar image

updated 2017-04-10 06:57:20 -0500

I'd like multiply two arrays(cv::Mat) with mask for speed up application.

In add and subtraction exists

mask - optional operation mask - 8-bit single channel array, that specifies elements of the output array to be changed

Provide OpenCV similar functionality for multiplication and divide?

I can solve it for full image and then copy data to output. But this is slow down.

cv::Mat input1(size, CV_8U|CV_16S|CV_32F);
cv::Mat input2(size, CV_8U|CV_16S|CV_32F); // or cv::Scalar
cv::Mat mask(size, CV_8U);
cv::Mat output(size, CV_8U|CV_16S|CV_32F); 

// per pixel multiplication input1 and input2 
cv::multiply(input1, input2, output);
//cv::multiply(input1, input2, output, mask);

way around for same result:

cv::Mat multiplyFull;
cv::multiply(input1, input2, multiplyFull);

// clear data in output
output.setTo(cv::Scalar::all(0), mask);

// set in output only multiplication given by mask
cv::add(output, multiplyFull, output, mask);
edit retag flag offensive close merge delete

Comments

I don't think it's possible without copying images.

LBerger gravatar imageLBerger ( 2015-07-14 03:15:09 -0500 )edit
1

IMHO would be nice if you ask your question like : here is my code to do ...... is there anyway to speed up my code. then maybe i learned something from your code

sturkmen gravatar imagesturkmen ( 2015-07-14 12:14:58 -0500 )edit

Hi did you solve this problem, I have the same question about multiplying mat using mask. Thanks!

BAHRAMUDIN ADIL gravatar imageBAHRAMUDIN ADIL ( 2019-02-12 03:21:02 -0500 )edit

you must write your own code

LBerger gravatar imageLBerger ( 2019-02-12 04:25:31 -0500 )edit

1 answer

Sort by ยป oldest newest most voted
3

answered 2019-02-12 05:18:42 -0500

LBerger gravatar image

updated 2019-02-12 05:24:41 -0500

You can try :

    multiply(x, y, z);
    bitwise_not(mask,maskneg);
    x.copyTo(z,maskneg);

or you can try this :

template<typename Type>
class ParallelMultiplyWithMask : public ParallelLoopBody
{
private:
    Mat &imgSrc1;
    Mat &imgSrc2;
    Mat &mask;
    Mat &dst;

public:
    ParallelMultiplyWithMask<Type>(Mat& img1,Mat &img2, Mat &d, Mat &m) :
        imgSrc1(img1),
        imgSrc2(img2),
        dst(d),
        mask(m)
    {}
    virtual void operator()(const Range& range) const CV_OVERRIDE
    {

        for (int y = range.start; y < range.end; y++)
        {
            uchar *m = mask.ptr<uchar>(y);
            Type *vDst = dst.ptr<Type>(y);
            Type *vSrc1 = imgSrc1.ptr<Type>(y);
            Type *vSrc2 = imgSrc2.ptr<Type>(y);
            for (int x = 0; x < imgSrc1.cols; x++, vDst++, vSrc1++, vSrc2++, m++)
            {
                if (*m)
                    *vDst = *vSrc1 * *vSrc2;
                else
                    *vDst = *vSrc1;
            }

        }
    }
};


void multiplywithMask(InputArray _src1, InputArray _src2,  OutputArray _dst, InputArray _mask)
{
    CV_Assert(_src1.sameSize(_src2) && _src1.type() == _src2.type());
    CV_Assert(_src1.sameSize(_mask) );
    Mat mask = _mask.getMat();
    CV_Assert(mask.type() == CV_8U);
    Mat dst(_src1.size(), _src1.type());
    Mat src1 = _src1.getMat(), src2 = _src2.getMat();
    if (_src1.type() == CV_8UC1)
    {
        ParallelMultiplyWithMask<uchar> product(src1,src2, dst, mask);
        parallel_for_(Range(0, src1.rows), product);
    }
    else if (_src1.type() == CV_32FC1)

    {
        ParallelMultiplyWithMask<float> product(src1, src2, dst, mask);
        parallel_for_(Range(0, src1.rows), product);
    }
    dst.copyTo(_dst);

}

multiplywithMask(x, y, z, mask);

edit flag offensive delete link more

Comments

Thanks for the reply, it works. Now I have I new question if you can help how to achieve? Thanks!

BAHRAMUDIN ADIL gravatar imageBAHRAMUDIN ADIL ( 2019-02-13 02:01:40 -0500 )edit
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2015-07-14 02:57:07 -0500

Seen: 3,542 times

Last updated: Feb 12