0
votes

I'm using the openCV library (v3.4.2) and I was planning to convert RGB images to HSV and then filter them by colour via adjusting the Hue values to get black&white images (adjusting Saturation and Value/Brightness won't give me much better results), which already works in theory. However, some of my images have a lot of noise as you can see in the section of the image that is shown below (image 1).

Now I'd like to fill the dense black spots (remove the few white pixels inside them) and remove the sparse black pixels that are mostly surrounded by white pixels to obtain something like what is shown below in image 2.

I wouldn't say that it's gaussian noise since there are some rather "clean" spots all over the images. I already considered this post: Remove spurious small islands of noise in an image - Python OpenCV. I borrowed a few lines and adapted them to my purposes like this:

// cloV and opV are JSliders so that I can try different values
Mat se1 = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(cloV,cloV));
Mat se2 = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(opV,opV));

Mat mask = new Mat();

// bwMat is my Mat containing the black&white image
Imgproc.morphologyEx(bwMat, mask, Imgproc.MORPH_CLOSE, se1);
Imgproc.morphologyEx(mask, mask, Imgproc.MORPH_OPEN, se2);
bwMat.setTo(new Scalar(0), mask);

Attempting this approach and playing with the parameters I can't get any decent results though (I only manage to turn mostly everything inside the images black.) I assume that is because every neighbourhood pixel is taken into consideration and there is almost always at least a few pixels in close proximity. Now I thought that maybe there is a method that would affect pixels only if there is a certain percentage in its neighbourhood (e.g. a certain radius) but I don't really know what to look for. Is this the right approach? Or is it even realistic what I'm thinking about?

(1) Original black & white image:

[![originalopenc picture][2]][2]

(2) Black & white image I'd like to obtain:

[![edited picture][3]][3]

Note: I created the 2nd image using Paint. I only wanted to show that I'm trying to retain the denser black areas (I might even have removed some in this image by accident) so it doesn't have to look exactly like this, but I'm grateful for any hint that is bringing me any closer to this.

Edit: Someone told me to look up salt-and-pepper noise and by that I stumbled upon the medianblur method which is quite effective already:

Imgproc.medianBlur(Mat src, Mat dst, int ksize);

I leave this question open for a little while in case some other suggestions come up. Edit 2: Images removed

1
Just erode a couple of times then dilateDr.Haimovitz

1 Answers

1
votes

This is code what I tried.

I think find contours and remove small blobs after this code works will be generate the result what you expected.

Mat image = Imgcodecs.imread(templImage, Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE);
Imgproc.GaussianBlur(image, image, new Size(3,3), 0);

Mat thre = new Mat();
Imgproc.threshold(image, thre, 80, 255, Imgproc.THRESH_BINARY);

Mat eroded = new Mat();
Imgproc.erode(thre, eroded, Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2,2)));
Imgproc.dilate(eroded, eroded, Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2,2)));

enter image description here