Thijser
Thijser

Reputation: 2633

How do I denoise straight lines

So I have images of a bunch of straight lines forming various shapes. However these straight line have a tendency to not be quite straight because the underlying source often has these lines go between pixels. In that case the underlying source produces pixels that are next to a line. In that case I would like for these extra pixels to be removed.

Here we have a source image:

noised

And here we have the same image denoised:

denoised.

I'm messing around with houghline transforms or de-noising algorithms but none of these are working well and it feels like there should be a good way of fixing this that uses the specific fact that these are lines rather than just normal pepper and salt noise.

I'm working with python right now but other language answers are acceptable.

Upvotes: 1

Views: 503

Answers (1)

Rotem
Rotem

Reputation: 32144

I thought of the same solution as commented by Cris:

  • Convert the image to binary image.
  • Apply morphological opening with np.ones((3, 15)) kernel - keeping only horizontal lines.
  • Apply morphological opening with np.ones((15, 3)) kernel - keeping only vertical lines.
  • Apply bitwise or between the above matrices to form a mask.
  • Apply mask on image - zero pixels in the mask gets zero values.

Here is a code sample:

import numpy as np
import cv2

img = cv2.imread('input.png')  # Read input image (BGR color format)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # Convert to grayscale
thresh = cv2.threshold(gray, 1, 255, cv2.THRESH_BINARY)[1]  # Convert to binary (only zeros and 255)

horz = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, np.ones((3, 15)))  # Keep only horizontal lines
vert = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, np.ones((15, 3)))  # Keep only vertical lines

mask = cv2.bitwise_or(horz, vert)  # Unite horizontal and vertical lines to form a mask

res = cv2.bitwise_and(img, img, mask=mask)  # Place zeros where mask is zero

# Show the result
cv2.imshow('mask', mask)
cv2.imshow('res', res)
cv2.waitKey()
cv2.destroyAllWindows()

Result:

mask:
enter image description here

res:
enter image description here


The result is not perfect, and not generalized.
You may get better result using for loops.
Example: Delete pixels that has many horizontal pixels below them, but only few next to them (repeat for left, right, and bottom).

Upvotes: 2

Related Questions