How to Apply Mask to Image in OpenCV?
Asked Answered
B

6

26

I want to apply a binary mask to a color image. Please provide a basic code example with proper explanation of how the code works.

Also, is there some option to apply a mask permanently so all functions operate only within the mask?

Boffa answered 20/9, 2011 at 1:59 Comment(0)
S
11

You don't apply a binary mask to an image. You (optionally) use a binary mask in a processing function call to tell the function which pixels of the image you want to process. If I'm completely misinterpreting your question, you should add more detail to clarify.

Smashing answered 21/9, 2011 at 18:34 Comment(2)
some simple example would be helpfulRonn
@Vitovalov I think this applies for example to feature detection fonctions like SIFT or SURF.Mutton
G
69

While @perrejba s answer is correct, it uses the legacy C-style functions. As the question is tagged C++, you may want to use a method instead:

inputMat.copyTo(outputMat, maskMat);

All objects are of type cv::Mat.

Please be aware that the masking is binary. Any non-zero value in the mask is interpreted as 'do copy'. Even if the mask is a greyscale image.

Also be aware that the .copyTo() function does not clear the output before copying.

If you want to permanently alter the original Image, you have to do an additional copy/clone/assignment. The copyTo() function is not defined for overlapping input/output images. So you can't use the same image as both input and output.

Granada answered 10/8, 2013 at 11:15 Comment(1)
copyTo is undefined only for partially overlapping images so you should be able to use it to apply the mask without creating a new matrix. From docs.opencv.org/modules/core/doc/… : "While m.copyTo(m); works flawlessly, the function does not handle the case of a partial overlap between the source and the destination matrices."Pleomorphism
S
11

You don't apply a binary mask to an image. You (optionally) use a binary mask in a processing function call to tell the function which pixels of the image you want to process. If I'm completely misinterpreting your question, you should add more detail to clarify.

Smashing answered 21/9, 2011 at 18:34 Comment(2)
some simple example would be helpfulRonn
@Vitovalov I think this applies for example to feature detection fonctions like SIFT or SURF.Mutton
G
8

Well, this question appears on top of search results, so I believe we need code example here. Here's the Python code:

import cv2

def apply_mask(frame, mask):
    """Apply binary mask to frame, return in-place masked image."""
    return cv2.bitwise_and(frame, frame, mask=mask)

Mask and frame must be the same size, so pixels remain as-is where mask is 1 and are set to zero where mask pixel is 0.

And for C++ it's a little bit different:

cv::Mat inFrame; // Original (non-empty) image
cv::Mat mask; // Original (non-empty) mask

// ...

cv::Mat outFrame;  // Result output
inFrame.copyTo(outFrame, mask);
Germano answered 10/3, 2018 at 18:25 Comment(0)
P
5

You can use the mask to copy only the region of interest of an original image to a destination one:

cvCopy(origImage,destImage,mask);

where mask should be an 8-bit single channel array.

See more at the OpenCV docs

Pernas answered 27/3, 2013 at 19:3 Comment(2)
This uses the old legacy C API of OpenCV. You should use and recommend the C++ API instead.Breeze
You just need image.copyTo(dst, mask);Boutwell
H
1

Here is some code to apply binary mask on a video frame sequence acquired from a webcam. comment and uncomment the "bitwise_not(Mon_mask,Mon_mask);"line and see the effect.

bests, Ahmed.

#include "cv.h"      // include it to used Main OpenCV functions.
#include "highgui.h" //include it to use GUI functions.

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
    int c;

int radius=100;
      CvPoint2D32f center;
    //IplImage* color_img;
      Mat image, image0,image1; 
        IplImage *tmp;
    CvCapture* cv_cap = cvCaptureFromCAM(0);

    while(1)  {
        tmp = cvQueryFrame(cv_cap); // get frame
          // IplImage to Mat
            Mat imgMat(tmp);
            image =tmp; 



    center.x = tmp->width/2;
    center.y = tmp->height/2;

         Mat Mon_mask(image.size(), CV_8UC1, Scalar(0,0,0));


        circle(Mon_mask, center, radius, Scalar(255,255,255), -1, 8, 0 ); //-1 means filled

        bitwise_not(Mon_mask,Mon_mask);// commenté ou pas = RP ou DMLA 





        if(tmp != 0)

           imshow("Glaucom", image); // show frame

     c = cvWaitKey(10); // wait 10 ms or for key stroke
    if(c == 27)
        break; // if ESC, break and quit
    }
    /* clean up */
    cvReleaseCapture( &cv_cap );
    cvDestroyWindow("Glaucom");

}
Hypervitaminosis answered 6/11, 2013 at 11:25 Comment(1)
As the person asking the question wrote if you provide "code, please explain the code instead of just posting it."Madgemadhouse
S
1

Use copy with a mask.

Code sample:

Mat img1 = imread(path); // Load your image
Mat mask(img1 .size(),img1 .type()); // Create your mask
mask.setTo(0);
Point center(img1.cols/2, img1.rows / 2); 
const int radius = img1.cols / 5; // Circle radio
circle(mask, center, radius, 255, FILLED);// Draw a circle in the image center

Mat img2(img1 .size(),img1 .type()); // Outimage
img2.setTo(0); // Clear data
img1.copyTo(img2, mask); // Only values at mask > 0 will be copied.
Synecology answered 6/6, 2022 at 14:38 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.