Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fill the outside of contours OpenCV

I am trying to color in black the outside region of a contours using openCV and python language. Here is my code :

contours, hierarchy = cv2.findContours(copy.deepcopy(img_copy),cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
areas = [cv2.contourArea(c) for c in contours]
max_index = np.argmax(areas)
cnt=contours[max_index]
# how to fill of black the outside of the contours cnt please? `
like image 860
Bill Avatar asked Jun 19 '16 23:06

Bill


People also ask

How do I fill a shape in OpenCV?

fillPoly() function of OpenCV is used to draw filled polygons like rectangle, triangle, pentagon over an image. This function takes inputs an image and endpoints of Polygon and color.

What does .read do OpenCV?

The imread function is a function of the OpenCV library. OpenCV is used for deep learning algorithms. It will read the image for further processing which will help in classification and analysis purposes. In order to use these images, the first step will be reading an image.

How do I combine contours in OpenCV?

go through the first contour as it is listed until you hit the closest point. Then switch to the other list, starting from the closest point you go clockwise through the other contour until it is used up. switch back to the first contour and append the rest of their points. force them into cv2 contour format.


1 Answers

Here's how you can fill an image with black color outside of a set of contours:

import cv2
import numpy
img = cv2.imread("zebra.jpg")
stencil = numpy.zeros(img.shape).astype(img.dtype)
contours = [numpy.array([[100, 180], [200, 280], [200, 180]]), numpy.array([[280, 70], [12, 20], [80, 150]])]
color = [255, 255, 255]
cv2.fillPoly(stencil, contours, color)
result = cv2.bitwise_and(img, stencil)
cv2.imwrite("result.jpg", result)

enter image description here enter image description here

UPD.: The code above exploits the fact that bitwise_and with 0-s produces 0-s, and won't work for fill colors other than black. To fill with an arbitrary color:

import cv2
import numpy

img = cv2.imread("zebra.jpg")

fill_color = [127, 256, 32] # any BGR color value to fill with
mask_value = 255            # 1 channel white (can be any non-zero uint8 value)

# contours to fill outside of
contours = [ numpy.array([ [100, 180], [200, 280], [200, 180] ]), 
             numpy.array([ [280, 70], [12, 20], [80, 150]])
           ]

# our stencil - some `mask_value` contours on black (zeros) background, 
# the image has same height and width as `img`, but only 1 color channel
stencil  = numpy.zeros(img.shape[:-1]).astype(numpy.uint8)
cv2.fillPoly(stencil, contours, mask_value)

sel      = stencil != mask_value # select everything that is not mask_value
img[sel] = fill_color            # and fill it with fill_color

cv2.imwrite("result.jpg", img)

enter image description here

Can fill with another image as well, for example, using img[sel] = ~img[sel] instead of img[sel] = fill_color would fill it with the same inverted image outside of the contours:

enter image description here

like image 174
Headcrab Avatar answered Sep 24 '22 20:09

Headcrab