I was able to solve this problem 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 do not care (not used in this case).
The result of four error and miss transformations will be used as a mask to remove single pixels. The following is the complete 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 result:
