I have a binary image like shown below. How do I remove the single pixels on the borders of the blobs?
No need to give the full code if you don't want to, you can explain some algorithms or point me to the right direction.
I managed to solve this problem by using the hit and miss transform as suggested by midtiby. I used the following kernels to detect the top, right, bottom, and left single-pixels.
-1 -1 -1 1 -1 -1 1 1 1 -1 -1 1
-1 1 -1 1 1 -1 -1 1 -1 -1 1 1
1 1 1 1 -1 -1 -1 -1 -1 -1 -1 1
where -1
represent the background, 1
represent the foreground, and 0
for don't care (not being used in this case).
The result of the four hit and miss transform will be used as the mask to remove the single pixels. Below is the full code in Python/OpenCV:
import numpy as np
import cv2
def hitmiss(src, kernel):
im = src / 255
k1 = (kernel == 1).astype('uint8')
k2 = (kernel == -1).astype('uint8')
e1 = cv2.erode(im, k1, borderType=cv2.BORDER_CONSTANT)
e2 = cv2.erode(1-im, k2, borderType=cv2.BORDER_CONSTANT)
return e1 & e2
if __name__ == "__main__":
im = cv2.imread('blobs.png', cv2.CV_LOAD_IMAGE_GRAYSCALE)
_, im_binary = cv2.threshold(im, 50, 255, cv2.THRESH_BINARY)
kernel = np.array([[-1,-1, 1],
[-1, 1, 1],
[-1,-1, 1]])
im_mask = np.zeros(im_binary.shape, np.uint8)
im_mask |= hitmiss(im_binary, kernel)
im_mask |= hitmiss(im_binary, np.fliplr(kernel))
im_mask |= hitmiss(im_binary, kernel.T)
im_mask |= hitmiss(im_binary, np.flipud(kernel.T))
im_dst = im_binary & ((1 - im_mask) * 255)
cv2.imwrite('dst.png', im_dst)
Given this input image:
The script will produce this output:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With