Filtering noise from very noisy binary thresholded image

aapp :

I would like to be able to analyze the following image, get the lines and find the average width.(My copy is much larger ~5K by ~4K) Cannot move to the next step due to all the noise after thresholding.

enter image description here

Using my code I was able to get to this point...

enter image description here

My issue is that it has a lot of noise in-between lines, which looks like noise that got condensed.

Here is my code...

image = np.copy(origImg)
newImage = np.empty_like(image)

scale = 64

height = image.shape[0]
width = image.shape[1]

dH = int(height / scale)
dW = int(width / scale)

xi = int(dH)
yi = int(dW)

fragments = []
image = cv2.bilateralFilter(image,9,75,75)
image = cv2.medianBlur(image, 21)

for i in range(0,height,dH):
    for j in range(0,width,dW):
        fragment = image[i:i + int(dH), j:j + int(dW)]

        fragment = cv2.adaptiveThreshold(fragment, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 0)

        fragments.append(fragment)

analyzed = com.stackArrayToImage(fragments)

nlabels, labels, stats, centroids = cv2.connectedComponentsWithStats(analyzed, None, None, None, 8, cv2.CV_32S)
sizes = stats[1:, -1] 
img2 = np.zeros((labels.shape), np.uint8)

for i in range(0, nlabels - 1):
    if sizes[i] >= 100:  
        img2[labels == i + 1] = 255

analyzed = cv2.bitwise_not(img2)

analyzed = cv2.erode(analyzed, np.ones((5, 5)), iterations=2)
analyzed = cv2.dilate(analyzed, np.ones((5, 5), np.uint8))

dis.plotImages([origImg], "Origional")
dis.plotImages([analyzed], "Analyzed")
dis.displayStart() 

Is there anyway I can remove that noise?

Thank you very much!

nathancy :

You can remove some of the noise using contour area filtering with cv2.contourArea. The idea is to filter using some threshold area. If a contour passes this filter then we can remove the noise by filling in the contour with cv2.drawContours. Using your binary image as input:

enter image description here

Detected contours to remove highlighted in green

enter image description here

Result

enter image description here

Depending on how much noise you want to remove, you can adjust the threshold area value

Code

import numpy as np
import cv2

# Load image, grayscale, Otsu's threshold
image = cv2.imread("1.png")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Find contours and filter using contour area
cnts = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    if area < 50:
        cv2.drawContours(thresh, [c], -1, 0, -1)
        cv2.drawContours(image, [c], -1, (36,255,12), -1)

result = 255 - thresh
cv2.imshow("image", image) 
cv2.imshow("thresh", thresh) 
cv2.imshow("result", result) 
cv2.waitKey()

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=20487&siteId=1