Search code examples
pythonopencvimage-processingcomputer-vision

Laserline in freespace... and how I can detect the Line for further calculations?


I want to find a laser beam in different images.

Example image:

The Original one:

I found different approaches, but somehow it doesn't seem to work. I have now also used a threshold:

logicM = image > Threshold
plt.figure()
plt.imshow(logicM, cmap='gray')
plt.axis('image')
plt.title(laserColor + ' band intensity over ' + str(Threshold))

to identify the line. Now I want to mark the beam with a dashed line... and then plot the intensity over height (i.e., pixels)... how can this be done? I just can't figure it out.

I found this: Vertical curved line detection with OpenCV and that Draw a curve line going through the blobs in OpenCV C++

both doesn't work.

EDIT: The theoretical equations can be found here, but is there a easy opencv solution?: https://mv.in.tum.de/_media/members/steger/publications/1996/icpr-96-steger.pdf

EDIT2: I tried this, to get the values between the contour.

# Sort the contour points by their y-value
contour_points_by_row = {}
for contour in contours:
    print(contour)
    for point in contour:
        x, y = point[0]  # Zugriff auf die x- und y-Koordinaten
        if y in contour_points_by_row:
            contour_points_by_row[y].append(x)
        else:
            contour_points_by_row[y] = [x]

But the array is to short. Ony further ideas?


Solution

  • This does the trick to isolate the beam – there's probably some tool for getting a polyline approximation instead of an area contour too...

    import cv2
    from matplotlib import pyplot as plt
    
    img = cv2.imread("hQiak.png")
    
    # Mask in HSV space to keep only the vivid red color
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    lower_red = (0, 100, 20)
    upper_red = (10, 255, 255)
    mask = cv2.inRange(hsv, lower_red, upper_red)
    
    plt.imshow(mask, cmap="gray")
    
    # Detect contours from mask
    contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # Only keep the largest contour
    contours = [max(contours, key=cv2.contourArea)]
    
    cv2.drawContours(img, contours, -1, (0, 255, 0), 3)
    plt.figure(dpi=250)
    plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    plt.show()
    

    enter image description here