Skip to content

Meenakshiarya22 patch 1 #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141,273 changes: 141,273 additions & 0 deletions 1_detection_to_csv.ipynb

Large diffs are not rendered by default.

245,759 changes: 245,759 additions & 0 deletions 1_detection_to_csv_wbb.ipynb

Large diffs are not rendered by default.

101 changes: 101 additions & 0 deletions 2_detect_red_all.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import cv2
import os
import pandas as pd
import numpy as np
from os.path import splitext, basename, join
from datetime import datetime, timedelta
from glob import glob

# Function to detect red light in the ROI
def detect_red_light(image):
lower_red = np.array([0, 120, 70])
upper_red = np.array([10, 255, 255])
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, lower_red, upper_red)
return cv2.countNonZero(mask) > 0

# Function to manually draw the ROI
def draw_roi(event, x, y, flags, param):
global traffic_light_box, drawing, top_left_pt, bottom_right_pt, roi_selected
if event == cv2.EVENT_LBUTTONDOWN:
drawing = True
top_left_pt = (x, y)
elif event == cv2.EVENT_LBUTTONUP:
drawing = False
bottom_right_pt = (x, y)
roi_selected = True

# Paths
videos_path = 'C:/Users/marya1/Box/MnDOT DNRTOR Project/Meenakshi/videos'
output_path = 'C:/Users/marya1/Box/MnDOT DNRTOR Project/Meenakshi/detect_red'
#videos_path = 'C:/Users/ASUS/Box/MnDOT DNRTOR Project/Pratik'
#output_path = 'C:/Users/ASUS/Box/MnDOT DNRTOR Project/Pratik/output'
#videos_path = 'E:/MnDOT/Videos'
#output_path = 'E:/MnDOT/Videos/output'


# List all video files
video_files = glob(join(videos_path, '*.mp4'))

for video_path in video_files:
# Initialize variables for each video
traffic_light_box = None
roi_selected = False

# Display video and select ROI
cap = cv2.VideoCapture(video_path)
ret, first_frame = cap.read()
if not ret:
print("Failed to read video:", video_path)
cap.release()
continue # Skip to the next video

# Input for date and time
video_date = input(f"Enter the video start date (yyyy-mm-dd) for {basename(video_path)}: ")
video_start_time = input(f"Enter the video start time (hh-mm-ss) for {basename(video_path)}: ")
start_datetime = datetime.strptime(f"{video_date} {video_start_time}", "%Y-%m-%d %H-%M-%S")

cv2.namedWindow('Frame')
cv2.setMouseCallback('Frame', draw_roi)

print("Draw a bounding box around the traffic light and press 'Enter'.")
while True:
frame_copy = first_frame.copy()
if roi_selected:
cv2.rectangle(frame_copy, top_left_pt, bottom_right_pt, (0, 255, 0), 2)
cv2.imshow('Frame', frame_copy)
key = cv2.waitKey(1)
if key == 13: # Enter key
traffic_light_box = (top_left_pt[0], top_left_pt[1], bottom_right_pt[0] - top_left_pt[0], bottom_right_pt[1] - top_left_pt[1])
break

cv2.destroyAllWindows()

df = pd.DataFrame(columns=['Frame_Number', 'Date', 'Time', 'Red_Light'])
frame_counter = 0
fps = cap.get(cv2.CAP_PROP_FPS)

while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
current_time = start_datetime + timedelta(seconds=frame_counter / fps)
date_str = current_time.strftime("%Y-%m-%d")
time_str = current_time.strftime("%H:%M:%S")

traffic_light_roi = frame[traffic_light_box[1]:traffic_light_box[1]+traffic_light_box[3],
traffic_light_box[0]:traffic_light_box[0]+traffic_light_box[2]]
red_light_detected = detect_red_light(traffic_light_roi)

new_row = {'Frame_Number': frame_counter, 'Date': date_str, 'Time': time_str, 'Red_Light': red_light_detected}
df = pd.concat([df, pd.DataFrame([new_row])], ignore_index=True)

