Reputation: 2455
I am trying to copy part of an image to another one based on a mask. But the result becomes white in all the mask pixels.
Mat img = imread("a CV_8UC3 RGB image");
Mat mask = imread("the mask image which is a CV_8UC1");
Mat img_masked;
img.copyTo(img_masked, mask);
imshow("img_masked", img_masked);
cvWaitKey(1);
Here are examples of the images:
I want the original pixels of the img in the result but only in the location of mask pixels.
How can I do this properly?
Upvotes: 2
Views: 4798
Reputation: 5815
Two ways of doing this, depending on the data type
of your mats
.
The first one involves converting your images to grayscale. Since you didn't provide your inputs, I saved your screenshots as RGB
png
images and processed them this way:
//Read input image and mask (as RGB images):
cv::Mat imageInput = cv::imread( "C://opencvImages//road01.png", cv::IMREAD_COLOR );
cv::Mat imageMask = cv::imread( "C://opencvImages//roadMask.png", cv::IMREAD_COLOR );
//Convert images to grayscale:
cv::cvtColor( imageInput, imageInput, CV_RGB2GRAY );
cv::cvtColor( imageMask, imageMask, CV_RGB2GRAY );
//Prepare the masked image:
cv::Mat maskedImage;
//Use an AND operation to mask the original image:
cv::bitwise_and( imageInput, imageMask, maskedImage );
cv::imshow( "maskedImage [gray]", maskedImage );
As you see, I'm using a bitwise and
to mask everything with a value of 0
in your original mask.
Here's another approach, assuming your input is an BGR
(24-bit) image and your mask a binary (8-bit) image. You just basically split
the BGR
mat into three individual channels, mask them, and merge
them back into a BGR
matrix:
//BGR spliting:
std::vector<cv::Mat> bgrChannels(3);
cv::split( colorInput, bgrChannels );
//Mask every channel:
cv::bitwise_and( bgrChannels[0], imageMask, bgrChannels[0] ); //B
cv::bitwise_and( bgrChannels[1], imageMask, bgrChannels[1] ); //G
cv::bitwise_and( bgrChannels[2], imageMask, bgrChannels[2] ); //R
//Merge back the channels
cv::merge( bgrChannels, maskedImage );
cv::imshow( "maskedImage [color]", maskedImage );
Both solutions produce the same result:
Upvotes: 2