0

I have a 2d drawing of a element (isometric view) as follow:

enter image description here

I would like to extract only the thick, longest black line (element with arrows embedded in it not dimensions) from it.

How to achieve that ?

For now my code goes as follow

import cv2
import numpy as np

inputImage = cv2.imread("iso.jpg")
inputImageGray = cv2.cvtColor(inputImage, cv2.COLOR_BGR2GRAY)

edges = cv2.Canny(inputImageGray, 150, 200, apertureSize=3)
minLineLength = 30
maxLineGap = 5

lines = cv2.HoughLinesP(
    image=edges,
    rho=cv2.HOUGH_PROBABILISTIC,
    theta=np.pi / 180,
    threshold=30,
    minLineLength=minLineLength,
    maxLineGap=maxLineGap,
)

for x in range(0, len(lines)):
    for x1, y1, x2, y2 in lines[x]:
        pts = np.array([[x1, y1], [x2, y2]], np.int32)
        cv2.polylines(inputImage, [pts], True, (0, 255, 0))

cv2.imshow("Result", inputImage)
cv2.imshow("Edges", edges)
cv2.waitKey(0)

Which gives fallowing result - it detect all lines also thin ones, text brackets etc.

enter image description here

forDeFan
  • 31
  • 6
  • Did you already try to remove thin lines using [cv2.erode()](https://docs.opencv.org/4.7.0/db/df6/tutorial_erosion_dilatation.html)? – Markus May 10 '23 at 19:44
  • Please clarify "extract". Do you want that removed or do you want only those black lines. Get contours or canny edges and find only the horizontal ones. – fmw42 May 10 '23 at 19:52
  • I see 4 thick black lines - which one of them do you mean? – Mark Setchell May 10 '23 at 20:10
  • Morphology Erode the thin lines leaving the thick ones as suggested by Markus above. – fmw42 May 10 '23 at 23:56
  • @Markus - Will try with erosion - good idea. MarkSetchell - the longest one with arrows embedded – forDeFan May 11 '23 at 05:43
  • @fmw42 pardon the title, that was my doing. I believe I improved it, perhaps not sufficiently. I'd guess that a mask would be a good start. – Christoph Rackwitz May 11 '23 at 07:04
  • @ChristophRackwitz - can you elaborate a bit about mask approach in this particular example ? – forDeFan May 11 '23 at 07:26
  • "mask" isn't an approach, it's a specific form of result. it says "yes/no" for each pixel. it says nothing about how that was determined. – Christoph Rackwitz May 11 '23 at 07:33
  • Use morphology close rather than erode to remove the thin lines. Make the filter larger than the thin line thickness and smaller than the thick line thickness. – fmw42 May 11 '23 at 16:15
  • If you already `detect all lines`, why don't evaluate thickness of them? – fana May 12 '23 at 04:45

1 Answers1

1

Sorry, I posted this under a misunderstanding. This is not what the OP wanted. The post was not clear. He apparently wants the medium thick lines with the arrows (from his subsequent comment).

Nevertheless, perhaps this will help someone else on a different project. So here is one way to get the thickest black lines using Python/OpenCV.

  • Read the input
  • Convert to grayscale
  • Apply morphology close such that the kernel is thicker than the thin lines and thinner than the thick lines
  • Threshold
  • Save the results

Input:

enter image description here

import cv2
import numpy as np

# read the input
img = cv2.imread('schematic.jpg')

# convert to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# apply morphology close
kernel = cv2.getStructuringElement(cv2.MORPH_RECT , (3,3))
morph = cv2.morphologyEx(gray, cv2.MORPH_DILATE, kernel)

# threshold
result = cv2.threshold(gray, 32, 255, cv2.THRESH_BINARY)[1]

# save results
cv2.imwrite('schematic_thick_lines.jpg', result)

# show result
cv2.imshow('morph', morph)
cv2.imshow('result', result)
cv2.waitKey(0)

Results:

enter image description here

You can use contours to extract each one separately if that is needed.

fmw42
  • 46,825
  • 10
  • 62
  • 80