Search code examples
pythonopencvimage-processingcomputer-vision

Measuring angle of a curve wire with OpenCV


I have a robotic device that bends wire, and I try to measure whether the bending was successful by looking at the desired and true angle measurements.

I'm very new to image processing so please excuse my crude terminology.

test image

What I have in mind is to detect the wire and draw a line for each segment of the wire, after that it becomes just a little trigonometry problem. But I can not find a way to draw and get coordinates of those lines.


Solution

  • I would try these steps:

    1. Skeletonize the image.
    2. Get the relevant points from the skeleton-path.
    3. Calculate the angle.

    EDIT:

    import cv2
    import numpy as np
    from skimage import morphology, graph
    from skan import Skeleton
    
    def angle(v1, v2):
        rad = np.arctan2(v2[0], v2[1]) - np.arctan2(v1[0], v1[1])
        return np.abs((np.rad2deg(rad)))
    
    # read an threshold image
    img = cv2.imread('img.png')
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    inverted = 255 - gray
    ret, thresh = cv2.threshold(inverted, 50, 255, cv2.THRESH_BINARY)
    
    # skeletonize image and split skeleton to paths, for now assume there is only one
    skeleton = morphology.skeletonize(thresh, method='lee')
    g = Skeleton(skeleton)
    path = np.array(g.path_coordinates(0).astype(int))
    
    # draw path for demonstration purpose
    for p in path:
        img[p[0], p[1]] = [0, 0, 255]
    
    # get reference points by percental position on path
    l = len(path)
    a1 = path[int(0.02 * l)]
    a2 = path[int(0.10 * l)]
    b1 = path[int(0.98 * l)]
    b2 = path[int(0.90 * l)]
    
    # results
    print(f"Degrees: {angle(a1 - a2, b1 - b2):0.2f}")
    cv2.line(img, (a1[1], a1[0]), (a2[1], a2[0]), [0, 255, 0], 2)
    cv2.line(img, (b1[1], b1[0]), (b2[1], b2[0]), [0, 255, 0], 2)
    cv2.imwrite("out.png", img)
    

    Output:

    Degrees: 32.32
    

    enter image description here