Ask Your Question

# How to Multiply cv::Mat with mask

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 close merge delete

## Comments

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

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

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

## 1 answer

Sort by » oldest newest most voted

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

more

## Comments

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

Official site

GitHub

Wiki

Documentation

## Stats

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

Seen: 6,221 times

Last updated: Feb 12 '19