frame_counter += 1

cap.release()

# Save the DataFrame to a CSV file
csv_file_name = splitext(basename(video_path))[0] + '.csv'
csv_path = join(output_path, csv_file_name)
df.to_csv(csv_path, index=False)
print(f"CSV saved at {csv_path}")
55 changes: 55 additions & 0 deletions 3_merge_detection_red.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import pandas as pd
import os
from glob import glob

def merge_csv_with_timestamps(output_csv_dir, timestamps_csv_dir, merged_csv_dir):
# List all CSV files in the output CSV directory
output_csv_files = glob(os.path.join(output_csv_dir, '*.csv'))

for output_csv_path in output_csv_files:
# Derive the base file name without extension to match with timestamp file
base_file_name = os.path.basename(output_csv_path)

# Construct the expected timestamp CSV file path
timestamps_csv_path = os.path.join(timestamps_csv_dir, base_file_name)

# Check if the corresponding timestamps CSV exists
if not os.path.exists(timestamps_csv_path):
print(f"No matching timestamp file found for {base_file_name}. Skipping...")
continue

# Load the CSV files
output_df = pd.read_csv(output_csv_path)
timestamps_df = pd.read_csv(timestamps_csv_path)

# Merge the two dataframes on the Frame and Frame_Number columns
merged_df = pd.merge(output_df, timestamps_df, left_on='Frame', right_on='Frame_Number', how='left')

# Including all relevant columns and renaming
#final_df = merged_df[['Datetime', 'Frame', 'Track', 'Class', 'BBox', 'Time', 'Date', 'Red_Light']].copy()
final_df = merged_df[['Datetime', 'Frame', 'Track', 'Class', 'Class_ID','xmin', 'ymin','xmax','ymax', 'Time', 'Date', 'Red_Light']].copy()
final_df.rename(columns={'Frame': 'FrameNumber', 'Red_Light': 'Color'}, inplace=True)

# Handle 'Color' column
final_df['Color'].fillna('Not Red', inplace=True)
final_df['Color'] = final_df['Color'].apply(lambda x: 'Red' if x == True else 'Not Red')

# Construct path for saving the merged CSV
merged_csv_path = os.path.join(merged_csv_dir, base_file_name)

# Save the merged dataframe
final_df.to_csv(merged_csv_path, index=False)
print(f"Merged CSV saved to {merged_csv_path}")

# Directories containing the CSV files
#output_csv_dir = 'C:/Users/marya1/Box/MnDOT DNRTOR Project/Meenakshi/detect_objects'
#timestamps_csv_dir = 'C:/Users/marya1/Box/MnDOT DNRTOR Project/Meenakshi/detect_red'
#merged_csv_dir = 'C:/Users/marya1/Box/MnDOT DNRTOR Project/Meenakshi/final_csv'


output_csv_dir = '/home/marya1/Documents/MnDoTNRToR/inference/detect_objects/processing'
timestamps_csv_dir = '/home/marya1/Documents/MnDoTNRToR/inference/detect_red'
merged_csv_dir = '/home/marya1/Documents/MnDoTNRToR/inference/final_csv'

# Call the function with the directories
merge_csv_with_timestamps(output_csv_dir, timestamps_csv_dir, merged_csv_dir)
39 changes: 39 additions & 0 deletions 3_merge_detection_red2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import pandas as pd
import os
from glob import glob

def merge_csv_with_timestamps(output_csv_dir, timestamps_csv_dir, merged_csv_dir):
output_csv_files = glob(os.path.join(output_csv_dir, '*.csv'))

for output_csv_path in output_csv_files:
base_file_name = os.path.basename(output_csv_path)
timestamps_csv_path = os.path.join(timestamps_csv_dir, base_file_name)

if not os.path.exists(timestamps_csv_path):
print(f"No matching timestamp file found for {base_file_name}. Skipping...")
continue

try:
output_df = pd.read_csv(output_csv_path, on_bad_lines='warn')
timestamps_df = pd.read_csv(timestamps_csv_path, on_bad_lines='warn')
except Exception as e:
print(f"Error reading {base_file_name}: {e}")
continue

merged_df = pd.merge(output_df, timestamps_df, left_on='Frame', right_on='Frame_Number', how='left')
final_df = merged_df[['Datetime', 'Frame', 'Track', 'Class', 'Class_ID', 'xmin', 'ymin', 'xmax', 'ymax', 'Time', 'Date', 'Red_Light']].copy()
final_df.rename(columns={'Frame': 'FrameNumber', 'Red_Light': 'Color'}, inplace=True)
final_df['Color'].fillna('Not Red', inplace=True)
final_df['Color'] = final_df['Color'].apply(lambda x: 'Red' if x == True else 'Not Red')

merged_csv_path = os.path.join(merged_csv_dir, base_file_name)
final_df.to_csv(merged_csv_path, index=False)
print(f"Merged CSV saved to {merged_csv_path}")


output_csv_dir = '/home/marya1/Documents/MnDoTNRToR/inference/detect_objects/processing'
timestamps_csv_dir = '/home/marya1/Documents/MnDoTNRToR/inference/detect_red'
merged_csv_dir = '/home/marya1/Documents/MnDoTNRToR/inference/final_csv'

# Use the directories as defined in the script
merge_csv_with_timestamps(output_csv_dir, timestamps_csv_dir, merged_csv_dir)
126 changes: 126 additions & 0 deletions 4_detect_violations_confirmation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import cv2
import pandas as pd
from os.path import join, basename, splitext
from glob import glob

# Define global variables for ROI drawing
drawing = False
roi_selected = False
top_left_pt, bottom_right_pt = None, None

def draw_roi(event, x, y, flags, param):
global drawing, roi_selected, top_left_pt, bottom_right_pt
if event == cv2.EVENT_LBUTTONDOWN:
drawing = True
top_left_pt = (x, y)
elif event == cv2.EVENT_LBUTTONUP:
drawing = False
bottom_right_pt = (x, y)
roi_selected = True

def is_within_roi(xmin, ymin, xmax, ymax, roi):
roi_xmin, roi_ymin, roi_xmax, roi_ymax = roi
return xmin >= roi_xmin and xmax <= roi_xmax and ymin >= roi_ymin and ymax <= roi_ymax


def count_vehicles_and_violations(csv_file, roi, valid_classes=[1, 2, 3, 5, 7], min_frames=60):
df = pd.read_csv(csv_file)
# Assuming 'Date' column is in 'YYYY-MM-DD' format and 'Time' in 'HH:MM:SS' format
df['DateTime'] = pd.to_datetime(df['Date'] + ' ' + df['Time'], errors='coerce')

red_light_phases = df[df['Color'] == 'Red'].groupby((df['Color'] != df['Color'].shift()).cumsum())
results = []

for _, phase in red_light_phases:
start_of_red_light = phase['DateTime'].iloc[0]
next_phase_start = phase['DateTime'].iloc[-1] + pd.Timedelta(seconds=1)

# Skip intervals less than 1 second
if (next_phase_start - start_of_red_light).total_seconds() <= 1:
continue

tracks_in_roi = df[(df['DateTime'] >= start_of_red_light) & (df['DateTime'] < next_phase_start)]
tracks_in_roi = tracks_in_roi[tracks_in_roi.apply(lambda row: is_within_roi(row['xmin'], row['ymin'], row['xmax'], row['ymax'], roi), axis=1)]
valid_tracks_in_roi = tracks_in_roi[tracks_in_roi['Class_ID'].isin(valid_classes)]

