From f31aa282dde3c5a166ac829e279aaf13a5e0c783 Mon Sep 17 00:00:00 2001 From: "Ishan S. Patel" Date: Mon, 16 Jun 2025 14:08:32 -0400 Subject: [PATCH] YACWC --- deepstream_obj_det.py | 255 ++++++++++++-------------------- deepstream_obj_det_pre_queue.py | 191 ++++++++++++------------ dump.json | 2 +- 3 files changed, 196 insertions(+), 252 deletions(-) mode change 100755 => 100644 deepstream_obj_det.py diff --git a/deepstream_obj_det.py b/deepstream_obj_det.py old mode 100755 new mode 100644 index 50414b5..6bda4cd --- a/deepstream_obj_det.py +++ b/deepstream_obj_det.py @@ -16,19 +16,14 @@ import argparse pfm = LogColorize.watch_and_fix_permissions logger = get_logger(__name__,'/var/log/ml_vision_logs/00_watch_and_fix_permissions', stdout=True, systemd=False) -Gst.debug_set_default_threshold(Gst.DebugLevel.INFO) -os.environ.pop("DISPLAY",':0') -target_width_detect = 1280 -target_height_detect = 720 -target_width_embed = 512 -target_height_embed = 512 - +target_width = 1280 +target_height = 720 +os.environ.pop("DISPLAY",None) MUXER_BATCH_TIMEOUT_USEC = 1000000 -def embed_results_probe(pad,info,u_data, list_add, frame_num = 0): +def embedder_results_probe(pad,info,u_data, list_add, frame_num = 0): gst_buffer = info.get_buffer() - print("HEY I AM PROBING EMBEDDINGS") if not gst_buffer: print("Unable to get GstBuffer ") return @@ -109,7 +104,7 @@ def detector_results_probe(pad,info,u_data, list_add, frame_num = 0): frame_number=0 num_rects=0 got_fps = False - print("HEY I AM PROBING DETECTIONS") + gst_buffer = info.get_buffer() if not gst_buffer: print("Unable to get GstBuffer ") @@ -183,6 +178,7 @@ def detector_results_probe(pad,info,u_data, list_add, frame_num = 0): def cb_newpad(decodebin, decoder_src_pad,data): + print("In cb_newpad\n") caps=decoder_src_pad.get_current_caps() if not caps: caps = decoder_src_pad.query_caps() @@ -219,22 +215,34 @@ def decodebin_child_added(child_proxy,Object,name,user_data): def create_source_bin(uri): + print("Creating source bin") + # Create a source GstBin to abstract this bin's content from the rest of the + # pipeline bin_name="source-bin-any-format" - + print(bin_name) nbin=Gst.Bin.new(bin_name) if not nbin: sys.stderr.write(" Unable to create source bin \n") + # Source element for reading from the uri. + # We will use decodebin and let it figure out the container format of the + # stream and the codec and plug the appropriate demux and decode plugins. uri_decode_bin=Gst.ElementFactory.make("uridecodebin", "uri-decode-bin") if not uri_decode_bin: sys.stderr.write(" Unable to create uri decode bin \n") - + # We set the input uri to the source element uri_decode_bin.set_property("uri",uri) - - uri_decode_bin.connect("pad-added",cb_newpad, nbin) + # Connect to the "pad-added" signal of the decodebin which generates a + # callback once a new pad for raw data has beed created by the decodebin + uri_decode_bin.connect("pad-added",cb_newpad,nbin) uri_decode_bin.connect("child-added",decodebin_child_added,nbin) + # We need to create a ghost pad for the source bin which will act as a proxy + # for the video decoder src pad. The ghost pad will not have a target right + # now. Once the decode bin creates the video decoder and generates the + # cb_newpad callback, we will set the ghost pad target to the video decoder + # src pad. Gst.Bin.add(nbin,uri_decode_bin) bin_pad=nbin.add_pad(Gst.GhostPad.new_no_target("src",Gst.PadDirection.SRC)) if not bin_pad: @@ -253,116 +261,86 @@ def run_inference(file_path): pipeline = Gst.Pipeline() - source_file=create_source_bin(file_path) - - - - - tee=Gst.ElementFactory.make("tee", "nvsink-tee") - - - - -# DETECT - queue_detect=Gst.ElementFactory.make("queue", "nvtee-detect") - - - streammux_detect = Gst.ElementFactory.make("nvstreammux", "Stream-muxer-detector") - streammux_detect.set_property('width', target_width_detect) - streammux_detect.set_property('height', target_height_detect) - streammux_detect.set_property('batched-push-timeout', MUXER_BATCH_TIMEOUT_USEC) - streammux_detect.set_property('enable-padding',1) - streammux_detect.set_property('batch-size', 4) + streammux = Gst.ElementFactory.make("nvstreammux", "Stream-muxer") nugget_detector = Gst.ElementFactory.make("nvinfer", "primary-inference") + nugget_embedder = Gst.ElementFactory.make("nvinfer", "secondary-inference") + + streammux.set_property('width', target_width) + streammux.set_property('height', target_height) + streammux.set_property('batched-push-timeout', MUXER_BATCH_TIMEOUT_USEC) + streammux.set_property('enable-padding',1) + streammux.set_property('batch-size', 4) + + +# nugget_detector.set_property('config-file-path', "/home/thebears/DeepStream-Yolo/detector.txt") nugget_detector.set_property('config-file-path', "/home/thebears/DeepStream-Yolo/config_infer_primary_yoloV7.txt") + nugget_embedder.set_property('config-file-path', "/home/thebears/DeepStream-Yolo/embedder.txt") - fakesink_detect = Gst.ElementFactory.make("fakesink","fakesink") - fakesink_detect.set_property('enable-last-sample', 0) - fakesink_detect.set_property('sync', 0) + fakesink1 = Gst.ElementFactory.make("fakesink","fakesink") + fakesink1.set_property('enable-last-sample', 0) + fakesink1.set_property('sync', 0) + pipeline.add(fakesink1) + fakesink2 = Gst.ElementFactory.make("fakesink","fakesink2") + fakesink2.set_property('enable-last-sample', 0) + fakesink2.set_property('sync', 0) + pipeline.add(fakesink2) - -# EMBED - - queue_embed=Gst.ElementFactory.make("queue", "nvtee-que-embed") - - streammux_embed = Gst.ElementFactory.make("nvstreammux", "Stream-muxer-embed") - streammux_embed.set_property('width', target_width_embed) - streammux_embed.set_property('height', target_height_embed) - streammux_embed.set_property('batched-push-timeout', MUXER_BATCH_TIMEOUT_USEC) - streammux_embed.set_property('enable-padding',1) - streammux_embed.set_property('batch-size', 4) - - - nugget_embed = Gst.ElementFactory.make("nvinfer", "primary-inference") - nugget_embed.set_property('config-file-path', "/home/thebears/DeepStream-Yolo/embedder.txt") -# nugget_embed.set_property('config-file-path', "/home/thebears/DeepStream-Yolo/config_infer_primary_yoloV7.txt") - - fakesink_embed = Gst.ElementFactory.make("fakesink","fakesink2") - fakesink_embed.set_property('enable-last-sample', 0) - fakesink_embed.set_property('sync', 0) + pipeline.add(streammux) + pipeline.add(nugget_detector) + pipeline.add(nugget_embedder) - - - - - - - - -# LINKING - - # Ensure NVMM caps with a capsfilter -# capsfilter = Gst.ElementFactory.make("capsfilter", "capsfilter") -# capsfilter.set_property("caps", Gst.Caps.from_string("video/x-raw(memory:NVMM), format=NV12")) -# pipeline.add(capsfilter) - - +# uri_name = 'file:///home/thebears/railing.mp4' +# uri_name = 'file:///home/thebears/railing_00_20250213094806.mp4' + source_file=create_source_bin(file_path) pipeline.add(source_file) + + stream_pad = streammux.request_pad_simple("sink_0") + source_pad = source_file.get_static_pad("src") + source_pad.link(stream_pad) + + tee=Gst.ElementFactory.make("tee", "nvsink-tee") pipeline.add(tee) - nvvidconv = Gst.ElementFactory.make("nvvidconv", "nvvidconv") - pipeline.add(nvvidconv) + queue1=Gst.ElementFactory.make("queue", "nvtee-que1") + queue2=Gst.ElementFactory.make("queue", "nvtee-que2") + pipeline.add(queue1) + pipeline.add(queue2) + + streammux.link(tee) + - source_file.link(nvvidconv) - # nvvidconv.link(capsfilter) - # capsfilter.link(tee) - nvvidconv.link(tee) + tee.link(queue1) + tee.link(queue2) + + +# preprocess_detector = Gst.ElementFactory.make("nvdspreprocess","preprocess_detector") +# preprocess_detector.set_property('config-file', "/home/thebears/DeepStream-Yolo/detector_preprocess.txt") +# preprocess_detector.set_property('config-file',pre_file) + + +# preprocess_embedder = Gst.ElementFactory.make("nvdspreprocess","preprocess_embedder") +# preprocess_embedder.set_property('config-file', "/home/thebears/DeepStream-Yolo/embedder_preprocess.txt") +# preprocess_embedder.set_property('config-file',pre_file) + +# pipeline.add(preprocess_detector) +# pipeline.add(preprocess_embedder) + +# queue1.link(preprocess_detector) +# preprocess_detector.link(nugget_detector) + +# queue2.link(preprocess_embedder) +# preprocess_embedder.link(nugget_embedder) + + + queue1.link(nugget_detector) + queue2.link(nugget_embedder) - - if True: - pipeline.add(queue_detect) - pipeline.add(streammux_detect) - pipeline.add(nugget_detector) - pipeline.add(fakesink_detect) - - - - tee.get_request_pad("src_%u").link(queue_detect.get_static_pad("sink")) - queue_detect.get_static_pad("src").link(streammux_detect.get_request_pad("sink_0")) - streammux_detect.link(nugget_detector) - nugget_detector.link(fakesink_detect) - - - - - if False: - pipeline.add(queue_embed) - pipeline.add(streammux_embed) - pipeline.add(nugget_embed) - pipeline.add(fakesink_embed) - - tee.get_request_pad("src_%u").link(queue_embed.get_static_pad("sink")) - queue_embed.get_static_pad("src").link(streammux_embed.get_request_pad("sink_0")) - streammux_embed.link(nugget_embed) - nugget_embed.link(fakesink_embed) - - print_pipeline_structure(pipeline) cmd = f'/usr/bin/ffprobe -v error -select_streams v:0 -count_packets -show_entries stream=nb_read_packets -of csv=p=0 {file_path}'#/srv/ftp/railing/2025/02/28/railing_00_20250228115800.mp4 try: frames = int(os.popen(cmd).read().strip()) @@ -371,24 +349,21 @@ def run_inference(file_path): logger.info(f"TOTAL_FRAMES: {frames}") - embed_list = list() + embedder_list = list() - Gst.debug_bin_to_dot_file(pipeline, Gst.DebugGraphDetails.ALL, "pipeline_structure") - embed_results = partial(embed_results_probe, list_add=embed_list, frame_num = frames) - nugget_embed.get_static_pad("src").add_probe(Gst.PadProbeType.BUFFER, embed_results, 0) + + embedder_results = partial(embedder_results_probe, list_add=embedder_list, frame_num = frames) + nugget_embedder.get_static_pad("src").add_probe(Gst.PadProbeType.BUFFER, embedder_results, 0) - - Gst.debug_bin_to_dot_file(pipeline, Gst.DebugGraphDetails.ALL, "/home/thebears/local/source/pipeline_structure") - detector_list = list() detector_results = partial(detector_results_probe, list_add = detector_list, frame_num = frames) nugget_detector.get_static_pad("src").add_probe(Gst.PadProbeType.BUFFER, detector_results, 0) - - print("AFTER SETTING STATIC PADS") + + def get_pipeline_string(pipeline): if not isinstance(pipeline, Gst.Pipeline): return None @@ -403,9 +378,11 @@ def run_inference(file_path): return " ! ".join(elements) - Gst.debug_bin_to_dot_file(pipeline, Gst.DebugGraphDetails.ALL, "pipeline_structure") - + nugget_detector.link(fakesink1) + nugget_embedder.link(fakesink2) + print(get_pipeline_string(pipeline)) + # create an event loop and feed gstreamer bus mesages to it loop = GLib.MainLoop() bus = pipeline.get_bus() @@ -421,45 +398,7 @@ def run_inference(file_path): pass # cleanup pipeline.set_state(Gst.State.NULL) - return detector_list, embed_list - -def print_pipeline_structure(pipeline): - """ - Recursively prints elements in the pipeline and their properties. - """ - if not isinstance(pipeline, Gst.Pipeline): - print("Not a valid GStreamer pipeline.") - return - - def _print_element_properties(element, indent=0): - spaces = " " * indent - print(spaces + f"Element: {element.get_name()} (Type: {element.get_factory().get_name()})") - - # Print its properties - for prop in element.list_properties(): - try: - val = element.get_property(prop.name) - if val != prop.default_value: # Display only non-default properties - print(spaces + f" - {prop.name}: {val}") - except: - pass - - def _print_pipeline_structure(element, indent=0): - spaces = " " * indent - children = element.children if hasattr(element, 'children') else [] - - if len(children) > 0: - print(spaces + f"[{element.get_name()}]") - for child in children: - _print_pipeline_structure(child, indent + 2) - else: - _print_element_properties(element, indent) - - print("\nPipeline Structure:") - print("===================") - _print_pipeline_structure(pipeline) - print("===================\n") - + return detector_list, embedder_list def get_detailed_pipeline_string(pipeline): """Generate a more detailed pipeline string with properties""" diff --git a/deepstream_obj_det_pre_queue.py b/deepstream_obj_det_pre_queue.py index 50414b5..8ffa31c 100755 --- a/deepstream_obj_det_pre_queue.py +++ b/deepstream_obj_det_pre_queue.py @@ -16,7 +16,7 @@ import argparse pfm = LogColorize.watch_and_fix_permissions logger = get_logger(__name__,'/var/log/ml_vision_logs/00_watch_and_fix_permissions', stdout=True, systemd=False) -Gst.debug_set_default_threshold(Gst.DebugLevel.INFO) +Gst.debug_set_default_threshold(Gst.DebugLevel.ERROR) os.environ.pop("DISPLAY",':0') target_width_detect = 1280 target_height_detect = 720 @@ -26,6 +26,99 @@ target_width_embed = 512 target_height_embed = 512 MUXER_BATCH_TIMEOUT_USEC = 1000000 + +def print_pipeline_structure(pipeline): + """ + Recursively prints elements in the pipeline and their properties. + """ + if not isinstance(pipeline, Gst.Pipeline): + print("Not a valid GStreamer pipeline.") + return + + def _print_element_properties(element, indent=0): + spaces = " " * indent + print(spaces + f"Element: {element.get_name()} (Type: {element.get_factory().get_name()})") + + # Print its properties + for prop in element.list_properties(): + try: + val = element.get_property(prop.name) + if val != prop.default_value: # Display only non-default properties + print(spaces + f" - {prop.name}: {val}") + except: + pass + + def _print_pipeline_structure(element, indent=0): + spaces = " " * indent + children = element.children if hasattr(element, 'children') else [] + + if len(children) > 0: + print(spaces + f"[{element.get_name()}]") + for child in children: + _print_pipeline_structure(child, indent + 2) + else: + _print_element_properties(element, indent) + + print("\nPipeline Structure:") + print("===================") + _print_pipeline_structure(pipeline) + print("===================\n") + + +def get_detailed_pipeline_string(pipeline): + """Generate a more detailed pipeline string with properties""" + if not isinstance(pipeline, Gst.Pipeline): + return None + + def get_element_string(element): + # Get element factory name + factory = element.get_factory() + if factory: + element_str = factory.get_name() + else: + element_str = element.get_name() + + # Add properties + props = [] + for prop in element.list_properties(): + # Skip some properties that are typically not set in command line + if prop.name in ('name', 'parent'): + continue + + try: + val = element.get_property(prop.name) + if val is not None and val != prop.default_value: + # Format value appropriately based on type + if isinstance(val, str): + props.append(f"{prop.name}=\"{val}\"") + elif isinstance(val, bool): + props.append(f"{prop.name}={str(val).lower()}") + else: + props.append(f"{prop.name}={val}") + except: + # Skip properties that can't be read + pass + + if props: + element_str += " " + " ".join(props) + + return element_str + + result = [] + + # Simple approach - just gets top-level elements + iterator = pipeline.iterate_elements() + while True: + ret, element = iterator.next() + if ret != Gst.IteratorResult.OK: + break + result.append(get_element_string(element)) + + return " ! ".join(result) + + + + def embed_results_probe(pad,info,u_data, list_add, frame_num = 0): gst_buffer = info.get_buffer() print("HEY I AM PROBING EMBEDDINGS") @@ -243,7 +336,9 @@ def create_source_bin(uri): return nbin -def run_inference(file_path): +#def run_inference(file_path): +if True: + file_path = '/home/thebears/local/source/short.mp4' os.environ.pop("DISPLAY",None) if not file_path.startswith('file://'): file_path = 'file://'+file_path @@ -421,97 +516,7 @@ def run_inference(file_path): pass # cleanup pipeline.set_state(Gst.State.NULL) - return detector_list, embed_list - -def print_pipeline_structure(pipeline): - """ - Recursively prints elements in the pipeline and their properties. - """ - if not isinstance(pipeline, Gst.Pipeline): - print("Not a valid GStreamer pipeline.") - return - - def _print_element_properties(element, indent=0): - spaces = " " * indent - print(spaces + f"Element: {element.get_name()} (Type: {element.get_factory().get_name()})") - - # Print its properties - for prop in element.list_properties(): - try: - val = element.get_property(prop.name) - if val != prop.default_value: # Display only non-default properties - print(spaces + f" - {prop.name}: {val}") - except: - pass - - def _print_pipeline_structure(element, indent=0): - spaces = " " * indent - children = element.children if hasattr(element, 'children') else [] - - if len(children) > 0: - print(spaces + f"[{element.get_name()}]") - for child in children: - _print_pipeline_structure(child, indent + 2) - else: - _print_element_properties(element, indent) - - print("\nPipeline Structure:") - print("===================") - _print_pipeline_structure(pipeline) - print("===================\n") - - -def get_detailed_pipeline_string(pipeline): - """Generate a more detailed pipeline string with properties""" - if not isinstance(pipeline, Gst.Pipeline): - return None - - def get_element_string(element): - # Get element factory name - factory = element.get_factory() - if factory: - element_str = factory.get_name() - else: - element_str = element.get_name() - - # Add properties - props = [] - for prop in element.list_properties(): - # Skip some properties that are typically not set in command line - if prop.name in ('name', 'parent'): - continue - - try: - val = element.get_property(prop.name) - if val is not None and val != prop.default_value: - # Format value appropriately based on type - if isinstance(val, str): - props.append(f"{prop.name}=\"{val}\"") - elif isinstance(val, bool): - props.append(f"{prop.name}={str(val).lower()}") - else: - props.append(f"{prop.name}={val}") - except: - # Skip properties that can't be read - pass - - if props: - element_str += " " + " ".join(props) - - return element_str - - result = [] - - # Simple approach - just gets top-level elements - iterator = pipeline.iterate_elements() - while True: - ret, element = iterator.next() - if ret != Gst.IteratorResult.OK: - break - result.append(get_element_string(element)) - - return " ! ".join(result) - +# return detector_list, embed_list diff --git a/dump.json b/dump.json index 2bde03c..e6f9476 100644 --- a/dump.json +++ b/dump.json @@ -1 +1 @@ -[[{"score": 0.7726675271987915, "label": "Passer domesticus", "left": 952.071044921875, "top": 277.29156494140625, "width": 245.0166015625, "height": 158.998779296875, "frame_number": 0, "class_id": 69}, {"score": 0.844989001750946, "label": "Agelaius phoeniceus", "left": 702.3428344726562, "top": 225.53204345703125, "width": 211.4481201171875, "height": 129.602783203125, "frame_number": 0, "class_id": 2}, {"score": 0.7775482535362244, "label": "Passer domesticus", "left": 952.0147705078125, "top": 277.20477294921875, "width": 245.08056640625, "height": 159.2000732421875, "frame_number": 1, "class_id": 69}, {"score": 0.8474487662315369, "label": "Agelaius phoeniceus", "left": 701.252685546875, "top": 225.35638427734375, "width": 212.61279296875, "height": 130.490478515625, "frame_number": 1, "class_id": 2}, {"score": 0.7692915201187134, "label": "Passer domesticus", "left": 952.0294189453125, "top": 277.06280517578125, "width": 244.1826171875, "height": 159.64208984375, "frame_number": 2, "class_id": 69}, {"score": 0.8531866669654846, "label": "Agelaius phoeniceus", "left": 700.8994750976562, "top": 225.39694213867188, "width": 212.95166015625, "height": 127.91775512695312, "frame_number": 2, "class_id": 2}, {"score": 0.8023891448974609, "label": "Passer domesticus", "left": 951.9942626953125, "top": 276.9007568359375, "width": 244.289306640625, "height": 159.26513671875, "frame_number": 3, "class_id": 69}, {"score": 0.8496067523956299, "label": "Agelaius phoeniceus", "left": 700.4541015625, "top": 225.16973876953125, "width": 212.67626953125, "height": 127.6424560546875, "frame_number": 3, "class_id": 2}, {"score": 0.7929546236991882, "label": "Passer domesticus", "left": 952.13330078125, "top": 276.91571044921875, "width": 244.17333984375, "height": 159.28515625, "frame_number": 4, "class_id": 69}, {"score": 0.8557752966880798, "label": "Agelaius phoeniceus", "left": 699.3697509765625, "top": 225.19210815429688, "width": 214.1104736328125, "height": 127.37948608398438, "frame_number": 4, "class_id": 2}, {"score": 0.7718002796173096, "label": "Passer domesticus", "left": 952.455810546875, "top": 277.0213623046875, "width": 243.99658203125, "height": 159.2984619140625, "frame_number": 5, "class_id": 69}, {"score": 0.8632484674453735, "label": "Agelaius phoeniceus", "left": 699.041748046875, "top": 225.00473022460938, "width": 214.428466796875, "height": 126.62716674804688, "frame_number": 5, "class_id": 2}, {"score": 0.79726642370224, "label": "Passer domesticus", "left": 951.884521484375, "top": 276.8973388671875, "width": 244.208251953125, "height": 159.52001953125, "frame_number": 6, "class_id": 69}, {"score": 0.8637232184410095, "label": "Agelaius phoeniceus", "left": 699.2064208984375, "top": 225.03631591796875, "width": 214.3070068359375, "height": 126.6427001953125, "frame_number": 6, "class_id": 2}, {"score": 0.7745611071586609, "label": "Passer domesticus", "left": 952.0403442382812, "top": 277.14984130859375, "width": 243.23199462890625, "height": 159.4669189453125, "frame_number": 7, "class_id": 69}, {"score": 0.8615800142288208, "label": "Agelaius phoeniceus", "left": 698.4238891601562, "top": 224.903076171875, "width": 215.478515625, "height": 126.733154296875, "frame_number": 7, "class_id": 2}, {"score": 0.7999551892280579, "label": "Passer domesticus", "left": 952.010498046875, "top": 277.1109619140625, "width": 243.580810546875, "height": 159.590087890625, "frame_number": 8, "class_id": 69}, {"score": 0.859934389591217, "label": "Agelaius phoeniceus", "left": 698.044189453125, "top": 224.79025268554688, "width": 216.706787109375, "height": 126.86587524414062, "frame_number": 8, "class_id": 2}, {"score": 0.7929943799972534, "label": "Passer domesticus", "left": 950.8526611328125, "top": 277.426025390625, "width": 244.436767578125, "height": 159.4423828125, "frame_number": 9, "class_id": 69}, {"score": 0.8631913065910339, "label": "Agelaius phoeniceus", "left": 697.3823852539062, "top": 224.70199584960938, "width": 221.5584716796875, "height": 127.17227172851562, "frame_number": 9, "class_id": 2}, {"score": 0.8015537858009338, "label": "Passer domesticus", "left": 951.9852294921875, "top": 277.5960693359375, "width": 243.194580078125, "height": 158.8065185546875, "frame_number": 10, "class_id": 69}, {"score": 0.8581196069717407, "label": "Agelaius phoeniceus", "left": 697.232421875, "top": 223.52215576171875, "width": 224.5390625, "height": 129.4383544921875, "frame_number": 10, "class_id": 2}, {"score": 0.7939319014549255, "label": "Passer domesticus", "left": 951.1990356445312, "top": 277.65179443359375, "width": 244.13031005859375, "height": 158.95166015625, "frame_number": 11, "class_id": 69}, {"score": 0.8586158156394958, "label": "Agelaius phoeniceus", "left": 697.0647583007812, "top": 223.20111083984375, "width": 225.5535888671875, "height": 129.8291015625, "frame_number": 11, "class_id": 2}, {"score": 0.769993782043457, "label": "Passer domesticus", "left": 953.3613891601562, "top": 277.9259033203125, "width": 242.13226318359375, "height": 158.5416259765625, "frame_number": 12, "class_id": 69}, {"score": 0.8623547554016113, "label": "Agelaius phoeniceus", "left": 697.4545288085938, "top": 223.001953125, "width": 224.570556640625, "height": 130.037841796875, "frame_number": 12, "class_id": 2}, {"score": 0.7361095547676086, "label": "Passer domesticus", "left": 953.167724609375, "top": 278.34552001953125, "width": 242.254638671875, "height": 158.4537353515625, "frame_number": 13, "class_id": 69}, {"score": 0.8686440587043762, "label": "Agelaius phoeniceus", "left": 696.9415893554688, "top": 222.74331665039062, "width": 225.6243896484375, "height": 129.30313110351562, "frame_number": 13, "class_id": 2}, {"score": 0.7418409585952759, "label": "Passer domesticus", "left": 953.3622436523438, "top": 278.87213134765625, "width": 241.60260009765625, "height": 157.5760498046875, "frame_number": 14, "class_id": 69}, {"score": 0.8676533699035645, "label": "Agelaius phoeniceus", "left": 696.846923828125, "top": 222.69036865234375, "width": 226.3231201171875, "height": 129.9708251953125, "frame_number": 14, "class_id": 2}, {"score": 0.7629972696304321, "label": "Passer domesticus", "left": 953.3805541992188, "top": 278.56884765625, "width": 241.73590087890625, "height": 157.79443359375, "frame_number": 15, "class_id": 69}, {"score": 0.8620957732200623, "label": "Agelaius phoeniceus", "left": 697.0010986328125, "top": 222.53765869140625, "width": 226.345703125, "height": 130.584716796875, "frame_number": 15, "class_id": 2}, {"score": 0.781523585319519, "label": "Passer domesticus", "left": 953.2913818359375, "top": 278.75823974609375, "width": 241.26123046875, "height": 157.5245361328125, "frame_number": 16, "class_id": 69}, {"score": 0.852977991104126, "label": "Agelaius phoeniceus", "left": 696.958984375, "top": 222.26559448242188, "width": 226.64794921875, "height": 131.91384887695312, "frame_number": 16, "class_id": 2}, {"score": 0.6388205885887146, "label": "Passer domesticus", "left": 970.748291015625, "top": 279.1617431640625, "width": 225.0830078125, "height": 157.215087890625, "frame_number": 17, "class_id": 69}, {"score": 0.8683550953865051, "label": "Agelaius phoeniceus", "left": 696.9841918945312, "top": 222.37039184570312, "width": 227.22802734375, "height": 131.61325073242188, "frame_number": 17, "class_id": 2}, {"score": 0.5825411677360535, "label": "Passer domesticus", "left": 975.3619384765625, "top": 279.2227783203125, "width": 218.645751953125, "height": 157.5479736328125, "frame_number": 18, "class_id": 69}, {"score": 0.8770885467529297, "label": "Agelaius phoeniceus", "left": 697.0938110351562, "top": 222.16619873046875, "width": 227.1646728515625, "height": 129.7569580078125, "frame_number": 18, "class_id": 2}, {"score": 0.6091969013214111, "label": "Passer domesticus", "left": 975.9924926757812, "top": 278.98040771484375, "width": 218.60772705078125, "height": 157.86279296875, "frame_number": 19, "class_id": 69}, {"score": 0.8831968903541565, "label": "Agelaius phoeniceus", "left": 697.2744750976562, "top": 222.03277587890625, "width": 226.88525390625, "height": 128.3935546875, "frame_number": 19, "class_id": 2}, {"score": 0.35236647725105286, "label": "Passer domesticus", "left": 976.2227783203125, "top": 278.5706787109375, "width": 218.095703125, "height": 156.1968994140625, "frame_number": 20, "class_id": 69}, {"score": 0.2812725603580475, "label": "Agelaius phoeniceus", "left": 975.0895385742188, "top": 278.74969482421875, "width": 217.84320068359375, "height": 160.9017333984375, "frame_number": 20, "class_id": 2}, {"score": 0.8867024183273315, "label": "Agelaius phoeniceus", "left": 697.3972778320312, "top": 221.92459106445312, "width": 226.563720703125, "height": 128.46310424804688, "frame_number": 20, "class_id": 2}, {"score": 0.4661272466182709, "label": "Passer domesticus", "left": 976.982177734375, "top": 279.16900634765625, "width": 216.27783203125, "height": 157.495849609375, "frame_number": 21, "class_id": 69}, {"score": 0.8799837231636047, "label": "Agelaius phoeniceus", "left": 696.9931030273438, "top": 222.03335571289062, "width": 226.908447265625, "height": 129.56509399414062, "frame_number": 21, "class_id": 2}, {"score": 0.5409456491470337, "label": "Passer domesticus", "left": 976.873291015625, "top": 278.94744873046875, "width": 216.518310546875, "height": 157.6212158203125, "frame_number": 22, "class_id": 69}, {"score": 0.8792304992675781, "label": "Agelaius phoeniceus", "left": 696.5487060546875, "top": 222.0142822265625, "width": 227.2012939453125, "height": 129.708740234375, "frame_number": 22, "class_id": 2}, {"score": 0.4282020926475525, "label": "Passer domesticus", "left": 975.9383544921875, "top": 279.021728515625, "width": 217.656005859375, "height": 156.9654541015625, "frame_number": 23, "class_id": 69}, {"score": 0.8799262642860413, "label": "Agelaius phoeniceus", "left": 697.0576782226562, "top": 222.18255615234375, "width": 227.4434814453125, "height": 129.40576171875, "frame_number": 23, "class_id": 2}, {"score": 0.6224381923675537, "label": "Passer domesticus", "left": 977.0655517578125, "top": 279.00128173828125, "width": 216.45068359375, "height": 157.237060546875, "frame_number": 24, "class_id": 69}, {"score": 0.874984622001648, "label": "Agelaius phoeniceus", "left": 697.049072265625, "top": 222.12091064453125, "width": 228.5428466796875, "height": 129.4881591796875, "frame_number": 24, "class_id": 2}, {"score": 0.7430468797683716, "label": "Passer domesticus", "left": 971.0340576171875, "top": 279.31524658203125, "width": 222.80126953125, "height": 156.6156005859375, "frame_number": 25, "class_id": 69}, {"score": 0.8614256978034973, "label": "Agelaius phoeniceus", "left": 696.9281616210938, "top": 221.21453857421875, "width": 229.3753662109375, "height": 131.1395263671875, "frame_number": 25, "class_id": 2}], []] \ No newline at end of file +[[], []] \ No newline at end of file