How to remove individual pixels at the borders of a drop?

I have a binary image as shown below. How to remove individual pixels at the borders of a drop?

enter image description here

No need to specify the full code, if you do not want it, you can explain some algorithms or point me in the right direction.

+6
source share
4 answers

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:

enter image description here

The script will produce this result:

enter image description here

+4
source

It looks like a task to skip and skip transformation .

+3
source

You must run erosion followed by dialation for the given image. Somehow the images on these links are oppsite, so don't confuse.
Erosion will reduce your white areas with an appropriate filter. It will remove the extra white pixels. You can then type to expand the white areas again, but without the extra white noisy pixels.

0
source

My method of removing such single pixels is to check 4-connected neighbors around each pixel. If a pixel has only one neighbor, it will be deleted. It will also delete one pixel on the edge of the β€œrotated L”, which is not expected to be deleted.

Here is my code for implementing my method above:

  int neighborNum; vector<cv::Point> willRemove; for (int i = 1; i < img.rows - 1; i++) { for (int j = 1; j < img.cols - 1; j++) { neighborNum = 0; if (img.at<uchar>(i, j) == 255) { // Check 4 connected neighbors if (img.at<uchar>(i, j - 1) == 255) { neighborNum++; } if (img.at<uchar>(i - 1, j) == 255) { neighborNum++; } if (img.at<uchar>(i, j + 1) == 255) { neighborNum++; } if (img.at<uchar>(i + 1, j) == 255) { neighborNum++; } // Found! if (neighborNum == 1) { willRemove.push_back(cv::Point(j, i)); } } } } // Try to remove pixels now for (int i = 0; i < willRemove.size(); i++) { cv::circle(img, willRemove[i], 0, cv::Scalar(0, 0, 0), 1, 8, 0); } 
0
source

All Articles