matrice 1.0.99120__py3-none-any.whl → 1.0.99121__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -590,11 +590,12 @@ class AssemblyLineUseCase(BaseProcessor):
590
590
  """
591
591
  return {cat: len(ids) for cat, ids in getattr(self, '_per_category_total_track_ids', {}).items()}
592
592
 
593
+
593
594
  def _format_timestamp_for_stream(self, timestamp: float) -> str:
594
595
  """Format timestamp for streams (YYYY:MM:DD HH:MM:SS format)."""
595
596
  dt = datetime.fromtimestamp(timestamp, tz=timezone.utc)
596
597
  return dt.strftime('%Y:%m:%d %H:%M:%S')
597
-
598
+
598
599
  def _format_timestamp_for_video(self, timestamp: float) -> str:
599
600
  """Format timestamp for video chunks (HH:MM:SS.ms format)."""
600
601
  hours = int(timestamp // 3600)
@@ -581,38 +581,45 @@ class CropWeedDetectionUseCase(BaseProcessor):
581
581
  """
582
582
  return {cat: len(ids) for cat, ids in getattr(self, '_per_category_total_track_ids', {}).items()}
583
583
 
584
- def _format_timestamp_for_video(self, timestamp: float) -> str:
585
- """Format timestamp for video chunks (HH:MM:SS.ms format)."""
586
- hours = int(timestamp // 3600)
587
- minutes = int((timestamp % 3600) // 60)
588
- seconds = timestamp % 60
589
- return f"{hours:02d}:{minutes:02d}:{seconds:06.2f}"
590
-
584
+
591
585
  def _format_timestamp_for_stream(self, timestamp: float) -> str:
592
586
  """Format timestamp for streams (YYYY:MM:DD HH:MM:SS format)."""
593
587
  dt = datetime.fromtimestamp(timestamp, tz=timezone.utc)
594
588
  return dt.strftime('%Y:%m:%d %H:%M:%S')
595
589
 
596
- def _get_current_timestamp_str(self, stream_info: Optional[Dict[str, Any]], precision=False) -> str:
590
+ def _format_timestamp_for_video(self, timestamp: float) -> str:
591
+ """Format timestamp for video chunks (HH:MM:SS.ms format)."""
592
+ hours = int(timestamp // 3600)
593
+ minutes = int((timestamp % 3600) // 60)
594
+ seconds = round(float(timestamp % 60),2)
595
+ return f"{hours:02d}:{minutes:02d}:{seconds:.1f}"
596
+
597
+ def _get_current_timestamp_str(self, stream_info: Optional[Dict[str, Any]], precision=False, frame_id: Optional[str]=None) -> str:
597
598
  """Get formatted current timestamp based on stream type."""
598
599
  if not stream_info:
599
600
  return "00:00:00.00"
600
-
601
601
  # is_video_chunk = stream_info.get("input_settings", {}).get("is_video_chunk", False)
602
602
  if precision:
603
- if stream_info.get("input_settings", {}).get("stream_type", "video_file") == "video_file":
604
- stream_time_str = stream_info.get("video_timestamp", "")
605
- return stream_time_str[:8]
603
+ if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
604
+ if frame_id:
605
+ start_time = int(frame_id)/stream_info.get("input_settings", {}).get("original_fps", 30)
606
+ else:
607
+ start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
608
+ stream_time_str = self._format_timestamp_for_video(start_time)
609
+ return stream_time_str
606
610
  else:
607
611
  return datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
608
612
 
609
- if stream_info.get("input_settings", {}).get("stream_type", "video_file") == "video_file":
610
- # If video format, return video timestamp
611
- stream_time_str = stream_info.get("video_timestamp", "")
612
- return stream_time_str[:8]
613
+ if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
614
+ if frame_id:
615
+ start_time = int(frame_id)/stream_info.get("input_settings", {}).get("original_fps", 30)
616
+ else:
617
+ start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
618
+ stream_time_str = self._format_timestamp_for_video(start_time)
619
+ return stream_time_str
613
620
  else:
614
621
  # For streams, use stream_time from stream_info
615
- stream_time_str = stream_info.get("stream_time", "")
622
+ stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
616
623
  if stream_time_str:
617
624
  # Parse the high precision timestamp string to get timestamp
618
625
  try:
@@ -631,23 +638,20 @@ class CropWeedDetectionUseCase(BaseProcessor):
631
638
  """Get formatted start timestamp for 'TOTAL SINCE' based on stream type."""
632
639
  if not stream_info:
633
640
  return "00:00:00"
634
-
635
- is_video_chunk = stream_info.get("input_settings", {}).get("is_video_chunk", False)
636
641
  if precision:
637
- if stream_info.get("input_settings", {}).get("stream_type", "video_file") == "video_file":
642
+ if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
638
643
  return "00:00:00"
639
644
  else:
640
645
  return datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
641
646
 
642
-
643
- if stream_info.get("input_settings", {}).get("stream_type", "video_file") == "video_file":
647
+ if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
644
648
  # If video format, start from 00:00:00
645
649
  return "00:00:00"
646
650
  else:
647
651
  # For streams, use tracking start time or current time with minutes/seconds reset
648
652
  if self._tracking_start_time is None:
649
653
  # Try to extract timestamp from stream_time string
650
- stream_time_str = stream_info.get("stream_time", "")
654
+ stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
651
655
  if stream_time_str:
652
656
  try:
653
657
  # Remove " UTC" suffix and parse
@@ -665,6 +669,7 @@ class CropWeedDetectionUseCase(BaseProcessor):
665
669
  dt = dt.replace(minute=0, second=0, microsecond=0)
666
670
  return dt.strftime('%Y:%m:%d %H:%M:%S')
667
671
 
672
+
668
673
  def _count_categories(self, detections: list, config: CropWeedDetectionConfig) -> dict:
669
674
  """
670
675
  Count the number of detections per category and return a summary dict.
@@ -578,11 +578,12 @@ class EmergencyVehicleUseCase(BaseProcessor):
578
578
  """
579
579
  return {cat: len(ids) for cat, ids in getattr(self, '_per_category_total_track_ids', {}).items()}
580
580
 
581
+
581
582
  def _format_timestamp_for_stream(self, timestamp: float) -> str:
582
583
  """Format timestamp for streams (YYYY:MM:DD HH:MM:SS format)."""
583
584
  dt = datetime.fromtimestamp(timestamp, tz=timezone.utc)
584
585
  return dt.strftime('%Y:%m:%d %H:%M:%S')
585
-
586
+
586
587
  def _format_timestamp_for_video(self, timestamp: float) -> str:
587
588
  """Format timestamp for video chunks (HH:MM:SS.ms format)."""
588
589
  hours = int(timestamp // 3600)
@@ -585,38 +585,45 @@ class FashionDetectionUseCase(BaseProcessor):
585
585
  """
586
586
  return {cat: len(ids) for cat, ids in getattr(self, '_per_category_total_track_ids', {}).items()}
587
587
 
588
- def _format_timestamp_for_video(self, timestamp: float) -> str:
589
- """Format timestamp for video chunks (HH:MM:SS.ms format)."""
590
- hours = int(timestamp // 3600)
591
- minutes = int((timestamp % 3600) // 60)
592
- seconds = timestamp % 60
593
- return f"{hours:02d}:{minutes:02d}:{seconds:06.2f}"
594
588
 
595
589
  def _format_timestamp_for_stream(self, timestamp: float) -> str:
596
590
  """Format timestamp for streams (YYYY:MM:DD HH:MM:SS format)."""
597
591
  dt = datetime.fromtimestamp(timestamp, tz=timezone.utc)
598
592
  return dt.strftime('%Y:%m:%d %H:%M:%S')
599
593
 
600
- def _get_current_timestamp_str(self, stream_info: Optional[Dict[str, Any]], precision=False) -> str:
594
+ def _format_timestamp_for_video(self, timestamp: float) -> str:
595
+ """Format timestamp for video chunks (HH:MM:SS.ms format)."""
596
+ hours = int(timestamp // 3600)
597
+ minutes = int((timestamp % 3600) // 60)
598
+ seconds = round(float(timestamp % 60),2)
599
+ return f"{hours:02d}:{minutes:02d}:{seconds:.1f}"
600
+
601
+ def _get_current_timestamp_str(self, stream_info: Optional[Dict[str, Any]], precision=False, frame_id: Optional[str]=None) -> str:
601
602
  """Get formatted current timestamp based on stream type."""
602
603
  if not stream_info:
603
604
  return "00:00:00.00"
604
-
605
605
  # is_video_chunk = stream_info.get("input_settings", {}).get("is_video_chunk", False)
606
606
  if precision:
607
- if stream_info.get("input_settings", {}).get("stream_type", "video_file") == "video_file":
608
- stream_time_str = stream_info.get("video_timestamp", "")
609
- return stream_time_str[:8]
607
+ if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
608
+ if frame_id:
609
+ start_time = int(frame_id)/stream_info.get("input_settings", {}).get("original_fps", 30)
610
+ else:
611
+ start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
612
+ stream_time_str = self._format_timestamp_for_video(start_time)
613
+ return stream_time_str
610
614
  else:
611
615
  return datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
612
616
 
613
- if stream_info.get("input_settings", {}).get("stream_type", "video_file") == "video_file":
614
- # If video format, return video timestamp
615
- stream_time_str = stream_info.get("video_timestamp", "")
616
- return stream_time_str[:8]
617
+ if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
618
+ if frame_id:
619
+ start_time = int(frame_id)/stream_info.get("input_settings", {}).get("original_fps", 30)
620
+ else:
621
+ start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
622
+ stream_time_str = self._format_timestamp_for_video(start_time)
623
+ return stream_time_str
617
624
  else:
618
625
  # For streams, use stream_time from stream_info
619
- stream_time_str = stream_info.get("stream_time", "")
626
+ stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
620
627
  if stream_time_str:
621
628
  # Parse the high precision timestamp string to get timestamp
622
629
  try:
@@ -635,23 +642,20 @@ class FashionDetectionUseCase(BaseProcessor):
635
642
  """Get formatted start timestamp for 'TOTAL SINCE' based on stream type."""
636
643
  if not stream_info:
637
644
  return "00:00:00"
638
-
639
- is_video_chunk = stream_info.get("input_settings", {}).get("is_video_chunk", False)
640
645
  if precision:
641
- if stream_info.get("input_settings", {}).get("stream_type", "video_file") == "video_file":
646
+ if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
642
647
  return "00:00:00"
643
648
  else:
644
649
  return datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
645
650
 
646
-
647
- if stream_info.get("input_settings", {}).get("stream_type", "video_file") == "video_file":
651
+ if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
648
652
  # If video format, start from 00:00:00
649
653
  return "00:00:00"
650
654
  else:
651
655
  # For streams, use tracking start time or current time with minutes/seconds reset
652
656
  if self._tracking_start_time is None:
653
657
  # Try to extract timestamp from stream_time string
654
- stream_time_str = stream_info.get("stream_time", "")
658
+ stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
655
659
  if stream_time_str:
656
660
  try:
657
661
  # Remove " UTC" suffix and parse
@@ -669,6 +673,7 @@ class FashionDetectionUseCase(BaseProcessor):
669
673
  dt = dt.replace(minute=0, second=0, microsecond=0)
670
674
  return dt.strftime('%Y:%m:%d %H:%M:%S')
671
675
 
676
+
672
677
  def _count_categories(self, detections: list, config: FashionDetectionConfig) -> dict:
673
678
  """
674
679
  Count the number of detections per category and return a summary dict.
@@ -581,38 +581,45 @@ class GenderDetectionUseCase(BaseProcessor):
581
581
  """
582
582
  return {cat: len(ids) for cat, ids in getattr(self, '_per_category_total_track_ids', {}).items()}
583
583
 
584
- def _format_timestamp_for_video(self, timestamp: float) -> str:
585
- """Format timestamp for video chunks (HH:MM:SS.ms format)."""
586
- hours = int(timestamp // 3600)
587
- minutes = int((timestamp % 3600) // 60)
588
- seconds = timestamp % 60
589
- return f"{hours:02d}:{minutes:02d}:{seconds:06.2f}"
590
584
 
591
585
  def _format_timestamp_for_stream(self, timestamp: float) -> str:
592
586
  """Format timestamp for streams (YYYY:MM:DD HH:MM:SS format)."""
593
587
  dt = datetime.fromtimestamp(timestamp, tz=timezone.utc)
594
588
  return dt.strftime('%Y:%m:%d %H:%M:%S')
595
589
 
596
- def _get_current_timestamp_str(self, stream_info: Optional[Dict[str, Any]], precision=False) -> str:
590
+ def _format_timestamp_for_video(self, timestamp: float) -> str:
591
+ """Format timestamp for video chunks (HH:MM:SS.ms format)."""
592
+ hours = int(timestamp // 3600)
593
+ minutes = int((timestamp % 3600) // 60)
594
+ seconds = round(float(timestamp % 60),2)
595
+ return f"{hours:02d}:{minutes:02d}:{seconds:.1f}"
596
+
597
+ def _get_current_timestamp_str(self, stream_info: Optional[Dict[str, Any]], precision=False, frame_id: Optional[str]=None) -> str:
597
598
  """Get formatted current timestamp based on stream type."""
598
599
  if not stream_info:
599
600
  return "00:00:00.00"
600
-
601
601
  # is_video_chunk = stream_info.get("input_settings", {}).get("is_video_chunk", False)
602
602
  if precision:
603
- if stream_info.get("input_settings", {}).get("stream_type", "video_file") == "video_file":
604
- stream_time_str = stream_info.get("video_timestamp", "")
605
- return stream_time_str[:8]
603
+ if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
604
+ if frame_id:
605
+ start_time = int(frame_id)/stream_info.get("input_settings", {}).get("original_fps", 30)
606
+ else:
607
+ start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
608
+ stream_time_str = self._format_timestamp_for_video(start_time)
609
+ return stream_time_str
606
610
  else:
607
611
  return datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
608
612
 
609
- if stream_info.get("input_settings", {}).get("stream_type", "video_file") == "video_file":
610
- # If video format, return video timestamp
611
- stream_time_str = stream_info.get("video_timestamp", "")
612
- return stream_time_str[:8]
613
+ if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
614
+ if frame_id:
615
+ start_time = int(frame_id)/stream_info.get("input_settings", {}).get("original_fps", 30)
616
+ else:
617
+ start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
618
+ stream_time_str = self._format_timestamp_for_video(start_time)
619
+ return stream_time_str
613
620
  else:
614
621
  # For streams, use stream_time from stream_info
615
- stream_time_str = stream_info.get("stream_time", "")
622
+ stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
616
623
  if stream_time_str:
617
624
  # Parse the high precision timestamp string to get timestamp
618
625
  try:
@@ -631,23 +638,20 @@ class GenderDetectionUseCase(BaseProcessor):
631
638
  """Get formatted start timestamp for 'TOTAL SINCE' based on stream type."""
632
639
  if not stream_info:
633
640
  return "00:00:00"
634
-
635
- is_video_chunk = stream_info.get("input_settings", {}).get("is_video_chunk", False)
636
641
  if precision:
637
- if stream_info.get("input_settings", {}).get("stream_type", "video_file") == "video_file":
642
+ if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
638
643
  return "00:00:00"
639
644
  else:
640
645
  return datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
641
646
 
642
-
643
- if stream_info.get("input_settings", {}).get("stream_type", "video_file") == "video_file":
647
+ if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
644
648
  # If video format, start from 00:00:00
645
649
  return "00:00:00"
646
650
  else:
647
651
  # For streams, use tracking start time or current time with minutes/seconds reset
648
652
  if self._tracking_start_time is None:
649
653
  # Try to extract timestamp from stream_time string
650
- stream_time_str = stream_info.get("stream_time", "")
654
+ stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
651
655
  if stream_time_str:
652
656
  try:
653
657
  # Remove " UTC" suffix and parse
@@ -665,6 +669,7 @@ class GenderDetectionUseCase(BaseProcessor):
665
669
  dt = dt.replace(minute=0, second=0, microsecond=0)
666
670
  return dt.strftime('%Y:%m:%d %H:%M:%S')
667
671
 
672
+
668
673
  def _count_categories(self, detections: list, config: GenderDetectionConfig) -> dict:
669
674
  """
670
675
  Count the number of detections per category and return a summary dict.
@@ -572,38 +572,45 @@ class PriceTagUseCase(BaseProcessor):
572
572
  """
573
573
  return {cat: len(ids) for cat, ids in getattr(self, '_per_category_total_track_ids', {}).items()}
574
574
 
575
- def _format_timestamp_for_video(self, timestamp: float) -> str:
576
- """Format timestamp for video chunks (HH:MM:SS.ms format)."""
577
- hours = int(timestamp // 3600)
578
- minutes = int((timestamp % 3600) // 60)
579
- seconds = timestamp % 60
580
- return f"{hours:02d}:{minutes:02d}:{seconds:06.2f}"
581
575
 
582
576
  def _format_timestamp_for_stream(self, timestamp: float) -> str:
583
577
  """Format timestamp for streams (YYYY:MM:DD HH:MM:SS format)."""
584
578
  dt = datetime.fromtimestamp(timestamp, tz=timezone.utc)
585
579
  return dt.strftime('%Y:%m:%d %H:%M:%S')
586
580
 
587
- def _get_current_timestamp_str(self, stream_info: Optional[Dict[str, Any]], precision=False) -> str:
581
+ def _format_timestamp_for_video(self, timestamp: float) -> str:
582
+ """Format timestamp for video chunks (HH:MM:SS.ms format)."""
583
+ hours = int(timestamp // 3600)
584
+ minutes = int((timestamp % 3600) // 60)
585
+ seconds = round(float(timestamp % 60),2)
586
+ return f"{hours:02d}:{minutes:02d}:{seconds:.1f}"
587
+
588
+ def _get_current_timestamp_str(self, stream_info: Optional[Dict[str, Any]], precision=False, frame_id: Optional[str]=None) -> str:
588
589
  """Get formatted current timestamp based on stream type."""
589
590
  if not stream_info:
590
591
  return "00:00:00.00"
591
-
592
592
  # is_video_chunk = stream_info.get("input_settings", {}).get("is_video_chunk", False)
593
593
  if precision:
594
- if stream_info.get("input_settings", {}).get("stream_type", "video_file") == "video_file":
595
- stream_time_str = stream_info.get("video_timestamp", "")
596
- return stream_time_str[:8]
594
+ if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
595
+ if frame_id:
596
+ start_time = int(frame_id)/stream_info.get("input_settings", {}).get("original_fps", 30)
597
+ else:
598
+ start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
599
+ stream_time_str = self._format_timestamp_for_video(start_time)
600
+ return stream_time_str
597
601
  else:
598
602
  return datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
599
603
 
600
- if stream_info.get("input_settings", {}).get("stream_type", "video_file") == "video_file":
601
- # If video format, return video timestamp
602
- stream_time_str = stream_info.get("video_timestamp", "")
603
- return stream_time_str[:8]
604
+ if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
605
+ if frame_id:
606
+ start_time = int(frame_id)/stream_info.get("input_settings", {}).get("original_fps", 30)
607
+ else:
608
+ start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
609
+ stream_time_str = self._format_timestamp_for_video(start_time)
610
+ return stream_time_str
604
611
  else:
605
612
  # For streams, use stream_time from stream_info
606
- stream_time_str = stream_info.get("stream_time", "")
613
+ stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
607
614
  if stream_time_str:
608
615
  # Parse the high precision timestamp string to get timestamp
609
616
  try:
@@ -622,23 +629,20 @@ class PriceTagUseCase(BaseProcessor):
622
629
  """Get formatted start timestamp for 'TOTAL SINCE' based on stream type."""
623
630
  if not stream_info:
624
631
  return "00:00:00"
625
-
626
- is_video_chunk = stream_info.get("input_settings", {}).get("is_video_chunk", False)
627
632
  if precision:
628
- if stream_info.get("input_settings", {}).get("stream_type", "video_file") == "video_file":
633
+ if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
629
634
  return "00:00:00"
630
635
  else:
631
636
  return datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
632
637
 
633
-
634
- if stream_info.get("input_settings", {}).get("stream_type", "video_file") == "video_file":
638
+ if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
635
639
  # If video format, start from 00:00:00
636
640
  return "00:00:00"
637
641
  else:
638
642
  # For streams, use tracking start time or current time with minutes/seconds reset
639
643
  if self._tracking_start_time is None:
640
644
  # Try to extract timestamp from stream_time string
641
- stream_time_str = stream_info.get("stream_time", "")
645
+ stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
642
646
  if stream_time_str:
643
647
  try:
644
648
  # Remove " UTC" suffix and parse
@@ -656,6 +660,7 @@ class PriceTagUseCase(BaseProcessor):
656
660
  dt = dt.replace(minute=0, second=0, microsecond=0)
657
661
  return dt.strftime('%Y:%m:%d %H:%M:%S')
658
662
 
663
+
659
664
  def _count_categories(self, detections: list, config: PriceTagConfig) -> dict:
660
665
  """
661
666
  Count the number of detections per category and return a summary dict.
@@ -595,6 +595,8 @@ class WindmillMaintenanceUseCase(BaseProcessor):
595
595
  Return total unique track_id count for each category.
596
596
  """
597
597
  return {cat: len(ids) for cat, ids in getattr(self, '_per_category_total_track_ids', {}).items()}
598
+
599
+
598
600
  def _format_timestamp_for_stream(self, timestamp: float) -> str:
599
601
  """Format timestamp for streams (YYYY:MM:DD HH:MM:SS format)."""
600
602
  dt = datetime.fromtimestamp(timestamp, tz=timezone.utc)
@@ -681,7 +683,8 @@ class WindmillMaintenanceUseCase(BaseProcessor):
681
683
  # Reset minutes and seconds to 00:00 for "TOTAL SINCE" format
682
684
  dt = dt.replace(minute=0, second=0, microsecond=0)
683
685
  return dt.strftime('%Y:%m:%d %H:%M:%S')
684
-
686
+
687
+
685
688
  def _count_categories(self, detections: list, config: WindmillMaintenanceConfig) -> dict:
686
689
  """
687
690
  Count the number of detections per category and return a summary dict.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matrice
3
- Version: 1.0.99120
3
+ Version: 1.0.99121
4
4
  Summary: SDK for connecting to matrice.ai services
5
5
  Home-page: https://github.com/matrice-ai/python-sdk
6
6
  Author: Matrice.ai
@@ -156,7 +156,7 @@ matrice/deploy/utils/post_processing/usecases/__init__.py,sha256=Nb13P5IZSs7tl9j
156
156
  matrice/deploy/utils/post_processing/usecases/advanced_customer_service.py,sha256=ELt5euxr6P4X2s8-YGngmj27QscOHefjOsx3774sNFk,75914
157
157
  matrice/deploy/utils/post_processing/usecases/age_detection.py,sha256=cgOIx2zqPd_OWQMfTDV_4HSlvXlI8eKcZSEZ85SnZWA,35263
158
158
  matrice/deploy/utils/post_processing/usecases/anti_spoofing_detection.py,sha256=XdtDdXGzZMLQdWcoOoiE5t4LPYHhgOtJ7tZCNlq1A2E,31329
159
- matrice/deploy/utils/post_processing/usecases/assembly_line_detection.py,sha256=aWvdUesfVSDeuG5k5J0pmbg-xUp_tS_A6TyZGSsPeDI,39657
159
+ matrice/deploy/utils/post_processing/usecases/assembly_line_detection.py,sha256=b87TAv5718l2E22BIKK4VbHdNR1gJA9jMR9lE0x4H4U,39654
160
160
  matrice/deploy/utils/post_processing/usecases/banana_defect_detection.py,sha256=OgkqYP8-LkCt3bg4x7V0VvlqvSE8I38SeKr_Wtb63B8,29532
161
161
  matrice/deploy/utils/post_processing/usecases/basic_counting_tracking.py,sha256=-vr2z0J-qMh5wOoGubqeTWPttJ4NOYtGqKSV-_8PaKw,28311
162
162
  matrice/deploy/utils/post_processing/usecases/blood_cancer_detection_img.py,sha256=Ay_0OC9gM1dTQHWC5wL8XLZjl7ulHzd0zdhNzGH4JKU,42128
@@ -167,18 +167,18 @@ matrice/deploy/utils/post_processing/usecases/child_monitoring.py,sha256=pHt3uth
167
167
  matrice/deploy/utils/post_processing/usecases/color_detection.py,sha256=Z8-akjy8a7f8YyiOzXu_Zi1Km30v-TRrymDqQOPpJ_8,43277
168
168
  matrice/deploy/utils/post_processing/usecases/color_map_utils.py,sha256=SP-AEVcjLmL8rxblu-ixqUJC2fqlcr7ab4hWo4Fcr_k,2677
169
169
  matrice/deploy/utils/post_processing/usecases/concrete_crack_detection.py,sha256=jl3INFXNjEGS5qha1NP9xrDYPMXNlacKI1Z98zFjo0Q,34358
170
- matrice/deploy/utils/post_processing/usecases/crop_weed_detection.py,sha256=fcQx05Y5guYP6x_kbpw5jXFPKwwPr7Un_nY2eGD5jR4,39077
170
+ matrice/deploy/utils/post_processing/usecases/crop_weed_detection.py,sha256=GLgKjq0qCJzSjgleHvBvanaEjj4nREa6t_4GkeSAUYA,39656
171
171
  matrice/deploy/utils/post_processing/usecases/customer_service.py,sha256=UWS83qxguyAyhh8a0JF5QH9DtKxO8I-gI2BPOjLPxBw,44642
172
172
  matrice/deploy/utils/post_processing/usecases/defect_detection_products.py,sha256=flvTWv6vxa3q4zXD8_e8TW0pqNE5z3LIuvU9ceVKuXg,34481
173
173
  matrice/deploy/utils/post_processing/usecases/distracted_driver_detection.py,sha256=lkBc7zcq_9WPvxdIiCgA8ESTpnkMxtcIBWVWEzB_IV8,38044
174
- matrice/deploy/utils/post_processing/usecases/emergency_vehicle_detection.py,sha256=lTTN7Ew7qyG0X-e3mA4QqE3WHpwLyV7366H0VX8zgww,39312
174
+ matrice/deploy/utils/post_processing/usecases/emergency_vehicle_detection.py,sha256=xse9f_DpO1VK-9Lv79ZmzblO8UaWWtSbAXd3R41NTSw,39309
175
175
  matrice/deploy/utils/post_processing/usecases/face_emotion.py,sha256=eRfqBdryB0uNoOlz_y-JMuZL1BhPWrI-odqgx_9LT7s,39132
176
- matrice/deploy/utils/post_processing/usecases/fashion_detection.py,sha256=-0X-HNwkPKiNl-95ZIytwwKNT42GpenakJdcfLD4gWY,39216
176
+ matrice/deploy/utils/post_processing/usecases/fashion_detection.py,sha256=yB0ggoY1Lm7TGf0FSNMwQgSS24qXmd3C3GwPaMdExCU,39791
177
177
  matrice/deploy/utils/post_processing/usecases/field_mapping.py,sha256=JDwYX8pd2W-waDvBh98Y_o_uchJu7wEYbFxOliA4Iq4,39822
178
178
  matrice/deploy/utils/post_processing/usecases/fire_detection.py,sha256=rLaUvU5ygvjGbOmjncEJCl_Oe52SRycS1Ar23LbRssM,32863
179
179
  matrice/deploy/utils/post_processing/usecases/flare_analysis.py,sha256=90UmC5ji12VvQa1OcQdXZIm9JYN9LOLLjm8JxCREncM,43267
180
180
  matrice/deploy/utils/post_processing/usecases/flower_segmentation.py,sha256=4I7qMx9Ztxg_hy9KTVX-3qBhAN-QwDt_Yigf9fFjLus,52017
181
- matrice/deploy/utils/post_processing/usecases/gender_detection.py,sha256=pz_AA_Ft82mHuRuGxdfUp3MrhDOAiXX-DLiAw5eKpIg,38865
181
+ matrice/deploy/utils/post_processing/usecases/gender_detection.py,sha256=UTbS_TUltupJ27_-oe8MtG0WC3HyjvtiKeX-hRIperI,39440
182
182
  matrice/deploy/utils/post_processing/usecases/leaf.py,sha256=cwgB1ZNxkQFtkk-thSJrkXOGou1ghJr1kqtopb3sLD4,37036
183
183
  matrice/deploy/utils/post_processing/usecases/leaf_disease.py,sha256=bkiLccTdf4KUq3he4eCpBlKXb5exr-WBhQ_oWQ7os68,36225
184
184
  matrice/deploy/utils/post_processing/usecases/license_plate_detection.py,sha256=-HWqEL5jn7KXI20fTmKLHn3kGMopiDLngcEpeVbvGpE,34680
@@ -190,7 +190,7 @@ matrice/deploy/utils/post_processing/usecases/people_counting.py,sha256=mDJOwcrs
190
190
  matrice/deploy/utils/post_processing/usecases/plaque_segmentation_img.py,sha256=d__a0PkkObYVoC-Q5-2bFVfeyKnQHtB5xVAKVOCeFyk,41925
191
191
  matrice/deploy/utils/post_processing/usecases/pothole_segmentation.py,sha256=6Mv8SoEE5CGItY7S0g-SY5Lb3DV-WWVMlpEp04a86a8,43197
192
192
  matrice/deploy/utils/post_processing/usecases/ppe_compliance.py,sha256=koLwrPtLerXM9vV-Lk_nj3BWVzZXcGtenpFm79Rl7l0,30147
193
- matrice/deploy/utils/post_processing/usecases/price_tag_detection.py,sha256=CzjpvRsYkRfbjsFBufGIyyfutkEToR0wSx1Y6j81_Hc,38639
193
+ matrice/deploy/utils/post_processing/usecases/price_tag_detection.py,sha256=evMC8pU_bVw5TbKUz3_LxyGSG6Yo0RGlrVhjBkHwUIc,39214
194
194
  matrice/deploy/utils/post_processing/usecases/road_lane_detection.py,sha256=vTe0svmI7ztuSSh--Orv4MAFvP7DIkd2AA_Kzq67LeA,27050
195
195
  matrice/deploy/utils/post_processing/usecases/shelf_inventory_detection.py,sha256=HvDWWz3O5XsmWoyKduQToiS8epKz2Hn7DQ7ZgsheleA,28558
196
196
  matrice/deploy/utils/post_processing/usecases/shoplifting_detection.py,sha256=zqeV_ARV5gJqMY2sJGBjlU6UOb0SthGGbC8UNj_mycs,34701
@@ -205,7 +205,7 @@ matrice/deploy/utils/post_processing/usecases/vehicle_monitoring.py,sha256=-Q4x0
205
205
  matrice/deploy/utils/post_processing/usecases/warehouse_object_segmentation.py,sha256=5uZXTJL_A3tUEN08T-_ZQpUoJ9gqbuuMc4z2mT4sMnQ,43753
206
206
  matrice/deploy/utils/post_processing/usecases/weapon_detection.py,sha256=ait-RCgmu3BH6tNAl9nZgVXO0pSu4ETjtJzN7x6ZFRY,29365
207
207
  matrice/deploy/utils/post_processing/usecases/weld_defect_detection.py,sha256=hjpe2dKnlzGYWM42bfuO-sJAslAs6H3cY4G5xEDeTqg,26721
208
- matrice/deploy/utils/post_processing/usecases/windmill_maintenance.py,sha256=OVY2gbSvb7RLtxcoLsDW9zA1nnvTkE23GMZpRnLolEs,40495
208
+ matrice/deploy/utils/post_processing/usecases/windmill_maintenance.py,sha256=G1eqo3Z-HYmGJ6oeZYrpZwhpvqQ9Lc_T-6S7BLBXHeA,40498
209
209
  matrice/deploy/utils/post_processing/usecases/wound_segmentation.py,sha256=7Nbc7zUQUKdXTSv8XpPuAZLIU3Mr1RU1KyO_D3thoGk,38289
210
210
  matrice/deploy/utils/post_processing/utils/__init__.py,sha256=A49ksdXL7gRwBbIUwnU2ueFDGA67qVnEW_9lItOibtk,3626
211
211
  matrice/deploy/utils/post_processing/utils/advanced_counting_utils.py,sha256=D6jlZNRCfPtfG8COv3AMCbCfZf4_DK9rFhwzVJEYjpg,19152
@@ -225,8 +225,8 @@ matrice/deployment/camera_manager.py,sha256=ReBZqm1CNXRImKcbcZ4uWAT3TUWkof1D28oB
225
225
  matrice/deployment/deployment.py,sha256=PLIUD-PxTaC2Zxb3Y12wUddsryV-OJetjCjLoSUh7S4,48103
226
226
  matrice/deployment/inference_pipeline.py,sha256=bXLgd29ViA7o0c7YWLFJl1otBUQfTPb61jS6VawQB0Y,37918
227
227
  matrice/deployment/streaming_gateway_manager.py,sha256=w5swGsuFVfZIdOm2ZuBHRHlRdYYJMLopLsf2gb91lQ8,20946
228
- matrice-1.0.99120.dist-info/licenses/LICENSE.txt,sha256=2bm9uFabQZ3Ykb_SaSU_uUbAj2-htc6WJQmS_65qD00,1073
229
- matrice-1.0.99120.dist-info/METADATA,sha256=RpltS6SiXXIs8q5ZV0-XL-wiCQ1cGoQd2VdEO4FDOZs,14624
230
- matrice-1.0.99120.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
231
- matrice-1.0.99120.dist-info/top_level.txt,sha256=P97js8ur6o5ClRqMH3Cjoab_NqbJ6sOQ3rJmVzKBvMc,8
232
- matrice-1.0.99120.dist-info/RECORD,,
228
+ matrice-1.0.99121.dist-info/licenses/LICENSE.txt,sha256=2bm9uFabQZ3Ykb_SaSU_uUbAj2-htc6WJQmS_65qD00,1073
229
+ matrice-1.0.99121.dist-info/METADATA,sha256=EBXVbD51fwqg16LEqYK0anItHUEvAcHQOSSeBU0PWMs,14624
230
+ matrice-1.0.99121.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
231
+ matrice-1.0.99121.dist-info/top_level.txt,sha256=P97js8ur6o5ClRqMH3Cjoab_NqbJ6sOQ3rJmVzKBvMc,8
232
+ matrice-1.0.99121.dist-info/RECORD,,