Ask Your Question
0

blending 3-channel images with setTo and mask: error: checkScalar?

asked 2018-01-11 04:49:24 -0600

eudoxos gravatar image

Hi, I am trying to blend background image (3-channel) with another image, which was draw with some geometric primitives. I want to keep background intact where there is nothing in the foreground, and blend the rest.

This is the minimal example, which compiles but fails at runtime:

#include<opencv2/core.hpp>
int main(void){
    cv::Mat back(10,10,CV_8UC3);
    cv::Mat fore(10,10,CV_8UC3);
    // mask is nonzero where there is something in fore - summed over all 3 channels
    cv::Mat mask; 
    cv::transform(fore,mask,cv::Matx13f(1,1,1));
    float alpha=.3;
    // blend pixels which have non-zero mask, keep the rest of back intact
    back.setTo((1-alpha)*back+alpha*fore,mask>0);
}

This is the error I get:

OpenCV Error: Assertion failed (checkScalar(value, type(), _value.kind(), _InputArray::MAT )) in setTo, file /build/opencv-AuXD2R/opencv-3.3.1/modules/core/src/copy.cpp, line 514
terminate called after throwing an instance of 'cv::Exception'
  what():  /build/opencv-AuXD2R/opencv-3.3.1/modules/core/src/copy.cpp:514: error: (-215) checkScalar(value, type(), _value.kind(), _InputArray::MAT ) in function setTo

Can I have more explanation of that? Both matrices are 3-channel, mask is 1-channel of type CV_8UC1. Is there any more straightforward way how to do some kind of alpha-blending?

Thanks!

edit retag flag offensive close merge delete

Comments

LBerger gravatar imageLBerger ( 2018-01-11 04:57:20 -0600 )edit

@LBerger: that is not equivalent, unless I am missing something. addWeighted takes scalar weights, but I need weight to depend on whether that particular pixel is (0,0,0) in fore, then weights are (1,0), or different from zero, then weights are (1-alpha, alpha).

eudoxos gravatar imageeudoxos ( 2018-01-11 04:59:32 -0600 )edit

(1-alpha)*back+alpha*fore is not a Scalar, but an image.

berak gravatar imageberak ( 2018-01-11 05:07:12 -0600 )edit

The argument is an image (InputArray), see setTo docs: https://docs.opencv.org/3.4.0/d3/d63/...

eudoxos gravatar imageeudoxos ( 2018-01-11 05:49:04 -0600 )edit

@euxodos, yes, but a Scalar is required for setTo()

again, use addWeighted, and copyTo(), like said before.

berak gravatar imageberak ( 2018-01-11 05:59:53 -0600 )edit

You must give me an example (as I don't understand how you'd do it) or you did not read my reply above. I need weight to be different for every pixel, depending on the channels value combined. addWeighted does not do that.

eudoxos gravatar imageeudoxos ( 2018-01-11 07:08:48 -0600 )edit
LBerger gravatar imageLBerger ( 2018-01-11 08:35:50 -0600 )edit

@LBerger please read comments above, addWeighted is not useful, unless you explain better what you mean.

eudoxos gravatar imageeudoxos ( 2018-01-11 08:46:15 -0600 )edit

1 answer

Sort by » oldest newest most voted
0

answered 2018-01-11 08:49:37 -0600

berak gravatar image

updated 2018-01-11 08:52:37 -0600

try this:

Mat blend = (1-alpha)*back+alpha*fore; // same as addWeighted()
blend.copyTo(back, mask);
edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2018-01-11 04:49:24 -0600

Seen: 1,282 times

Last updated: Jan 11 '18