The left is the original picture The right is after filling
For contour fill
, We first need to extract the contour in the image , I'm filling the inside with colors , I can't tell the difference myself , What is the difference between threshold segmentation and filling , If anyone knows , Share it , I will be very grateful ! Flooding algorithm is commonly used in contour filling !
The hole filling is under binarization , It's in the image “ White dot ” perhaps “ Black spot ”, This will affect our calculation of the area inside the contour !
Hole filling here, we aim at binary graph , It's not a grayscale image !
stay OpenCV Implementation in imfill Steps for
Please refer to the figure below when reading the following steps .
* Read picture .
* Binarization of input image .
* From pixel （0,0） fill color . Please note that , step 2 And steps 3 The difference between the outputs of is in the steps 3 The background of the image in is now white .
* Inverts the flood filled image （ That is, black becomes white , White turns black ）.
Use bitwise OR The threshold image is combined with the reverse flood fill image to obtain the final foreground mask filled with holes . step 4 The image in has some black areas within the boundary . Step by step 2, The holes in the image are filled . therefore , We combine the two to get a foreground mask .
The left is a binary inverse graph On the right is a binary graph
In short, it's two images with the same background , Reverse the color inside the outline , Merge the two images again , So that we can get a sense of what's in the profile “ Holes ” Fill in ;
The method is stupid , But it works !
Here's the point , On the code !!!!!
import cv2; import numpy as np; ''' Image description ： The image is a binary image ,255 White is the target ,0 Black background
To fill the black hole in the white target ''' imgPath = "H:/image.jpg" im_in = cv2.imread(imgPath, cv2.
IMREAD_GRAYSCALE); # copy im_in image im_floodfill = im_in.copy() # Mask be used for
floodFill, The official requirement is length and width +2 h, w = im_in.shape[:2] mask = np.zeros((h+2, w+2), np.uint8)
# floodFill In function seedPoint It has to be the background isbreak = False for i in range(im_floodfill.shape[
0]): for j in range(im_floodfill.shape): if(im_floodfill[i][j]==0): seedPoint
=(i,j) isbreak = True break if(isbreak): break # obtain im_floodfill cv2.floodFill(
im_floodfill, mask, seedPoint, 255); # obtain im_floodfill The inverse of im_floodfill_inv
im_floodfill_inv= cv2.bitwise_not(im_floodfill) #
hold im_in,im_floodfill_inv The two images are combined to get the foreground im_out = im_in | im_floodfill_inv cv2.
imshow('de',im_out) cv2.waitKey(0) cv2.destroyAllWindows()
Thank you for your comments !