简体   繁体   中英

Filtering noise from very noisy binary thresholded image

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.

在此处输入图片说明

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

在此处输入图片说明

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!

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:

在此处输入图片说明

Detected contours to remove highlighted in green

在此处输入图片说明

Result

在此处输入图片说明

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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM