Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filling an outlined circle

I have a collection of images with a circle drawn as a white outline. However, I want to fill the complete circle with white color. What is a fast way to do it? The following is the sample of the image:

Sample image

I have tried using nested loops to achieve this, but it takes a lot of time, and I have around 1.5 million images. The following is my code:

roundRobinIndex = 0
new_image = np.zeros((img_w, img_h))
for row in range(540):
    for column in range(800):
        if image[row,column] == 255:
            roundRobinIndex = (roundRobinIndex + 1) % 2
        if roundRobinIndex == 1:
            new_image[row, column] = 255
like image 712
Haroon S. Avatar asked Sep 30 '19 19:09

Haroon S.


People also ask

How do I make a half circle with an outline?

You can't apply an outline to part of a shape. So instead, create a half-circle with on outline but filled with your preferred color. I used Basic Shapes>Partial Circle here. Then on top of that, draw a half-circle arc using Basic Shapes>Block Arc.

How to draw a circle without fill in illustrator?

Go to the tool properties panel; click on the "Fill" icon and select the "No fill" option in the color palette. In the appeared "Create Ellipse" window press the "Cancel" button. Then hold the "Shift" key on the keyboard, do a left click on the canvas and draw a circle by moving the cursor. A circle without fill has been successfully created.

How do I apply an outline to a shape?

You can't apply an outline to part of a shape. So instead, create a half-circle with on outline but filled with your preferred color. I used Basic Shapes>Partial Circle here.

How do I create a circle in CSS?

There are many techniques used to create a circle. In our snippet, we’ll demonstrate some examples with the CSS border-radius property, as well as with the HTML <canvas> and SVG <circle> elements. The most common one is using the border-radius property.


2 Answers

Use cv2.fillPoly() to fill the circle contour

enter image description here

import cv2

image = cv2.imread('1.png', 0)
thresh = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cv2.fillPoly(image, cnts, [255,255,255])

cv2.imshow('image', image)
cv2.waitKey()

Note: The Otsu's threshold could be removed for slightly faster performance since the input image is already a binary image, you could directly find contours on the grayscale image

like image 101
nathancy Avatar answered Oct 09 '22 02:10

nathancy


I tried finding the bounding box of the white outline, and getting its centre, then floodfilling with white from there outwards.

#!/usr/bin/env python3

import cv2

def findfill(image):
    thresh = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
    cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    cv2.fillPoly(image, cnts, [255,255,255])

def me(image):
    x,y,w,h = cv2.boundingRect(image)
    cv2.floodFill(image,None,(int(x+w/2),int(y+h/2)),255)
    return image

image = cv2.imread('BLYmz.png', 0)

%timeit findfill(image)
%timeit me(image)

This seems to give the same results and run 2.5x faster:

findfill
810 µs ± 2.94 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

me
343 µs ± 1.06 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Of course, if you have 1.5 million to do, I would recommend some parallel processing too :-)

like image 39
Mark Setchell Avatar answered Oct 09 '22 02:10

Mark Setchell