File size: 6,950 Bytes
c02ccb7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import gradio as gr
import cv2
import numpy as np
from PIL import Image
from pathlib import Path

# Assuming find_target_in_source, reid_model, yolo_model, and transform are defined globally from previous cells

def process_video_with_reid_gradio(target_image: Image.Image, video1_filepath: str, video1_gps: str, video2_filepath: str, video2_gps: str, video3_filepath: str, video3_gps: str):
    """
    Processes three videos frame by frame, performs human detection and re-identification
    based on a target image, and saves annotated output videos.
    Includes GPS location for each video input and reports the location if a match is found.
    """
    video_inputs = [
        {"filepath": video1_filepath, "gps": video1_gps, "name": "Camera 1"},
        {"filepath": video2_filepath, "gps": video2_gps, "name": "Camera 2"},
        {"filepath": video3_filepath, "gps": video3_gps, "name": "Camera 3"}
    ]

    if target_image is None or any(v["filepath"] is None for v in video_inputs):
        return [None] * 3, "Please provide both a target image and all source videos.", "Error: Please provide both a target image and all source videos."

    output_videos = []
    all_summaries = []
    concise_summaries = []

    for video_info in video_inputs:
        video_filepath = video_info["filepath"]
        camera_name = video_info["name"]
        camera_gps = video_info["gps"]
        video_filename = Path(video_filepath).name
        print(f"Processing video from {camera_name} ({video_filename})")

        # 1. Load the video
        cap = cv2.VideoCapture(video_filepath)
        if not cap.isOpened():
            all_summaries.append(f"Error: Could not open video file {camera_name} ({video_filename})")
            concise_summaries.append(f"{camera_name}: Error opening video file.")
            output_videos.append(None)
            continue

        # Get video properties
        fps = int(cap.get(cv2.CAP_PROP_FPS))
        width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
        height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
        frame_size = (width, height)

        processed_frames = []
        video_summary_lines = []
        frame_count = 0
        found_match_in_video = False
        match_time_sec = -1

        print("Processing video frames...")
        # 2. Loop through each frame
        while True:
            ret, frame = cap.read()
            if not ret:
                break

            # Convert OpenCV BGR frame to PIL RGB image
            frame_pil = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))

            # 3. Call find_target_in_source
            annotated_frame_rgb, summary = find_target_in_source(target_image, frame_pil)

            # Check if any match was found in this frame
            if "MATCH" in summary and not found_match_in_video:
                found_match_in_video = True
                match_time_sec = frame_count / fps if fps > 0 else 0


            # Store the results
            processed_frames.append(annotated_frame_rgb)
            video_summary_lines.append(f"Frame {frame_count + 1}: {summary}")
            frame_count += 1


        # 4. Release the video capture object
        cap.release()
        print("Finished processing frames.")

        if not processed_frames:
            all_summaries.append(f"No frames were processed from {camera_name} ({video_filename}).")
            concise_summaries.append(f"{camera_name}: No frames processed.")
            output_videos.append(None)
            continue

        # 5. Create output video
        output_video_path = f'/content/gradio_output_{Path(video_filepath).stem}.mp4'
        fourcc = cv2.VideoWriter_fourcc(*'mp4v')
        out = cv2.VideoWriter(output_video_path, fourcc, fps, frame_size)

        if not out.isOpened():
            fourcc = cv2.VideoWriter_fourcc(*'XVID')
            out = cv2.VideoWriter(output_video_path, fourcc, fps, frame_size)
            if not out.isOpened():
                 all_summaries.append(f"Error: Could not create video writer object for {camera_name} ({video_filename}).")
                 concise_summaries.append(f"{camera_name}: Error creating output video.")
                 output_videos.append(None)
                 continue


        print(f"Writing {len(processed_frames)} frames to {output_video_path}...")
        # 6. Write frames to video
        for frame_rgb in processed_frames:
            frame_bgr = cv2.cvtColor(frame_rgb, cv2.COLOR_RGB2BGR)
            out.write(frame_bgr)

        # 7. Release the VideoWriter
        out.release()
        print(f"Output video created successfully for {camera_name} ({video_filename}).")

        # 8. Combine summaries for this video, including camera name
        combined_video_summary = f"--- Summary for {camera_name} ({video_filename}) ---\n" + "\n".join(video_summary_lines)
        all_summaries.append(combined_video_summary)

        # 9. Create concise summary for this video
        if found_match_in_video:
            concise_summaries.append(f"{camera_name} (GPS: {camera_gps}): Suspect found at approximately {match_time_sec:.2f} seconds.")
        else:
            concise_summaries.append(f"{camera_name}: Suspect is not found.")


        output_videos.append(output_video_path)


    # 10. Combine all summaries
    combined_detailed_summary = "\n\n".join(all_summaries)
    combined_concise_summary = "\n".join(concise_summaries)

    # 11. Return output video paths and combined summaries
    return output_videos, combined_detailed_summary, combined_concise_summary

# # Create a Gradio Interface
video_reid_iface = gr.Interface(
    fn=process_video_with_reid_gradio,
    inputs=[
        gr.Image(type="pil", label="Target Person Image"),
        gr.Video(label="Source Video 1"),
        gr.Text(label="Video 1 GPS Location (e.g., Latitude, Longitude)"), # Added GPS input
        gr.Video(label="Source Video 2"),
        gr.Text(label="Video 2 GPS Location (e.g., Latitude, Longitude)"), # Added GPS input
        gr.Video(label="Source Video 3"),
        gr.Text(label="Video 3 GPS Location (e.g., Latitude, Longitude)")  # Added GPS input
    ],
    outputs=[
        gr.Gallery(label="Detection Results Videos"),
        gr.Text(label="Detailed Summary of Results Per Frame Per Video", lines=10), # Increased lines for bigger box
        gr.Text(label="Concise Summary (Suspect Found/Not Found)")
    ],
    title="Person Re-identification in Multiple Videos",
    description="Upload an image of a target person and exactly 3 videos with their GPS locations. The system will detect all people in each video frame and check if any of them match the target, indicating which video the match was found in and its GPS location."
)

# Launch the Gradio interface
video_reid_iface.launch(share=True, debug=True)12. Create a Gradio Interface (Interface definition moved to a new cell)
# 13. Launch the Gradio interface (Launch call moved to a new cell)