python - Removing isolated pixels using OpenCV -
i'm looking way remove isolated white pixels binary image using opencv. similar question (opencv rid of isolated pixels) has bunch of "answers" none seem work me. i've tried various combinations of opening , closing without success well.
the article here:
https://homepages.inf.ed.ac.uk/rbf/hipr2/hitmiss.htm
suggests can use hit-or-miss operation purpose:
1 used locate isolated points in binary image
and reason why 0s interpreted differently when used erosion/dilation directly (where 0s interpreted "don't care's" rather "not white" i'm after). however, using kernel renders original image.
my input image this:
you'll notice there's few white pixels near left-hand side of image i'd rid of.
here's code:
kernel = np.array([ [0, 0, 0], [0, 1, 0], [0, 0, 0]],np.uint8) hitormiss = cv2.morphologyex(input_image, cv2.morph_hitmiss, kernel) cv2.imshow('hitormiss', hitormiss)
what right way of removing isolated pixels these?
update: alexander's answer works charm , fastest solution. other answer provides solution too, use cv2.connectedcomponents function, more processor-intensive. here's function uses approach:
def remove_isolated_pixels(self, image): connectivity = 8 output = cv2.connectedcomponentswithstats(image, connectivity, cv2.cv_32s) num_stats = output[0] labels = output[1] stats = output[2] new_image = image.copy() label in range(num_stats): if stats[label,cv2.cc_stat_area] == 1: new_image[labels == label] = 0 return new_image
i believe opencv implementation broken. there related issue on opencv's github seems have merged pull request fix; think added opencv 3.3-rc referenced in pull request should fixed next time update opencv. i'm not sure if problem caused same thing or not.
the creative solution selected answer great, agree you: there must better way, despite broken implementation.
on opencv hit-or-miss tutorial state:
therefore, hit-or-miss operation comprises 3 steps:
- erode image a structuring element b1.
- erode complement of image a (a_c) structuring element b2.
- and results step 1 , step 2.
it goes on can accomplished single kernel in hit-or-miss transform, know, broken. let's steps instead.
import cv2 import numpy np # load image, ensure binary, remove bar on left input_image = cv2.imread('calc.png', 0) input_image = cv2.threshold(input_image, 254, 255, cv2.thresh_binary)[1] input_image_comp = cv2.bitwise_not(input_image) # use 255-img kernel1 = np.array([[0, 0, 0], [0, 1, 0], [0, 0, 0]], np.uint8) kernel2 = np.array([[1, 1, 1], [1, 0, 1], [1, 1, 1]], np.uint8) hitormiss1 = cv2.morphologyex(input_image, cv2.morph_erode, kernel1) hitormiss2 = cv2.morphologyex(input_image_comp, cv2.morph_erode, kernel2) hitormiss = cv2.bitwise_and(hitormiss1, hitormiss2) cv2.imshow('isolated.png', hitormiss) cv2.waitkey()
and remove, it's simple inverting hitormiss
, using mask
in cv2.bitwise_and()
input_image
.
hitormiss_comp = cv2.bitwise_not(hitormiss) # use 255-img del_isolated = cv2.bitwise_and(input_image, input_image, mask=hitormiss_comp) cv2.imshow('removed.png', del_isolated) cv2.waitkey()
Comments
Post a Comment