I'm using OpenCV's HoughLinesP
function to detect straight lines in an image. When the image contains thin lines, the detection works perfectly. However, when the image contains thick lines, the algorithm detects them as two parallel lines instead of a single line.
Here's my current code:
import cv2
import numpy as np
image_path = "thickLines.png"
image = cv2.imread(image_path)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# Thresholding to create a binary image
_, binary = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)
# Edge Detection
edges = cv2.Canny(binary, 50, 150, apertureSize=3)
# Hough Line Transform to Detect Walls
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 100, minLineLength=50, maxLineGap=5)
# Draw Detected Walls
if lines is not None:
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(image, (x1, y1), (x2, y2), (0, 255, 0), 2) # Draw thick lines in green
# Show Final Processed Image
cv2.imshow("Detected Image", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
I have tried adjusting the Canny edge thresholds and modifying minLineLength
and maxLineGap
, but the issue persists.
My goal is to detect thick lines as a single line instead of two parallel lines.
Questions:
Screenshots
Here are screenshots of the issue:
The green lines represents the detected lines from the image
Here are sample images of thick & thin lines
You're looking to skeletonize the image - reduce the thickness of all features to 1 pixel.
scikit-image.morphology
has a neat method, skeletonize
, just for this.
import cv2
import numpy as np
from skimage.morphology import skeletonize
image_path = "thickLines.png"
image = cv2.imread(image_path)
# binarize image
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)
# convert to skeleton, then to mat
skeleton = skeletonize(binary)
skeletonImg = (skeleton * 255).astype(np.uint8)
# Hough Line Transform to Detect Walls
lines = cv2.HoughLinesP(skeletonImg, 1, np.pi / 180, 80, minLineLength=50, maxLineGap=5)
# Draw Detected Walls
if lines is not None:
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(image, (x1, y1), (x2, y2), (0, 255, 0), 2) # Draw thick lines in green
# Show Final Processed Image
cv2.imshow("Detected Image", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
Result: