Quantcast
Channel: Raspberry Pi Forums
Viewing all articles
Browse latest Browse all 8082

Hailo • object detection can't save jpeg or videos PI5 + Pi AI HAT

$
0
0
I have a modified detection.py script that is intended to save a short video if a "bird" is detected. The camera preview shows a bird is detected but the saved file is empty. Any insight would greatly be appreciated.

Frame count: 228
Detection: Label: bird Confidence: 0.88
Detection: Label: bird Confidence: 0.82
Detection: Label: bird Confidence: 0.79
Detection: Label: bird Confidence: 0.78
Detection: Label: bird Confidence: 0.77
Detection: Label: bird Confidence: 0.74
Detection: Label: bird Confidence: 0.64
Detection: Label: bird Confidence: 0.55
Detection: Label: bird Confidence: 0.43

Failed to push buffer: <enum GST_FLOW_FLUSHING of type Gst.FlowReturn>
Exiting...
Stopping recording...
Input #0, rawvideo, from 'pipe:':
Duration: N/A, bitrate: 663552 kb/s
Stream #0:0: Video: rawvideo (BGR[24] / 0x18524742), bgr24, 1280x720, 663552 kb/s, 30 tbr, 30 tbn
Stream mapping:
Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (libx264))
Finishing stream 0:0 without any data written to it.
[libx264 @ 0x55567335c730] using cpu capabilities: ARMv8 NEON
[libx264 @ 0x55567335c730] profile High 4:4:4 Predictive, level 3.1, 4:4:4, 8-bit
[libx264 @ 0x55567335c730] 264 - core 164 r3095 baee400 - H.264/MPEG-4 AVC codec - Copyleft 2003-2022 - http://www.videolan.org/x264.html - options: cabac=1 ref=1 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=2 psy=1 psy_rd=1.00:0.00 mixed_ref=0 me_range=16 chroma_me=1 trellis=0 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=6 threads=6 lookahead_threads=2 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=1 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=10 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to '/home/paul/Downloads/bird_detection_20250518_203026.mp4':
Metadata:
encoder : Lavf59.27.100
Stream #0:0: Video: h264 (avc1 / 0x31637661), yuv444p, 1280x720, q=2-31, 30 fps, 15360 tbn
Metadata:
encoder : Lavc59.37.100 libx264
Side data:
cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: N/A
frame= 0 fps=0.0 q=0.0 Lsize= 0kB time=00:00:00.00 bitrate=N/A speed= 0x
video:0kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown
Exiting normally, received signal 2.
Traceback (most recent call last):
File "/home/paul/hailo-rpi5-examples/basic_pipelines/detection6video.py", line 206, in <module>
main()
File "/home/paul/hailo-rpi5-examples/basic_pipelines/detection6video.py", line 201, in main
app.quit()
^^^^^^^^
AttributeError: 'GStreamerDetectionApp' object has no attribute 'quit'

Script
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GLib
import os
import numpy as np
import cv2
import hailo
from datetime import datetime, timedelta
import subprocess
import time # Import the time module

from hailo_apps_infra.hailo_rpi_common import (
get_caps_from_pad,
get_numpy_from_buffer,
app_callback_class,
)
from hailo_apps_infra.detection_pipeline import GStreamerDetectionApp

class VideoRecorder:
def __init__(self, save_location):
self.save_location = save_location
self.is_recording = False
self.process = None
self.start_time = None
self.video_filename = None
self.frame_width = None
self.frame_height = None
self.fps = 30 # Adjust as needed

def start_recording(self, width, height):
if not self.is_recording:
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
self.video_filename = os.path.join(self.save_location, f"bird_detection_{timestamp}.mp4")
self.frame_width = width
self.frame_height = height
command = [
'ffmpeg',
'-y', # Overwrite if exists
'-f', 'rawvideo',
'-pix_fmt', 'bgr24',
'-s', f'{self.frame_width}x{self.frame_height}',
'-r', str(self.fps),
'-i', '-',
'-c:v', 'libx264',
'-preset', 'veryfast',
'-crf', '23',
self.video_filename
]
try:
self.process = subprocess.Popen(command, stdin=subprocess.PIPE)
self.is_recording = True
self.start_time = datetime.now()
print(f"Recording started to: {self.video_filename}")
except FileNotFoundError:
print("Error: ffmpeg not found.")
self.process = None
self.is_recording = False
except Exception as e:
print(f"Error starting recording: {e}")
self.process = None
self.is_recording = False

