How to black out everything outside a circle in Open CV
Asked Answered
G

4

6

I am currently trying to black out everything outside a circle. I am drawing the circle using the following lines of code:

cv::Point center(cvRound(circles[i][0]), cvRound(circles[i][1])); // CVRound converts floating numbers to integer
int radius = cvRound(circles[i][2]);                              // Radius is the third parameter [i][0] = x [i][1]= y [i][2] = radius
circle( image, center, 3, cv::Scalar(0,255,0), -1, 8, 0 );        // Drawing little circle to Image Center , next Line of Code draws the real circle
circle( image, center, radius, cv::Scalar(0,0,255), 3, 8, 0 );    // Circle(img, center, radius, color, thickness=1, lineType=8, shift=0)

What is the best approach of painting everything of the circly black, if I have a radius and the center of my circle? Does OpenCV provide an easy mechanism of doing this or should I iterate through all the pixels of my image and depending on the position color them black or not?

Gossipy answered 27/8, 2013 at 7:59 Comment(1)
Create a mask image (just draw the circle in white color on a black image with size same as that of your original image), then use bitwise_and() with your image and mask..Colombi
G
7

Thanks to Abid for the hint, i ended up with this approach. Everything works fine:

cv::Mat src = someMethodThatReturnsSrcImage(); // src Image 
cv::Mat maskedImage; // stores masked Image
std::vector<cv::Vec3f> circles = someMethodThatReturnsCircles(src);    
cv::Mat mask(srcImageForDimensions.size(),srcImageForDimensions.type());  // create an Mat that has same Dimensons as src
mask.setTo(cv::Scalar(0,0,0));                                            // creates black-Image
    // Add all found circles to mask
for( size_t i = 0; i < circles.size(); i++ )                          // iterate through all detected Circles
       {
         cv::Point center(cvRound(circles[i][0]), cvRound(circles[i][1])); // CVRound converts floating numbers to integer
         int radius = cvRound(circles[i][2]);                              // Radius is the third parameter [i][0] = x [i][1]= y [i][2] = radius
         cv::circle( mask, center, radius, cv::Scalar(255,255,255),-1, 8, 0 );    // Circle(img, center, radius, color, thickness=1, lineType=8, shift=0)
       }

src.copyTo(maskedImage,mask); // creates masked Image and copies it to maskedImage
Gossipy answered 27/8, 2013 at 9:31 Comment(0)
J
3

you can make the background the color you want

image=cv::Scalar(red_value, green_value, blue_value);

then draw your circles

Jointress answered 27/8, 2013 at 9:7 Comment(0)
P
1

I think that comment just under your question is the best solution. I made a modified version of your code for 5M image from fisheye camera. This image also needs to make black all points outside circle.

#include <Windows.h>
#include <Vfw.h>
#include <string>
#include <iostream>    
#include "opencv2\core\core.hpp"
#include "opencv2\imgproc\imgproc.hpp"
#include "opencv2\imgcodecs\imgcodecs.hpp"
#include "opencv2\highgui\highgui.hpp"    
using namespace std;
using namespace cv;    
int _tmain(int argc, _TCHAR* argv[])
{
    cv::Mat im_source_non_square = cv::imread("D:/FishLib/sample_02.bmp", CV_LOAD_IMAGE_COLOR);
    cv::namedWindow("Image",CV_WINDOW_FREERATIO);
    cv::imshow("Image", im_source_non_square);
    Mat im_source_square;
    int m_nCenterX=1280;
    int m_nCenterY=960;
    int m_nRadius=916;
    Mat im_mask=im_source_non_square.clone();
    im_mask.setTo(cv::Scalar(0,0,0));
    circle( im_mask, cv::Point(m_nCenterX,m_nCenterY), m_nRadius, cv::Scalar(255,255,255), -3, 8, 0 );
    cv::namedWindow("Mask image",CV_WINDOW_FREERATIO);
    cv::imshow("Mask image", im_mask);
    Mat im_source_circle;
    cv::bitwise_and(im_source_non_square,im_mask,im_source_circle);
    cv::namedWindow("Combined image",CV_WINDOW_FREERATIO);
    cv::imshow("Combined image", im_source_circle);
    cv::waitKey(0);
    return 0;
}
Pfeifer answered 25/4, 2018 at 15:4 Comment(0)
G
0

Just tried your code snippet and it works. Also if you want to change the background color instead of black, according to opencv docs here, before copyTo the destination mat will be initialized if needed, so just add code below:

cv::Mat maskedImage(srcImageForDimensions.size(), srcImageForDimensions.type()); // stores masked Image 
maskedImage.setTo(cv::Scalar(0,0,255)); // set background color to red
Gaffney answered 4/7, 2017 at 10:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.