I have this code now and it is great for detecting the red lines in my video, the issue is that I'm currently getting around 40 lines for one red line (see photo), and I'd like to reduce this to just 1 so that I can easily determine the intersections and subsequently the corner points of my red squares, anyone has an idea?:

Code:

import cv2
import numpy as np


def detect_grid(frame):
   
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

 
    lower_red = np.array([0, 100, 100])
    upper_red = np.array([10, 255, 255])

    mask1 = cv2.inRange(hsv, lower_red, upper_red)


    lower_red = np.array([140, 20, 20])
    upper_red = np.array([180, 255, 255])

  
    mask2 = cv2.inRange(hsv, lower_red, upper_red)

  
    red_mask = mask1 + mask2

 
    kernel = np.ones((5, 5), np.uint8)
    red_mask = cv2.morphologyEx(red_mask, cv2.MORPH_OPEN, kernel)
    red_mask = cv2.morphologyEx(red_mask, cv2.MORPH_CLOSE, kernel)

    lines = cv2.HoughLinesP(red_mask, 1, np.pi / 180, threshold=50, minLineLength=50, maxLineGap=5)

    if lines is not None:
        for line in lines:
            x1, y1, x2, y2 = line[0]
            cv2.line(frame, (x1, y1), (x2, y2), (0, 255, 0), 5)


cap = cv2.VideoCapture('redline_rectified.mp4')

while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        break

  
    detect_grid(frame)

  
    cv2.imshow('Grid Detection', frame)

   
    if cv2.waitKey(1) & 0xFF == ord(' '):
        break

cap.release()
cv2.destroyAllWindows()

What i get now:

what i get now

original:

original

1

There are 1 best solutions below

3
On

Normally, I solve line detection problems via on contour detection and analyzing contour basically manually. Since your inputs are clear I continued by modifying your code.

Here are the steps I applied for your case: if 2 lines are close to each other than ignore one of those. I got this output at the end which has clear lines.

enter image description here

Here is the code. Beginning part is same just modifiedthe end of function:

import cv2
import numpy as np


def detect_grid(frame):
   
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    lower_red = np.array([0, 100, 100])
    upper_red = np.array([10, 255, 255])

    mask1 = cv2.inRange(hsv, lower_red, upper_red)

    lower_red = np.array([140, 20, 20])
    upper_red = np.array([180, 255, 255])

    mask2 = cv2.inRange(hsv, lower_red, upper_red)

    red_mask = mask1 + mask2

    kernel = np.ones((5, 5), np.uint8)
    red_mask = cv2.morphologyEx(red_mask, cv2.MORPH_OPEN, kernel)
    red_mask = cv2.morphologyEx(red_mask, cv2.MORPH_CLOSE, kernel)

    lines = cv2.HoughLinesP(red_mask, 1, np.pi / 180, threshold=350, minLineLength=50, maxLineGap=50)

    if lines is not None:
        # Filter out lines that are too close
        filtered_lines = []
        for line in lines:
            x1, y1, x2, y2 = line[0]
            p1 = np.array([x1, y1])
            p2 = np.array([x2, y2])
            too_close = False

            for other_line in filtered_lines:
                x3, y3, x4, y4 = other_line
                p3 = np.array([x3, y3])
                p4 = np.array([x4, y4])

                # Calculate Euclidean distance
                distance = np.linalg.norm(np.cross(p2 - p1, p1 - p3)) / np.linalg.norm(p2 - p1)

                if distance < 10:
                    too_close = True
                    break

            if not too_close:
                filtered_lines.append(line[0])

        for line in filtered_lines:
            x1, y1, x2, y2 = line
            cv2.line(frame, (x1, y1), (x2, y2), (0, 255, 255), 3)

    cv2.imwrite("/home/ubuntu/a.jpg", frame)

img = cv2.imread("/home/ubuntu/lines.png")
detect_grid(img)