# Count frames for each track and filter out those with less than min_frames
frame_counts = valid_tracks_in_roi.groupby('Track').size()
tracks_more_than_min_frames = frame_counts[frame_counts >= min_frames].index
valid_tracks_in_roi = valid_tracks_in_roi[valid_tracks_in_roi['Track'].isin(tracks_more_than_min_frames)]

exiting_tracks = valid_tracks_in_roi.groupby('Track').last()
exiting_tracks = exiting_tracks[exiting_tracks.index.isin(tracks_more_than_min_frames)]
violations = exiting_tracks[exiting_tracks['Color'] == 'Red'].index.nunique()
violating_track_ids = exiting_tracks[exiting_tracks['Color'] == 'Red'].index.unique().tolist()
total_vehicles = valid_tracks_in_roi['Track'].nunique()

total_vehicles_complying = valid_tracks_in_roi['Track'].nunique() - violations
complying_track_ids = valid_tracks_in_roi[~valid_tracks_in_roi['Track'].isin(violating_track_ids)]['Track'].unique().tolist()

results.append({
'Start_of_Red_Light': start_of_red_light.strftime('%Y-%m-%d %H:%M:%S'),
'Beginning_of_Not_Red': next_phase_start.strftime('%Y-%m-%d %H:%M:%S'),
'Total_Vehicles': total_vehicles,
'Vehicles_Complying': total_vehicles_complying,
'Vehicles_Violating': violations,
'Complying Tracks': complying_track_ids,
'Violating Tracks': violating_track_ids,
'Compliance Rate': (total_vehicles - violations) / total_vehicles if total_vehicles > 0 else 1
})

results_df = pd.DataFrame(results)


if not results_df.empty:
overall_compliance_rate = (results_df['Total_Vehicles'].sum() - results_df['Vehicles_Violating'].sum()) / results_df['Total_Vehicles'].sum()
overall_summary = pd.DataFrame([{'Start_of_Red_Light': 'Overall', 'Beginning_of_Not_Red': '', 'Total_Vehicles': results_df['Total_Vehicles'].sum(), 'Vehicles_Violating': results_df['Vehicles_Violating'].sum(), 'Compliance Rate': overall_compliance_rate}])
results_df = pd.concat([results_df, overall_summary], ignore_index=True)

return results_df

csv_path = '/home/marya1/Documents/MnDoTNRToR/inference/final_csv'
output_path='/home/marya1/Documents/MnDoTNRToR/inference/detect_violations_trial'
videos_path = '/home/marya1/Documents/MnDoTNRToR/videos/processing'

video_files = glob(join(videos_path, '*.mp4'))

for video_path in video_files:
cap = cv2.VideoCapture(video_path)
ret, first_frame = cap.read()
if not ret:
print(f"Failed to read video: {video_path}")
continue

# Reset RoI selection variables
drawing = False
roi_selected = False
top_left_pt, bottom_right_pt = None, None

cv2.namedWindow('Frame')
cv2.setMouseCallback('Frame', draw_roi)
print("Draw a bounding box around the area of interest and press 'Enter'.")

while True:
frame_copy = first_frame.copy()
if roi_selected:
cv2.rectangle(frame_copy, top_left_pt, bottom_right_pt, (0, 255, 0), 2)
cv2.imshow('Frame', frame_copy)
key = cv2.waitKey(1) & 0xFF
if key == 13: # Enter key is pressed
break

if not roi_selected:
print(f"RoI not selected for video: {video_path}. Skipping...")
cv2.destroyAllWindows()
continue

roi = (top_left_pt[0], top_left_pt[1], bottom_right_pt[0], bottom_right_pt[1])
cv2.destroyAllWindows()
cap.release()

# Proceed with analysis using selected RoI
csv_file = join(csv_path, splitext(basename(video_path))[0] + '.csv')
analysis_results = count_vehicles_and_violations(csv_file, roi)
output_file = join(output_path, splitext(basename(video_path))[0] + '_violations.csv')
analysis_results.to_csv(output_file, index=False)
print(f"Analysis saved to {output_file}")
Loading