Voja
Voja

Reputation: 33

Mask color image in OpenCV C++

I have a black/white image and a colour image of same size. I want to combine them to get one image which is black where black/white image was black and same colour as coloured image where black/white image was white.

This is the code in C++:

#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main(){
    Mat img1 = imread("frame1.jpg"); //coloured image
    Mat img2 = imread("framePr.jpg", 0); //grayscale image

    imshow("Oreginal", img1);

    //preform AND
    Mat r;
    bitwise_and(img1, img2, r);

    imshow("Result", r);

    waitKey(0);
    return 0;

}

This is the error message:

OpenCV Error: Sizes of input arguments do not match (The operation is neither 'array op array' (where arrays have the same size and type), nor 'array op scalar', nor 'scalar op array') in binary_op, file /home/voja/src/opencv-2.4.10/modules/core/src/arithm.cpp, line 1021
terminate called after throwing an instance of 'cv::Exception'
  what():  /home/voja/src/opencv-2.4.10/modules/core/src/arithm.cpp:1021: error: (-209) The operation is neither 'array op array' (where arrays have the same size and type), nor 'array op scalar', nor 'scalar op array' in function binary_op

Aborted (core dumped)

Upvotes: 3

Views: 11417

Answers (2)

Antonio
Antonio

Reputation: 20256

Actually, it is fairly simple using img1 as mask in a copyTo:

//Create a black colored image, with same size and type of the input color image
cv::Mat r = zeros(img2.size(),img2.type()); 
img1.copyTo(r, img2); //Only copies pixels which are !=0 in the mask

As said by Kiran, you get an error because bitwise_and cannot operate on image of different type.


As noted by Kiran, the initial allocation and zeroing is not mandatory (however doing things preliminarily has no impact on the performance). From the documentation:

When the operation mask is specified, if the Mat::create call shown above reallocates the matrix, the newly allocated matrix is initialized with all zeros before copying the data.

So the whole operation can be done with a simple:

img1.copyTo(r, img2); //Only copies pixels which are !=0 in the mask

Upvotes: 2

kiranpradeep
kiranpradeep

Reputation: 11201

Firstly, a black/white(binary) image is different from a grayscale image. Both are Mat's of type CV_8U. But each pixel in grayscale image could take any value between 0 and 255. A binary image is expected to have only two values - a zero and a non zero number.

Secondly, bitwise_and cannot be applied to Mat's of different type. Grayscale image is a single channel image of type CV_8U( 8 bits per pixel ) and color image is a 3 channel image of type CV_BGRA ( 32 bits per pixel ).

It appears what you are trying to do could be done with a mask.

//threshold grayscale to binary image 
cv::threshold(img2 , img2 , 100, 255, cv::THRESH_BINARY);
//copy the color image with binary image as mask
img1.copyTo(r, img2);

Upvotes: 2

Related Questions