def record_frame(self, frame):
if self.is_recording and self.process and self.process.stdin is not None:
try:
self.process.stdin.write(frame.tobytes())
except BrokenPipeError:
print("Error: Broken pipe while writing frame.")
self.stop_recording()
except Exception as e:
print(f"Error writing frame: {e}")
self.stop_recording()

def stop_recording(self):
if self.is_recording and self.process:
print("Stopping recording...")
try:
self.process.stdin.close()
self.process.wait(timeout=5) # Wait for the process to finish
except Exception as e:
print(f"Error stopping recording process: {e}")
finally:
self.process = None
self.is_recording = False
self.start_time = None
self.video_filename = None

def should_stop(self):
if self.is_recording and self.start_time:
return datetime.now() - self.start_time >= timedelta(seconds=10)
return False

class user_app_callback_class(app_callback_class):
def __init__(self, save_location):
super().__init__()
self.new_variable = 42
self.bird_detected = False
self.video_recorder = VideoRecorder(save_location)
self.recording_triggered = False
self.frame_width = None
self.frame_height = None

def new_function(self):
return "The meaning of life is: "

def set_bird_detected(self, detected):
self.bird_detected = detected
if detected and not self.recording_triggered:
self.recording_triggered = True

def get_bird_detected(self):
return self.bird_detected

def set_frame_dimensions(self, width, height):
self.frame_width = width
self.frame_height = height

def app_callback(pad, info, user_data):
buffer = info.get_buffer()
if buffer is None:
return Gst.PadProbeReturn.OK

user_data.increment()
string_to_print = f"Frame count: {user_data.get_count()}\n"

format, width, height = get_caps_from_pad(pad)
if user_data.frame_width is None or user_data.frame_height is None:
user_data.set_frame_dimensions(width, height)

frame = None
if user_data.use_frame and format is not None and width is not None and height is not None:
frame = get_numpy_from_buffer(buffer, format, width, height)
frame_bgr = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) # Convert to BGR for ffmpeg

if user_data.video_recorder.is_recording:
user_data.video_recorder.record_frame(frame_bgr)

roi = hailo.get_roi_from_buffer(buffer)
detections = roi.get_objects_typed(hailo.HAILO_DETECTION)

bird_detected_in_frame = False
detection_count = 0
for detection in detections:
label = detection.get_label()
confidence = detection.get_confidence()
if label == "bird":
string_to_print += (f"Detection: Label: {label} Confidence: {confidence:.2f}\n")
detection_count += 1
bird_detected_in_frame = True
user_data.set_bird_detected(True)
if not user_data.video_recorder.is_recording and user_data.video_recorder.process is None and user_data.frame_width is not None and user_data.frame_height is not None:
user_data.video_recorder.start_recording(user_data.frame_width, user_data.frame_height)
elif label == "person":
track = detection.get_objects_typed(hailo.HAILO_UNIQUE_ID)
if len(track) == 1:
track_id = track[0].get_id()
string_to_print += (f"Detection: ID: {track_id} Label: {label} Confidence: {confidence:.2f}\n")
detection_count += 1

if user_data.use_frame and frame is not None:
cv2.putText(frame, f"Detections: {detection_count}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.putText(frame, f"{user_data.new_function()} {user_data.new_variable}", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)

print(string_to_print)
return Gst.PadProbeReturn.OK

def main():
save_location = input("Enter the directory to save the video: ")
if not os.path.isdir(save_location):
print(f"Error: Directory '{save_location}' does not exist.")
return

user_data = user_app_callback_class(save_location)
app = GStreamerDetectionApp(app_callback, user_data)
main_loop = GLib.MainLoop()

try:
# Start the GStreamer pipeline in a separate thread to avoid blocking the main loop
import threading
pipeline_thread = threading.Thread(target=app.run)
pipeline_thread.start()

recording_active = False
while True:
if user_data.video_recorder.is_recording and not recording_active:
recording_active = True
elif recording_active and user_data.video_recorder.should_stop():
user_data.video_recorder.stop_recording()
break # Exit the main loop after recording

time.sleep(0.1) # Small delay

except GLib.Error as e:
print(f"GStreamer error occurred: {e}")
except KeyboardInterrupt:
print("Exiting application.")
finally:
if user_data.video_recorder.is_recording:
user_data.video_recorder.stop_recording()
# Ensure the GStreamer pipeline is stopped
app.quit()
if 'pipeline_thread' in locals() and pipeline_thread.is_alive():
pipeline_thread.join()

if __name__ == "__main__":
main()

Statistics: Posted by PaulOski — Mon May 19, 2025 12:33 am



Viewing all articles
Browse latest Browse all 8082

Trending Articles