@@ -21,8 +21,21 @@ def calculate_fps(prev_frame_time, new_frame_time, frame, position=(7, 70), font
2121 cv2 .putText (frame , fps_text , position , font , font_scale , color , thickness , cv2 .LINE_AA )
2222 return prev_frame_time
2323
24+ # Function to calculate lines angles
25+ def calculate_angles (lines ):
26+ try :
27+ for line in lines :
28+ x1 , y1 , x2 , y2 = line [0 ]
29+ # Calculate the angle of the line
30+ angle = np .arctan2 (y2 - y1 , x2 - x1 ) * 180 / np .pi # Convert to degrees
31+ print (f"Line angle: { angle } degrees" )
32+ except TypeError :
33+ pass
34+
35+
36+
2437# Open the video file
25- video_path = Path (__file__ ).parent .parent / "media" / "video1.mp4" # Get path relative to script location
38+ video_path = Path (__file__ ).resolve (). parent .parent / "media" / "video1.mp4" # Get path relative to script location
2639cap = cv2 .VideoCapture (str (video_path ))
2740
2841# Check if the video opened successfully
@@ -38,12 +51,18 @@ def calculate_fps(prev_frame_time, new_frame_time, frame, position=(7, 70), font
3851# used to record the time when we processed last frame
3952prev_frame_time = 0
4053
41- # Pre-calculate zones to exclude from drawing lines
42- def calculate_nozone (shape , offset = 50 ):
43- y , x = shape [:2 ]
44- y_nozone = list (range (y - offset , y + 1 )) + list (range (0 , offset + 1 ))
45- x_nozone = list (range (x - offset , x + 1 )) + list (range (0 , offset + 1 ))
46- return y_nozone , x_nozone
54+ # Calculate zones for the current frame
55+ ret , orig_frame = cap .read ()
56+
57+ # Define the region of interest (ROI)
58+ image_height , image_width = orig_frame .shape [:2 ]
59+ roi_height = int (image_height * 0.5 ) # Crop the top 50% of the image
60+ roi_width = int (image_width * 0.8 ) # Crop the middle 80% of the image
61+ x_offset = int (image_width * 0.1 ) # Offset to focus on the center
62+ y_offset = int (image_height * 0.25 ) # Vertical offset
63+
64+ orig_frame = orig_frame [y_offset :y_offset + roi_height , x_offset :x_offset + roi_width ]
65+ yimg_nozone , ximg_nozone = calculate_nozone (orig_frame .shape )
4766
4867# Loop to read frames
4968while True :
@@ -52,12 +71,12 @@ def calculate_nozone(shape, offset=50):
5271 if not ret :
5372 break
5473
74+ # Crop the image
75+ orig_frame = orig_frame [y_offset :y_offset + roi_height , x_offset :x_offset + roi_width ]
76+
5577 # Start measuring time for each frame
5678 new_frame_time = time .time ()
5779
58- # Calculate zones for the current frame
59- yimg_nozone , ximg_nozone = calculate_nozone (orig_frame .shape )
60-
6180 # Blur and convert to grayscale
6281 blurred = cv2 .GaussianBlur (orig_frame , (9 , 9 ), 0 )
6382 gray = cv2 .cvtColor (blurred , cv2 .COLOR_BGR2GRAY )
@@ -85,6 +104,7 @@ def calculate_nozone(shape, offset=50):
85104
86105 # Find contours of the field markings
87106 contours , _ = cv2 .findContours (thresh , cv2 .RETR_TREE , cv2 .CHAIN_APPROX_SIMPLE )
107+ contours = sorted (contours , key = cv2 .contourArea , reverse = True )[:10 ] # Keep top 10 largest contours
88108
89109 # Draw only large contours
90110 dummy_mask = np .zeros_like (mask_green )
@@ -95,20 +115,27 @@ def calculate_nozone(shape, offset=50):
95115 #adap_thrs_morph = cv2.morphologyEx(dummy_mask, cv2.MORPH_CLOSE, kernel2, iterations=1)
96116
97117 # Detect lines using Hough transform
98- lines = cv2 .HoughLinesP (dummy_mask , rho = 2 , theta = np .pi / 180 , threshold = 250 ,
99- minLineLength = 25 , maxLineGap = 50 )
118+ lines = cv2 .HoughLinesP (dummy_mask , rho = 10 , theta = np .pi / 180 , threshold = 250 ,
119+ minLineLength = 10 , maxLineGap = 50 ) # minLineLength=25
120+
121+ filtered_lines = []
122+ if lines is not None :
123+ for line in lines :
124+ x1 , y1 , x2 , y2 = line [0 ]
125+ if (y1 not in yimg_nozone or y2 not in yimg_nozone ) and (x1 not in ximg_nozone or x2 not in ximg_nozone ):
126+ filtered_lines .append (line )
127+
128+ calculate_angles (filtered_lines )
100129
101130 # Create a copy to draw lines on
102131 image_lines_thrs = orig_frame .copy ()
103132 lines_thrs = np .zeros_like (dummy_mask )
104133
105134 # Draw detected lines while avoiding no-line zones
106- if lines is not None :
107- for line in lines :
108- x1 , y1 , x2 , y2 = line [0 ]
109- if (y1 not in yimg_nozone or y2 not in yimg_nozone ) and (x1 not in ximg_nozone or x2 not in ximg_nozone ):
110- cv2 .line (image_lines_thrs , (x1 , y1 ), (x2 , y2 ), (255 , 0 , 0 ), 10 ) # Blue lines
111- cv2 .line (lines_thrs , (x1 , y1 ), (x2 , y2 ), (255 , 0 , 0 ), 10 )
135+ for line in filtered_lines :
136+ x1 , y1 , x2 , y2 = line [0 ]
137+ cv2 .line (image_lines_thrs , (x1 , y1 ), (x2 , y2 ), (255 , 0 , 0 ), 1 ) # Blue lines
138+ cv2 .line (lines_thrs , (x1 , y1 ), (x2 , y2 ), (255 , 0 , 0 ), 10 )
112139
113140 # Mask lines with white areas
114141 lines_thrs = cv2 .bitwise_and (lines_thrs , white_msk )
@@ -125,6 +152,7 @@ def calculate_nozone(shape, offset=50):
125152
126153 # Display the combined frame
127154 cv2 .imshow ('Combined Video' , overlay_image )
155+ # cv2.imshow("Region of Interest", roi)
128156
129157 # Break loop if 'q' is pressed
130158 if cv2 .waitKey (30 ) & 0xFF == ord ('q' ):
0 commit comments