Sebastian Boldt
Sebastian Boldt

Reputation: 5321

How to black out everything outside a circle in Open CV

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?

Upvotes: 6

Views: 8559

Answers (4)

Sebastian Boldt
Sebastian Boldt

Reputation: 5321

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

Upvotes: 7

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;
}

Upvotes: 1

Edwin Cen
Edwin Cen

Reputation: 181

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

Upvotes: 0

jambono
jambono

Reputation: 408

you can make the background the color you want

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

then draw your circles

Upvotes: 3

Related Questions