matrice-analytics 0.1.43__py3-none-any.whl → 0.1.44__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.
Potentially problematic release.
This version of matrice-analytics might be problematic. Click here for more details.
- matrice_analytics/post_processing/face_reg/face_recognition.py +70 -35
- matrice_analytics/post_processing/usecases/color_detection.py +89 -54
- matrice_analytics/post_processing/usecases/fire_detection.py +89 -54
- matrice_analytics/post_processing/usecases/license_plate_monitoring.py +81 -46
- matrice_analytics/post_processing/usecases/people_counting.py +29 -28
- matrice_analytics/post_processing/usecases/vehicle_monitoring.py +89 -54
- {matrice_analytics-0.1.43.dist-info → matrice_analytics-0.1.44.dist-info}/METADATA +1 -1
- {matrice_analytics-0.1.43.dist-info → matrice_analytics-0.1.44.dist-info}/RECORD +11 -11
- {matrice_analytics-0.1.43.dist-info → matrice_analytics-0.1.44.dist-info}/WHEEL +0 -0
- {matrice_analytics-0.1.43.dist-info → matrice_analytics-0.1.44.dist-info}/licenses/LICENSE.txt +0 -0
- {matrice_analytics-0.1.43.dist-info → matrice_analytics-0.1.44.dist-info}/top_level.txt +0 -0
|
@@ -1743,56 +1743,57 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
1743
1743
|
return f"{hours:02d}:{minutes:02d}:{seconds:.1f}"
|
|
1744
1744
|
|
|
1745
1745
|
def _format_timestamp(self, timestamp: Any) -> str:
|
|
1746
|
-
"""Format a timestamp
|
|
1746
|
+
"""Format a timestamp to match the current timestamp format: YYYY:MM:DD HH:MM:SS.
|
|
1747
1747
|
|
|
1748
1748
|
The input can be either:
|
|
1749
|
-
1. A numeric Unix timestamp (``float`` / ``int``) – it will
|
|
1750
|
-
|
|
1751
|
-
2. A string already following the same layout.
|
|
1749
|
+
1. A numeric Unix timestamp (``float`` / ``int``) – it will be converted to datetime.
|
|
1750
|
+
2. A string in the format ``YYYY-MM-DD-HH:MM:SS.ffffff UTC``.
|
|
1752
1751
|
|
|
1753
|
-
The returned value
|
|
1754
|
-
the fractional seconds portion to **exactly two digits**.
|
|
1752
|
+
The returned value will be in the format: YYYY:MM:DD HH:MM:SS (no milliseconds, no UTC suffix).
|
|
1755
1753
|
|
|
1756
1754
|
Example
|
|
1757
1755
|
-------
|
|
1758
|
-
>>> self._format_timestamp("2025-
|
|
1759
|
-
'2025
|
|
1756
|
+
>>> self._format_timestamp("2025-10-27-19:31:20.187574 UTC")
|
|
1757
|
+
'2025:10:27 19:31:20'
|
|
1760
1758
|
"""
|
|
1761
1759
|
|
|
1762
|
-
# Convert numeric timestamps to
|
|
1760
|
+
# Convert numeric timestamps to datetime first
|
|
1763
1761
|
if isinstance(timestamp, (int, float)):
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
)
|
|
1762
|
+
dt = datetime.fromtimestamp(timestamp, timezone.utc)
|
|
1763
|
+
return dt.strftime('%Y:%m:%d %H:%M:%S')
|
|
1767
1764
|
|
|
1768
1765
|
# Ensure we are working with a string from here on
|
|
1769
1766
|
if not isinstance(timestamp, str):
|
|
1770
1767
|
return str(timestamp)
|
|
1771
1768
|
|
|
1772
|
-
#
|
|
1773
|
-
|
|
1774
|
-
return timestamp
|
|
1769
|
+
# Remove ' UTC' suffix if present
|
|
1770
|
+
timestamp_clean = timestamp.replace(' UTC', '').strip()
|
|
1775
1771
|
|
|
1776
|
-
#
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
# Separate fractional digits from the suffix (typically ' UTC')
|
|
1780
|
-
if ' ' in fractional_and_suffix:
|
|
1781
|
-
fractional_part, suffix = fractional_and_suffix.split(' ', 1)
|
|
1782
|
-
suffix = ' ' + suffix # Re-attach the space removed by split
|
|
1783
|
-
else:
|
|
1784
|
-
fractional_part, suffix = fractional_and_suffix, ''
|
|
1772
|
+
# Remove milliseconds if present (everything after the last dot)
|
|
1773
|
+
if '.' in timestamp_clean:
|
|
1774
|
+
timestamp_clean = timestamp_clean.split('.')[0]
|
|
1785
1775
|
|
|
1786
|
-
#
|
|
1787
|
-
|
|
1776
|
+
# Parse the timestamp string and convert to desired format
|
|
1777
|
+
try:
|
|
1778
|
+
# Handle format: YYYY-MM-DD-HH:MM:SS
|
|
1779
|
+
if timestamp_clean.count('-') >= 2:
|
|
1780
|
+
# Replace first two dashes with colons for date part, third with space
|
|
1781
|
+
parts = timestamp_clean.split('-')
|
|
1782
|
+
if len(parts) >= 4:
|
|
1783
|
+
# parts = ['2025', '10', '27', '19:31:20']
|
|
1784
|
+
formatted = f"{parts[0]}:{parts[1]}:{parts[2]} {'-'.join(parts[3:])}"
|
|
1785
|
+
return formatted
|
|
1786
|
+
except Exception:
|
|
1787
|
+
pass
|
|
1788
1788
|
|
|
1789
|
-
return
|
|
1789
|
+
# If parsing fails, return the cleaned string as-is
|
|
1790
|
+
return timestamp_clean
|
|
1790
1791
|
|
|
1791
1792
|
def _get_current_timestamp_str(self, stream_info: Optional[Dict[str, Any]], precision=False, frame_id: Optional[str]=None) -> str:
|
|
1792
1793
|
"""Get formatted current timestamp based on stream type."""
|
|
1794
|
+
|
|
1793
1795
|
if not stream_info:
|
|
1794
1796
|
return "00:00:00.00"
|
|
1795
|
-
|
|
1796
1797
|
if precision:
|
|
1797
1798
|
if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
|
|
1798
1799
|
if frame_id:
|
|
@@ -1801,7 +1802,6 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
1801
1802
|
start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
|
|
1802
1803
|
stream_time_str = self._format_timestamp_for_video(start_time)
|
|
1803
1804
|
|
|
1804
|
-
|
|
1805
1805
|
return self._format_timestamp(stream_info.get("input_settings", {}).get("stream_time", "NA"))
|
|
1806
1806
|
else:
|
|
1807
1807
|
return datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
@@ -1813,7 +1813,8 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
1813
1813
|
start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
|
|
1814
1814
|
|
|
1815
1815
|
stream_time_str = self._format_timestamp_for_video(start_time)
|
|
1816
|
-
|
|
1816
|
+
|
|
1817
|
+
|
|
1817
1818
|
return self._format_timestamp(stream_info.get("input_settings", {}).get("stream_time", "NA"))
|
|
1818
1819
|
else:
|
|
1819
1820
|
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
@@ -1835,23 +1836,57 @@ class FaceRecognitionEmbeddingUseCase(BaseProcessor):
|
|
|
1835
1836
|
|
|
1836
1837
|
if precision:
|
|
1837
1838
|
if self.start_timer is None:
|
|
1838
|
-
|
|
1839
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1840
|
+
if not candidate or candidate == "NA":
|
|
1841
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1842
|
+
self.start_timer = candidate
|
|
1839
1843
|
return self._format_timestamp(self.start_timer)
|
|
1840
1844
|
elif stream_info.get("input_settings", {}).get("start_frame", "na") == 1:
|
|
1841
|
-
|
|
1845
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1846
|
+
if not candidate or candidate == "NA":
|
|
1847
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1848
|
+
self.start_timer = candidate
|
|
1842
1849
|
return self._format_timestamp(self.start_timer)
|
|
1843
1850
|
else:
|
|
1844
1851
|
return self._format_timestamp(self.start_timer)
|
|
1845
1852
|
|
|
1846
1853
|
if self.start_timer is None:
|
|
1847
|
-
|
|
1854
|
+
# Prefer direct input_settings.stream_time if available and not NA
|
|
1855
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1856
|
+
if not candidate or candidate == "NA":
|
|
1857
|
+
# Fallback to nested stream_info.stream_time used by current timestamp path
|
|
1858
|
+
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
1859
|
+
if stream_time_str:
|
|
1860
|
+
try:
|
|
1861
|
+
timestamp_str = stream_time_str.replace(" UTC", "")
|
|
1862
|
+
dt = datetime.strptime(timestamp_str, "%Y-%m-%d-%H:%M:%S.%f")
|
|
1863
|
+
self._tracking_start_time = dt.replace(tzinfo=timezone.utc).timestamp()
|
|
1864
|
+
candidate = datetime.fromtimestamp(self._tracking_start_time, timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1865
|
+
except:
|
|
1866
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1867
|
+
else:
|
|
1868
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1869
|
+
self.start_timer = candidate
|
|
1848
1870
|
return self._format_timestamp(self.start_timer)
|
|
1849
1871
|
elif stream_info.get("input_settings", {}).get("start_frame", "na") == 1:
|
|
1850
|
-
|
|
1872
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1873
|
+
if not candidate or candidate == "NA":
|
|
1874
|
+
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
1875
|
+
if stream_time_str:
|
|
1876
|
+
try:
|
|
1877
|
+
timestamp_str = stream_time_str.replace(" UTC", "")
|
|
1878
|
+
dt = datetime.strptime(timestamp_str, "%Y-%m-%d-%H:%M:%S.%f")
|
|
1879
|
+
ts = dt.replace(tzinfo=timezone.utc).timestamp()
|
|
1880
|
+
candidate = datetime.fromtimestamp(ts, timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1881
|
+
except:
|
|
1882
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1883
|
+
else:
|
|
1884
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1885
|
+
self.start_timer = candidate
|
|
1851
1886
|
return self._format_timestamp(self.start_timer)
|
|
1852
1887
|
|
|
1853
1888
|
else:
|
|
1854
|
-
if self.start_timer is not None:
|
|
1889
|
+
if self.start_timer is not None and self.start_timer != "NA":
|
|
1855
1890
|
return self._format_timestamp(self.start_timer)
|
|
1856
1891
|
|
|
1857
1892
|
if self._tracking_start_time is None:
|
|
@@ -1617,6 +1617,53 @@ class ColorDetectionUseCase(BaseProcessor):
|
|
|
1617
1617
|
seconds = round(float(timestamp % 60),2)
|
|
1618
1618
|
return f"{hours:02d}:{minutes:02d}:{seconds:.1f}"
|
|
1619
1619
|
|
|
1620
|
+
def _format_timestamp(self, timestamp: Any) -> str:
|
|
1621
|
+
"""Format a timestamp to match the current timestamp format: YYYY:MM:DD HH:MM:SS.
|
|
1622
|
+
|
|
1623
|
+
The input can be either:
|
|
1624
|
+
1. A numeric Unix timestamp (``float`` / ``int``) – it will be converted to datetime.
|
|
1625
|
+
2. A string in the format ``YYYY-MM-DD-HH:MM:SS.ffffff UTC``.
|
|
1626
|
+
|
|
1627
|
+
The returned value will be in the format: YYYY:MM:DD HH:MM:SS (no milliseconds, no UTC suffix).
|
|
1628
|
+
|
|
1629
|
+
Example
|
|
1630
|
+
-------
|
|
1631
|
+
>>> self._format_timestamp("2025-10-27-19:31:20.187574 UTC")
|
|
1632
|
+
'2025:10:27 19:31:20'
|
|
1633
|
+
"""
|
|
1634
|
+
|
|
1635
|
+
# Convert numeric timestamps to datetime first
|
|
1636
|
+
if isinstance(timestamp, (int, float)):
|
|
1637
|
+
dt = datetime.fromtimestamp(timestamp, timezone.utc)
|
|
1638
|
+
return dt.strftime('%Y:%m:%d %H:%M:%S')
|
|
1639
|
+
|
|
1640
|
+
# Ensure we are working with a string from here on
|
|
1641
|
+
if not isinstance(timestamp, str):
|
|
1642
|
+
return str(timestamp)
|
|
1643
|
+
|
|
1644
|
+
# Remove ' UTC' suffix if present
|
|
1645
|
+
timestamp_clean = timestamp.replace(' UTC', '').strip()
|
|
1646
|
+
|
|
1647
|
+
# Remove milliseconds if present (everything after the last dot)
|
|
1648
|
+
if '.' in timestamp_clean:
|
|
1649
|
+
timestamp_clean = timestamp_clean.split('.')[0]
|
|
1650
|
+
|
|
1651
|
+
# Parse the timestamp string and convert to desired format
|
|
1652
|
+
try:
|
|
1653
|
+
# Handle format: YYYY-MM-DD-HH:MM:SS
|
|
1654
|
+
if timestamp_clean.count('-') >= 2:
|
|
1655
|
+
# Replace first two dashes with colons for date part, third with space
|
|
1656
|
+
parts = timestamp_clean.split('-')
|
|
1657
|
+
if len(parts) >= 4:
|
|
1658
|
+
# parts = ['2025', '10', '27', '19:31:20']
|
|
1659
|
+
formatted = f"{parts[0]}:{parts[1]}:{parts[2]} {'-'.join(parts[3:])}"
|
|
1660
|
+
return formatted
|
|
1661
|
+
except Exception:
|
|
1662
|
+
pass
|
|
1663
|
+
|
|
1664
|
+
# If parsing fails, return the cleaned string as-is
|
|
1665
|
+
return timestamp_clean
|
|
1666
|
+
|
|
1620
1667
|
def _get_current_timestamp_str(self, stream_info: Optional[Dict[str, Any]], precision=False, frame_id: Optional[str]=None) -> str:
|
|
1621
1668
|
"""Get formatted current timestamp based on stream type."""
|
|
1622
1669
|
|
|
@@ -1630,7 +1677,6 @@ class ColorDetectionUseCase(BaseProcessor):
|
|
|
1630
1677
|
start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
|
|
1631
1678
|
stream_time_str = self._format_timestamp_for_video(start_time)
|
|
1632
1679
|
|
|
1633
|
-
|
|
1634
1680
|
return self._format_timestamp(stream_info.get("input_settings", {}).get("stream_time", "NA"))
|
|
1635
1681
|
else:
|
|
1636
1682
|
return datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
@@ -1642,7 +1688,8 @@ class ColorDetectionUseCase(BaseProcessor):
|
|
|
1642
1688
|
start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
|
|
1643
1689
|
|
|
1644
1690
|
stream_time_str = self._format_timestamp_for_video(start_time)
|
|
1645
|
-
|
|
1691
|
+
|
|
1692
|
+
|
|
1646
1693
|
return self._format_timestamp(stream_info.get("input_settings", {}).get("stream_time", "NA"))
|
|
1647
1694
|
else:
|
|
1648
1695
|
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
@@ -1661,26 +1708,60 @@ class ColorDetectionUseCase(BaseProcessor):
|
|
|
1661
1708
|
"""Get formatted start timestamp for 'TOTAL SINCE' based on stream type."""
|
|
1662
1709
|
if not stream_info:
|
|
1663
1710
|
return "00:00:00"
|
|
1664
|
-
|
|
1711
|
+
|
|
1665
1712
|
if precision:
|
|
1666
1713
|
if self.start_timer is None:
|
|
1667
|
-
|
|
1714
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1715
|
+
if not candidate or candidate == "NA":
|
|
1716
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1717
|
+
self.start_timer = candidate
|
|
1668
1718
|
return self._format_timestamp(self.start_timer)
|
|
1669
1719
|
elif stream_info.get("input_settings", {}).get("start_frame", "na") == 1:
|
|
1670
|
-
|
|
1720
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1721
|
+
if not candidate or candidate == "NA":
|
|
1722
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1723
|
+
self.start_timer = candidate
|
|
1671
1724
|
return self._format_timestamp(self.start_timer)
|
|
1672
1725
|
else:
|
|
1673
1726
|
return self._format_timestamp(self.start_timer)
|
|
1674
1727
|
|
|
1675
1728
|
if self.start_timer is None:
|
|
1676
|
-
|
|
1729
|
+
# Prefer direct input_settings.stream_time if available and not NA
|
|
1730
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1731
|
+
if not candidate or candidate == "NA":
|
|
1732
|
+
# Fallback to nested stream_info.stream_time used by current timestamp path
|
|
1733
|
+
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
1734
|
+
if stream_time_str:
|
|
1735
|
+
try:
|
|
1736
|
+
timestamp_str = stream_time_str.replace(" UTC", "")
|
|
1737
|
+
dt = datetime.strptime(timestamp_str, "%Y-%m-%d-%H:%M:%S.%f")
|
|
1738
|
+
self._tracking_start_time = dt.replace(tzinfo=timezone.utc).timestamp()
|
|
1739
|
+
candidate = datetime.fromtimestamp(self._tracking_start_time, timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1740
|
+
except:
|
|
1741
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1742
|
+
else:
|
|
1743
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1744
|
+
self.start_timer = candidate
|
|
1677
1745
|
return self._format_timestamp(self.start_timer)
|
|
1678
1746
|
elif stream_info.get("input_settings", {}).get("start_frame", "na") == 1:
|
|
1679
|
-
|
|
1747
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1748
|
+
if not candidate or candidate == "NA":
|
|
1749
|
+
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
1750
|
+
if stream_time_str:
|
|
1751
|
+
try:
|
|
1752
|
+
timestamp_str = stream_time_str.replace(" UTC", "")
|
|
1753
|
+
dt = datetime.strptime(timestamp_str, "%Y-%m-%d-%H:%M:%S.%f")
|
|
1754
|
+
ts = dt.replace(tzinfo=timezone.utc).timestamp()
|
|
1755
|
+
candidate = datetime.fromtimestamp(ts, timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1756
|
+
except:
|
|
1757
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1758
|
+
else:
|
|
1759
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1760
|
+
self.start_timer = candidate
|
|
1680
1761
|
return self._format_timestamp(self.start_timer)
|
|
1681
1762
|
|
|
1682
1763
|
else:
|
|
1683
|
-
if self.start_timer is not None:
|
|
1764
|
+
if self.start_timer is not None and self.start_timer != "NA":
|
|
1684
1765
|
return self._format_timestamp(self.start_timer)
|
|
1685
1766
|
|
|
1686
1767
|
if self._tracking_start_time is None:
|
|
@@ -1699,52 +1780,6 @@ class ColorDetectionUseCase(BaseProcessor):
|
|
|
1699
1780
|
dt = dt.replace(minute=0, second=0, microsecond=0)
|
|
1700
1781
|
return dt.strftime('%Y:%m:%d %H:%M:%S')
|
|
1701
1782
|
|
|
1702
|
-
def _format_timestamp(self, timestamp: Any) -> str:
|
|
1703
|
-
"""Format a timestamp so that exactly two digits follow the decimal point (milliseconds).
|
|
1704
|
-
|
|
1705
|
-
The input can be either:
|
|
1706
|
-
1. A numeric Unix timestamp (``float`` / ``int``) – it will first be converted to a
|
|
1707
|
-
string in the format ``YYYY-MM-DD-HH:MM:SS.ffffff UTC``.
|
|
1708
|
-
2. A string already following the same layout.
|
|
1709
|
-
|
|
1710
|
-
The returned value preserves the overall format of the input but truncates or pads
|
|
1711
|
-
the fractional seconds portion to **exactly two digits**.
|
|
1712
|
-
|
|
1713
|
-
Example
|
|
1714
|
-
-------
|
|
1715
|
-
>>> self._format_timestamp("2025-08-19-04:22:47.187574 UTC")
|
|
1716
|
-
'2025-08-19-04:22:47.18 UTC'
|
|
1717
|
-
"""
|
|
1718
|
-
|
|
1719
|
-
# Convert numeric timestamps to the expected string representation first
|
|
1720
|
-
if isinstance(timestamp, (int, float)):
|
|
1721
|
-
timestamp = datetime.fromtimestamp(timestamp, timezone.utc).strftime(
|
|
1722
|
-
'%Y-%m-%d-%H:%M:%S.%f UTC'
|
|
1723
|
-
)
|
|
1724
|
-
|
|
1725
|
-
# Ensure we are working with a string from here on
|
|
1726
|
-
if not isinstance(timestamp, str):
|
|
1727
|
-
return str(timestamp)
|
|
1728
|
-
|
|
1729
|
-
# If there is no fractional component, simply return the original string
|
|
1730
|
-
if '.' not in timestamp:
|
|
1731
|
-
return timestamp
|
|
1732
|
-
|
|
1733
|
-
# Split out the main portion (up to the decimal point)
|
|
1734
|
-
main_part, fractional_and_suffix = timestamp.split('.', 1)
|
|
1735
|
-
|
|
1736
|
-
# Separate fractional digits from the suffix (typically ' UTC')
|
|
1737
|
-
if ' ' in fractional_and_suffix:
|
|
1738
|
-
fractional_part, suffix = fractional_and_suffix.split(' ', 1)
|
|
1739
|
-
suffix = ' ' + suffix # Re-attach the space removed by split
|
|
1740
|
-
else:
|
|
1741
|
-
fractional_part, suffix = fractional_and_suffix, ''
|
|
1742
|
-
|
|
1743
|
-
# Guarantee exactly two digits for the fractional part
|
|
1744
|
-
fractional_part = (fractional_part + '00')[:2]
|
|
1745
|
-
|
|
1746
|
-
return f"{main_part}.{fractional_part}{suffix}"
|
|
1747
|
-
|
|
1748
1783
|
def _get_tracking_start_time(self) -> str:
|
|
1749
1784
|
"""Get the tracking start time, formatted as a string."""
|
|
1750
1785
|
if self._tracking_start_time is None:
|
|
@@ -892,11 +892,58 @@ class FireSmokeUseCase(BaseProcessor):
|
|
|
892
892
|
seconds = round(float(timestamp % 60), 2)
|
|
893
893
|
return f"{hours:02d}:{minutes:02d}:{seconds:.1f}"
|
|
894
894
|
|
|
895
|
+
def _format_timestamp(self, timestamp: Any) -> str:
|
|
896
|
+
"""Format a timestamp to match the current timestamp format: YYYY:MM:DD HH:MM:SS.
|
|
897
|
+
|
|
898
|
+
The input can be either:
|
|
899
|
+
1. A numeric Unix timestamp (``float`` / ``int``) – it will be converted to datetime.
|
|
900
|
+
2. A string in the format ``YYYY-MM-DD-HH:MM:SS.ffffff UTC``.
|
|
901
|
+
|
|
902
|
+
The returned value will be in the format: YYYY:MM:DD HH:MM:SS (no milliseconds, no UTC suffix).
|
|
903
|
+
|
|
904
|
+
Example
|
|
905
|
+
-------
|
|
906
|
+
>>> self._format_timestamp("2025-10-27-19:31:20.187574 UTC")
|
|
907
|
+
'2025:10:27 19:31:20'
|
|
908
|
+
"""
|
|
909
|
+
|
|
910
|
+
# Convert numeric timestamps to datetime first
|
|
911
|
+
if isinstance(timestamp, (int, float)):
|
|
912
|
+
dt = datetime.fromtimestamp(timestamp, timezone.utc)
|
|
913
|
+
return dt.strftime('%Y:%m:%d %H:%M:%S')
|
|
914
|
+
|
|
915
|
+
# Ensure we are working with a string from here on
|
|
916
|
+
if not isinstance(timestamp, str):
|
|
917
|
+
return str(timestamp)
|
|
918
|
+
|
|
919
|
+
# Remove ' UTC' suffix if present
|
|
920
|
+
timestamp_clean = timestamp.replace(' UTC', '').strip()
|
|
921
|
+
|
|
922
|
+
# Remove milliseconds if present (everything after the last dot)
|
|
923
|
+
if '.' in timestamp_clean:
|
|
924
|
+
timestamp_clean = timestamp_clean.split('.')[0]
|
|
925
|
+
|
|
926
|
+
# Parse the timestamp string and convert to desired format
|
|
927
|
+
try:
|
|
928
|
+
# Handle format: YYYY-MM-DD-HH:MM:SS
|
|
929
|
+
if timestamp_clean.count('-') >= 2:
|
|
930
|
+
# Replace first two dashes with colons for date part, third with space
|
|
931
|
+
parts = timestamp_clean.split('-')
|
|
932
|
+
if len(parts) >= 4:
|
|
933
|
+
# parts = ['2025', '10', '27', '19:31:20']
|
|
934
|
+
formatted = f"{parts[0]}:{parts[1]}:{parts[2]} {'-'.join(parts[3:])}"
|
|
935
|
+
return formatted
|
|
936
|
+
except Exception:
|
|
937
|
+
pass
|
|
938
|
+
|
|
939
|
+
# If parsing fails, return the cleaned string as-is
|
|
940
|
+
return timestamp_clean
|
|
941
|
+
|
|
895
942
|
def _get_current_timestamp_str(self, stream_info: Optional[Dict[str, Any]], precision=False, frame_id: Optional[str]=None) -> str:
|
|
896
943
|
"""Get formatted current timestamp based on stream type."""
|
|
944
|
+
|
|
897
945
|
if not stream_info:
|
|
898
946
|
return "00:00:00.00"
|
|
899
|
-
|
|
900
947
|
if precision:
|
|
901
948
|
if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
|
|
902
949
|
if frame_id:
|
|
@@ -905,7 +952,6 @@ class FireSmokeUseCase(BaseProcessor):
|
|
|
905
952
|
start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
|
|
906
953
|
stream_time_str = self._format_timestamp_for_video(start_time)
|
|
907
954
|
|
|
908
|
-
|
|
909
955
|
return self._format_timestamp(stream_info.get("input_settings", {}).get("stream_time", "NA"))
|
|
910
956
|
else:
|
|
911
957
|
return datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
@@ -917,7 +963,8 @@ class FireSmokeUseCase(BaseProcessor):
|
|
|
917
963
|
start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
|
|
918
964
|
|
|
919
965
|
stream_time_str = self._format_timestamp_for_video(start_time)
|
|
920
|
-
|
|
966
|
+
|
|
967
|
+
|
|
921
968
|
return self._format_timestamp(stream_info.get("input_settings", {}).get("stream_time", "NA"))
|
|
922
969
|
else:
|
|
923
970
|
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
@@ -939,23 +986,57 @@ class FireSmokeUseCase(BaseProcessor):
|
|
|
939
986
|
|
|
940
987
|
if precision:
|
|
941
988
|
if self.start_timer is None:
|
|
942
|
-
|
|
989
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
990
|
+
if not candidate or candidate == "NA":
|
|
991
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
992
|
+
self.start_timer = candidate
|
|
943
993
|
return self._format_timestamp(self.start_timer)
|
|
944
994
|
elif stream_info.get("input_settings", {}).get("start_frame", "na") == 1:
|
|
945
|
-
|
|
995
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
996
|
+
if not candidate or candidate == "NA":
|
|
997
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
998
|
+
self.start_timer = candidate
|
|
946
999
|
return self._format_timestamp(self.start_timer)
|
|
947
1000
|
else:
|
|
948
1001
|
return self._format_timestamp(self.start_timer)
|
|
949
1002
|
|
|
950
1003
|
if self.start_timer is None:
|
|
951
|
-
|
|
1004
|
+
# Prefer direct input_settings.stream_time if available and not NA
|
|
1005
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1006
|
+
if not candidate or candidate == "NA":
|
|
1007
|
+
# Fallback to nested stream_info.stream_time used by current timestamp path
|
|
1008
|
+
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
1009
|
+
if stream_time_str:
|
|
1010
|
+
try:
|
|
1011
|
+
timestamp_str = stream_time_str.replace(" UTC", "")
|
|
1012
|
+
dt = datetime.strptime(timestamp_str, "%Y-%m-%d-%H:%M:%S.%f")
|
|
1013
|
+
self._tracking_start_time = dt.replace(tzinfo=timezone.utc).timestamp()
|
|
1014
|
+
candidate = datetime.fromtimestamp(self._tracking_start_time, timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1015
|
+
except:
|
|
1016
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1017
|
+
else:
|
|
1018
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1019
|
+
self.start_timer = candidate
|
|
952
1020
|
return self._format_timestamp(self.start_timer)
|
|
953
1021
|
elif stream_info.get("input_settings", {}).get("start_frame", "na") == 1:
|
|
954
|
-
|
|
1022
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1023
|
+
if not candidate or candidate == "NA":
|
|
1024
|
+
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
1025
|
+
if stream_time_str:
|
|
1026
|
+
try:
|
|
1027
|
+
timestamp_str = stream_time_str.replace(" UTC", "")
|
|
1028
|
+
dt = datetime.strptime(timestamp_str, "%Y-%m-%d-%H:%M:%S.%f")
|
|
1029
|
+
ts = dt.replace(tzinfo=timezone.utc).timestamp()
|
|
1030
|
+
candidate = datetime.fromtimestamp(ts, timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1031
|
+
except:
|
|
1032
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1033
|
+
else:
|
|
1034
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1035
|
+
self.start_timer = candidate
|
|
955
1036
|
return self._format_timestamp(self.start_timer)
|
|
956
1037
|
|
|
957
1038
|
else:
|
|
958
|
-
if self.start_timer is not None:
|
|
1039
|
+
if self.start_timer is not None and self.start_timer != "NA":
|
|
959
1040
|
return self._format_timestamp(self.start_timer)
|
|
960
1041
|
|
|
961
1042
|
if self._tracking_start_time is None:
|
|
@@ -974,52 +1055,6 @@ class FireSmokeUseCase(BaseProcessor):
|
|
|
974
1055
|
dt = dt.replace(minute=0, second=0, microsecond=0)
|
|
975
1056
|
return dt.strftime('%Y:%m:%d %H:%M:%S')
|
|
976
1057
|
|
|
977
|
-
def _format_timestamp(self, timestamp: Any) -> str:
|
|
978
|
-
"""Format a timestamp so that exactly two digits follow the decimal point (milliseconds).
|
|
979
|
-
|
|
980
|
-
The input can be either:
|
|
981
|
-
1. A numeric Unix timestamp (``float`` / ``int``) – it will first be converted to a
|
|
982
|
-
string in the format ``YYYY-MM-DD-HH:MM:SS.ffffff UTC``.
|
|
983
|
-
2. A string already following the same layout.
|
|
984
|
-
|
|
985
|
-
The returned value preserves the overall format of the input but truncates or pads
|
|
986
|
-
the fractional seconds portion to **exactly two digits**.
|
|
987
|
-
|
|
988
|
-
Example
|
|
989
|
-
-------
|
|
990
|
-
>>> self._format_timestamp("2025-08-19-04:22:47.187574 UTC")
|
|
991
|
-
'2025-08-19-04:22:47.18 UTC'
|
|
992
|
-
"""
|
|
993
|
-
|
|
994
|
-
# Convert numeric timestamps to the expected string representation first
|
|
995
|
-
if isinstance(timestamp, (int, float)):
|
|
996
|
-
timestamp = datetime.fromtimestamp(timestamp, timezone.utc).strftime(
|
|
997
|
-
'%Y-%m-%d-%H:%M:%S.%f UTC'
|
|
998
|
-
)
|
|
999
|
-
|
|
1000
|
-
# Ensure we are working with a string from here on
|
|
1001
|
-
if not isinstance(timestamp, str):
|
|
1002
|
-
return str(timestamp)
|
|
1003
|
-
|
|
1004
|
-
# If there is no fractional component, simply return the original string
|
|
1005
|
-
if '.' not in timestamp:
|
|
1006
|
-
return timestamp
|
|
1007
|
-
|
|
1008
|
-
# Split out the main portion (up to the decimal point)
|
|
1009
|
-
main_part, fractional_and_suffix = timestamp.split('.', 1)
|
|
1010
|
-
|
|
1011
|
-
# Separate fractional digits from the suffix (typically ' UTC')
|
|
1012
|
-
if ' ' in fractional_and_suffix:
|
|
1013
|
-
fractional_part, suffix = fractional_and_suffix.split(' ', 1)
|
|
1014
|
-
suffix = ' ' + suffix # Re-attach the space removed by split
|
|
1015
|
-
else:
|
|
1016
|
-
fractional_part, suffix = fractional_and_suffix, ''
|
|
1017
|
-
|
|
1018
|
-
# Guarantee exactly two digits for the fractional part
|
|
1019
|
-
fractional_part = (fractional_part + '00')[:2]
|
|
1020
|
-
|
|
1021
|
-
return f"{main_part}.{fractional_part}{suffix}"
|
|
1022
|
-
|
|
1023
1058
|
def get_duration_seconds(self, start_time, end_time):
|
|
1024
1059
|
def parse_relative_time(t):
|
|
1025
1060
|
"""Parse HH:MM:SS(.f) manually into timedelta"""
|
|
@@ -1566,63 +1566,64 @@ class LicensePlateMonitorUseCase(BaseProcessor):
|
|
|
1566
1566
|
}
|
|
1567
1567
|
return canonical_id
|
|
1568
1568
|
|
|
1569
|
+
def _format_timestamp_for_stream(self, timestamp: float) -> str:
|
|
1570
|
+
"""Format timestamp for streams (YYYY:MM:DD HH:MM:SS format)."""
|
|
1571
|
+
dt = datetime.fromtimestamp(timestamp, tz=timezone.utc)
|
|
1572
|
+
return dt.strftime('%Y:%m:%d %H:%M:%S')
|
|
1573
|
+
|
|
1574
|
+
def _format_timestamp_for_video(self, timestamp: float) -> str:
|
|
1575
|
+
"""Format timestamp for video chunks (HH:MM:SS.ms format)."""
|
|
1576
|
+
hours = int(timestamp // 3600)
|
|
1577
|
+
minutes = int((timestamp % 3600) // 60)
|
|
1578
|
+
seconds = round(float(timestamp % 60), 2)
|
|
1579
|
+
return f"{hours:02d}:{minutes:02d}:{seconds:.1f}"
|
|
1580
|
+
|
|
1569
1581
|
def _format_timestamp(self, timestamp: Any) -> str:
|
|
1570
|
-
"""Format a timestamp
|
|
1582
|
+
"""Format a timestamp to match the current timestamp format: YYYY:MM:DD HH:MM:SS.
|
|
1571
1583
|
|
|
1572
1584
|
The input can be either:
|
|
1573
|
-
1. A numeric Unix timestamp (``float`` / ``int``)
|
|
1574
|
-
|
|
1575
|
-
2. A string already following the same layout.
|
|
1585
|
+
1. A numeric Unix timestamp (``float`` / ``int``) – it will be converted to datetime.
|
|
1586
|
+
2. A string in the format ``YYYY-MM-DD-HH:MM:SS.ffffff UTC``.
|
|
1576
1587
|
|
|
1577
|
-
The returned value
|
|
1578
|
-
the fractional seconds portion to **exactly two digits**.
|
|
1588
|
+
The returned value will be in the format: YYYY:MM:DD HH:MM:SS (no milliseconds, no UTC suffix).
|
|
1579
1589
|
|
|
1580
1590
|
Example
|
|
1581
1591
|
-------
|
|
1582
|
-
>>> self._format_timestamp("2025-
|
|
1583
|
-
'2025
|
|
1592
|
+
>>> self._format_timestamp("2025-10-27-19:31:20.187574 UTC")
|
|
1593
|
+
'2025:10:27 19:31:20'
|
|
1584
1594
|
"""
|
|
1585
1595
|
|
|
1586
|
-
# Convert numeric timestamps to
|
|
1596
|
+
# Convert numeric timestamps to datetime first
|
|
1587
1597
|
if isinstance(timestamp, (int, float)):
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
)
|
|
1598
|
+
dt = datetime.fromtimestamp(timestamp, timezone.utc)
|
|
1599
|
+
return dt.strftime('%Y:%m:%d %H:%M:%S')
|
|
1591
1600
|
|
|
1592
1601
|
# Ensure we are working with a string from here on
|
|
1593
1602
|
if not isinstance(timestamp, str):
|
|
1594
1603
|
return str(timestamp)
|
|
1595
1604
|
|
|
1596
|
-
#
|
|
1597
|
-
|
|
1598
|
-
return timestamp
|
|
1599
|
-
|
|
1600
|
-
# Split out the main portion (up to the decimal point)
|
|
1601
|
-
main_part, fractional_and_suffix = timestamp.split('.', 1)
|
|
1602
|
-
|
|
1603
|
-
# Separate fractional digits from the suffix (typically ' UTC')
|
|
1604
|
-
if ' ' in fractional_and_suffix:
|
|
1605
|
-
fractional_part, suffix = fractional_and_suffix.split(' ', 1)
|
|
1606
|
-
suffix = ' ' + suffix # Re-attach the space removed by split
|
|
1607
|
-
else:
|
|
1608
|
-
fractional_part, suffix = fractional_and_suffix, ''
|
|
1609
|
-
|
|
1610
|
-
# Guarantee exactly two digits for the fractional part
|
|
1611
|
-
fractional_part = (fractional_part + '00')[:2]
|
|
1605
|
+
# Remove ' UTC' suffix if present
|
|
1606
|
+
timestamp_clean = timestamp.replace(' UTC', '').strip()
|
|
1612
1607
|
|
|
1613
|
-
|
|
1608
|
+
# Remove milliseconds if present (everything after the last dot)
|
|
1609
|
+
if '.' in timestamp_clean:
|
|
1610
|
+
timestamp_clean = timestamp_clean.split('.')[0]
|
|
1614
1611
|
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1612
|
+
# Parse the timestamp string and convert to desired format
|
|
1613
|
+
try:
|
|
1614
|
+
# Handle format: YYYY-MM-DD-HH:MM:SS
|
|
1615
|
+
if timestamp_clean.count('-') >= 2:
|
|
1616
|
+
# Replace first two dashes with colons for date part, third with space
|
|
1617
|
+
parts = timestamp_clean.split('-')
|
|
1618
|
+
if len(parts) >= 4:
|
|
1619
|
+
# parts = ['2025', '10', '27', '19:31:20']
|
|
1620
|
+
formatted = f"{parts[0]}:{parts[1]}:{parts[2]} {'-'.join(parts[3:])}"
|
|
1621
|
+
return formatted
|
|
1622
|
+
except Exception:
|
|
1623
|
+
pass
|
|
1624
|
+
|
|
1625
|
+
# If parsing fails, return the cleaned string as-is
|
|
1626
|
+
return timestamp_clean
|
|
1626
1627
|
|
|
1627
1628
|
def _get_current_timestamp_str(self, stream_info: Optional[Dict[str, Any]], precision=False, frame_id: Optional[str]=None) -> str:
|
|
1628
1629
|
"""Get formatted current timestamp based on stream type."""
|
|
@@ -1671,23 +1672,57 @@ class LicensePlateMonitorUseCase(BaseProcessor):
|
|
|
1671
1672
|
|
|
1672
1673
|
if precision:
|
|
1673
1674
|
if self.start_timer is None:
|
|
1674
|
-
|
|
1675
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1676
|
+
if not candidate or candidate == "NA":
|
|
1677
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1678
|
+
self.start_timer = candidate
|
|
1675
1679
|
return self._format_timestamp(self.start_timer)
|
|
1676
1680
|
elif stream_info.get("input_settings", {}).get("start_frame", "na") == 1:
|
|
1677
|
-
|
|
1681
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1682
|
+
if not candidate or candidate == "NA":
|
|
1683
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1684
|
+
self.start_timer = candidate
|
|
1678
1685
|
return self._format_timestamp(self.start_timer)
|
|
1679
1686
|
else:
|
|
1680
1687
|
return self._format_timestamp(self.start_timer)
|
|
1681
1688
|
|
|
1682
1689
|
if self.start_timer is None:
|
|
1683
|
-
|
|
1690
|
+
# Prefer direct input_settings.stream_time if available and not NA
|
|
1691
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1692
|
+
if not candidate or candidate == "NA":
|
|
1693
|
+
# Fallback to nested stream_info.stream_time used by current timestamp path
|
|
1694
|
+
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
1695
|
+
if stream_time_str:
|
|
1696
|
+
try:
|
|
1697
|
+
timestamp_str = stream_time_str.replace(" UTC", "")
|
|
1698
|
+
dt = datetime.strptime(timestamp_str, "%Y-%m-%d-%H:%M:%S.%f")
|
|
1699
|
+
self._tracking_start_time = dt.replace(tzinfo=timezone.utc).timestamp()
|
|
1700
|
+
candidate = datetime.fromtimestamp(self._tracking_start_time, timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1701
|
+
except:
|
|
1702
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1703
|
+
else:
|
|
1704
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1705
|
+
self.start_timer = candidate
|
|
1684
1706
|
return self._format_timestamp(self.start_timer)
|
|
1685
1707
|
elif stream_info.get("input_settings", {}).get("start_frame", "na") == 1:
|
|
1686
|
-
|
|
1708
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
1709
|
+
if not candidate or candidate == "NA":
|
|
1710
|
+
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
1711
|
+
if stream_time_str:
|
|
1712
|
+
try:
|
|
1713
|
+
timestamp_str = stream_time_str.replace(" UTC", "")
|
|
1714
|
+
dt = datetime.strptime(timestamp_str, "%Y-%m-%d-%H:%M:%S.%f")
|
|
1715
|
+
ts = dt.replace(tzinfo=timezone.utc).timestamp()
|
|
1716
|
+
candidate = datetime.fromtimestamp(ts, timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1717
|
+
except:
|
|
1718
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1719
|
+
else:
|
|
1720
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
1721
|
+
self.start_timer = candidate
|
|
1687
1722
|
return self._format_timestamp(self.start_timer)
|
|
1688
1723
|
|
|
1689
1724
|
else:
|
|
1690
|
-
if self.start_timer is not None:
|
|
1725
|
+
if self.start_timer is not None and self.start_timer != "NA":
|
|
1691
1726
|
return self._format_timestamp(self.start_timer)
|
|
1692
1727
|
|
|
1693
1728
|
if self._tracking_start_time is None:
|
|
@@ -1705,7 +1740,7 @@ class LicensePlateMonitorUseCase(BaseProcessor):
|
|
|
1705
1740
|
dt = datetime.fromtimestamp(self._tracking_start_time, tz=timezone.utc)
|
|
1706
1741
|
dt = dt.replace(minute=0, second=0, microsecond=0)
|
|
1707
1742
|
return dt.strftime('%Y:%m:%d %H:%M:%S')
|
|
1708
|
-
|
|
1743
|
+
|
|
1709
1744
|
def _get_tracking_start_time(self) -> str:
|
|
1710
1745
|
"""Get the tracking start time, formatted as a string."""
|
|
1711
1746
|
if self._tracking_start_time is None:
|
|
@@ -437,50 +437,51 @@ class PeopleCountingUseCase(BaseProcessor):
|
|
|
437
437
|
return f"{hours:02d}:{minutes:02d}:{seconds:.1f}"
|
|
438
438
|
|
|
439
439
|
def _format_timestamp(self, timestamp: Any) -> str:
|
|
440
|
-
"""Format a timestamp
|
|
440
|
+
"""Format a timestamp to match the current timestamp format: YYYY:MM:DD HH:MM:SS.
|
|
441
441
|
|
|
442
442
|
The input can be either:
|
|
443
|
-
1. A numeric Unix timestamp (``float`` / ``int``) – it will
|
|
444
|
-
|
|
445
|
-
2. A string already following the same layout.
|
|
443
|
+
1. A numeric Unix timestamp (``float`` / ``int``) – it will be converted to datetime.
|
|
444
|
+
2. A string in the format ``YYYY-MM-DD-HH:MM:SS.ffffff UTC``.
|
|
446
445
|
|
|
447
|
-
The returned value
|
|
448
|
-
the fractional seconds portion to **exactly two digits**.
|
|
446
|
+
The returned value will be in the format: YYYY:MM:DD HH:MM:SS (no milliseconds, no UTC suffix).
|
|
449
447
|
|
|
450
448
|
Example
|
|
451
449
|
-------
|
|
452
|
-
>>> self._format_timestamp("2025-
|
|
453
|
-
'2025
|
|
450
|
+
>>> self._format_timestamp("2025-10-27-19:31:20.187574 UTC")
|
|
451
|
+
'2025:10:27 19:31:20'
|
|
454
452
|
"""
|
|
455
453
|
|
|
456
|
-
# Convert numeric timestamps to
|
|
454
|
+
# Convert numeric timestamps to datetime first
|
|
457
455
|
if isinstance(timestamp, (int, float)):
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
)
|
|
456
|
+
dt = datetime.fromtimestamp(timestamp, timezone.utc)
|
|
457
|
+
return dt.strftime('%Y:%m:%d %H:%M:%S')
|
|
461
458
|
|
|
462
459
|
# Ensure we are working with a string from here on
|
|
463
460
|
if not isinstance(timestamp, str):
|
|
464
461
|
return str(timestamp)
|
|
465
462
|
|
|
466
|
-
#
|
|
467
|
-
|
|
468
|
-
return timestamp
|
|
469
|
-
|
|
470
|
-
# Split out the main portion (up to the decimal point)
|
|
471
|
-
main_part, fractional_and_suffix = timestamp.split('.', 1)
|
|
463
|
+
# Remove ' UTC' suffix if present
|
|
464
|
+
timestamp_clean = timestamp.replace(' UTC', '').strip()
|
|
472
465
|
|
|
473
|
-
#
|
|
474
|
-
if '
|
|
475
|
-
|
|
476
|
-
suffix = ' ' + suffix # Re-attach the space removed by split
|
|
477
|
-
else:
|
|
478
|
-
fractional_part, suffix = fractional_and_suffix, ''
|
|
479
|
-
|
|
480
|
-
# Guarantee exactly two digits for the fractional part
|
|
481
|
-
fractional_part = (fractional_part + '00')[:2]
|
|
466
|
+
# Remove milliseconds if present (everything after the last dot)
|
|
467
|
+
if '.' in timestamp_clean:
|
|
468
|
+
timestamp_clean = timestamp_clean.split('.')[0]
|
|
482
469
|
|
|
483
|
-
|
|
470
|
+
# Parse the timestamp string and convert to desired format
|
|
471
|
+
try:
|
|
472
|
+
# Handle format: YYYY-MM-DD-HH:MM:SS
|
|
473
|
+
if timestamp_clean.count('-') >= 2:
|
|
474
|
+
# Replace first two dashes with colons for date part, third with space
|
|
475
|
+
parts = timestamp_clean.split('-')
|
|
476
|
+
if len(parts) >= 4:
|
|
477
|
+
# parts = ['2025', '10', '27', '19:31:20']
|
|
478
|
+
formatted = f"{parts[0]}:{parts[1]}:{parts[2]} {'-'.join(parts[3:])}"
|
|
479
|
+
return formatted
|
|
480
|
+
except Exception:
|
|
481
|
+
pass
|
|
482
|
+
|
|
483
|
+
# If parsing fails, return the cleaned string as-is
|
|
484
|
+
return timestamp_clean
|
|
484
485
|
|
|
485
486
|
def _get_current_timestamp_str(self, stream_info: Optional[Dict[str, Any]], precision=False, frame_id: Optional[str]=None) -> str:
|
|
486
487
|
"""Get formatted current timestamp based on stream type."""
|
|
@@ -759,11 +759,58 @@ class VehicleMonitoringUseCase(BaseProcessor):
|
|
|
759
759
|
seconds = round(float(timestamp % 60), 2)
|
|
760
760
|
return f"{hours:02d}:{minutes:02d}:{seconds:.1f}"
|
|
761
761
|
|
|
762
|
+
def _format_timestamp(self, timestamp: Any) -> str:
|
|
763
|
+
"""Format a timestamp to match the current timestamp format: YYYY:MM:DD HH:MM:SS.
|
|
764
|
+
|
|
765
|
+
The input can be either:
|
|
766
|
+
1. A numeric Unix timestamp (``float`` / ``int``) – it will be converted to datetime.
|
|
767
|
+
2. A string in the format ``YYYY-MM-DD-HH:MM:SS.ffffff UTC``.
|
|
768
|
+
|
|
769
|
+
The returned value will be in the format: YYYY:MM:DD HH:MM:SS (no milliseconds, no UTC suffix).
|
|
770
|
+
|
|
771
|
+
Example
|
|
772
|
+
-------
|
|
773
|
+
>>> self._format_timestamp("2025-10-27-19:31:20.187574 UTC")
|
|
774
|
+
'2025:10:27 19:31:20'
|
|
775
|
+
"""
|
|
776
|
+
|
|
777
|
+
# Convert numeric timestamps to datetime first
|
|
778
|
+
if isinstance(timestamp, (int, float)):
|
|
779
|
+
dt = datetime.fromtimestamp(timestamp, timezone.utc)
|
|
780
|
+
return dt.strftime('%Y:%m:%d %H:%M:%S')
|
|
781
|
+
|
|
782
|
+
# Ensure we are working with a string from here on
|
|
783
|
+
if not isinstance(timestamp, str):
|
|
784
|
+
return str(timestamp)
|
|
785
|
+
|
|
786
|
+
# Remove ' UTC' suffix if present
|
|
787
|
+
timestamp_clean = timestamp.replace(' UTC', '').strip()
|
|
788
|
+
|
|
789
|
+
# Remove milliseconds if present (everything after the last dot)
|
|
790
|
+
if '.' in timestamp_clean:
|
|
791
|
+
timestamp_clean = timestamp_clean.split('.')[0]
|
|
792
|
+
|
|
793
|
+
# Parse the timestamp string and convert to desired format
|
|
794
|
+
try:
|
|
795
|
+
# Handle format: YYYY-MM-DD-HH:MM:SS
|
|
796
|
+
if timestamp_clean.count('-') >= 2:
|
|
797
|
+
# Replace first two dashes with colons for date part, third with space
|
|
798
|
+
parts = timestamp_clean.split('-')
|
|
799
|
+
if len(parts) >= 4:
|
|
800
|
+
# parts = ['2025', '10', '27', '19:31:20']
|
|
801
|
+
formatted = f"{parts[0]}:{parts[1]}:{parts[2]} {'-'.join(parts[3:])}"
|
|
802
|
+
return formatted
|
|
803
|
+
except Exception:
|
|
804
|
+
pass
|
|
805
|
+
|
|
806
|
+
# If parsing fails, return the cleaned string as-is
|
|
807
|
+
return timestamp_clean
|
|
808
|
+
|
|
762
809
|
def _get_current_timestamp_str(self, stream_info: Optional[Dict[str, Any]], precision=False, frame_id: Optional[str]=None) -> str:
|
|
763
810
|
"""Get formatted current timestamp based on stream type."""
|
|
811
|
+
|
|
764
812
|
if not stream_info:
|
|
765
813
|
return "00:00:00.00"
|
|
766
|
-
|
|
767
814
|
if precision:
|
|
768
815
|
if stream_info.get("input_settings", {}).get("start_frame", "na") != "na":
|
|
769
816
|
if frame_id:
|
|
@@ -772,7 +819,6 @@ class VehicleMonitoringUseCase(BaseProcessor):
|
|
|
772
819
|
start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
|
|
773
820
|
stream_time_str = self._format_timestamp_for_video(start_time)
|
|
774
821
|
|
|
775
|
-
|
|
776
822
|
return self._format_timestamp(stream_info.get("input_settings", {}).get("stream_time", "NA"))
|
|
777
823
|
else:
|
|
778
824
|
return datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
@@ -784,7 +830,8 @@ class VehicleMonitoringUseCase(BaseProcessor):
|
|
|
784
830
|
start_time = stream_info.get("input_settings", {}).get("start_frame", 30)/stream_info.get("input_settings", {}).get("original_fps", 30)
|
|
785
831
|
|
|
786
832
|
stream_time_str = self._format_timestamp_for_video(start_time)
|
|
787
|
-
|
|
833
|
+
|
|
834
|
+
|
|
788
835
|
return self._format_timestamp(stream_info.get("input_settings", {}).get("stream_time", "NA"))
|
|
789
836
|
else:
|
|
790
837
|
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
@@ -806,23 +853,57 @@ class VehicleMonitoringUseCase(BaseProcessor):
|
|
|
806
853
|
|
|
807
854
|
if precision:
|
|
808
855
|
if self.start_timer is None:
|
|
809
|
-
|
|
856
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
857
|
+
if not candidate or candidate == "NA":
|
|
858
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
859
|
+
self.start_timer = candidate
|
|
810
860
|
return self._format_timestamp(self.start_timer)
|
|
811
861
|
elif stream_info.get("input_settings", {}).get("start_frame", "na") == 1:
|
|
812
|
-
|
|
862
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
863
|
+
if not candidate or candidate == "NA":
|
|
864
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
865
|
+
self.start_timer = candidate
|
|
813
866
|
return self._format_timestamp(self.start_timer)
|
|
814
867
|
else:
|
|
815
868
|
return self._format_timestamp(self.start_timer)
|
|
816
869
|
|
|
817
870
|
if self.start_timer is None:
|
|
818
|
-
|
|
871
|
+
# Prefer direct input_settings.stream_time if available and not NA
|
|
872
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
873
|
+
if not candidate or candidate == "NA":
|
|
874
|
+
# Fallback to nested stream_info.stream_time used by current timestamp path
|
|
875
|
+
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
876
|
+
if stream_time_str:
|
|
877
|
+
try:
|
|
878
|
+
timestamp_str = stream_time_str.replace(" UTC", "")
|
|
879
|
+
dt = datetime.strptime(timestamp_str, "%Y-%m-%d-%H:%M:%S.%f")
|
|
880
|
+
self._tracking_start_time = dt.replace(tzinfo=timezone.utc).timestamp()
|
|
881
|
+
candidate = datetime.fromtimestamp(self._tracking_start_time, timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
882
|
+
except:
|
|
883
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
884
|
+
else:
|
|
885
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
886
|
+
self.start_timer = candidate
|
|
819
887
|
return self._format_timestamp(self.start_timer)
|
|
820
888
|
elif stream_info.get("input_settings", {}).get("start_frame", "na") == 1:
|
|
821
|
-
|
|
889
|
+
candidate = stream_info.get("input_settings", {}).get("stream_time")
|
|
890
|
+
if not candidate or candidate == "NA":
|
|
891
|
+
stream_time_str = stream_info.get("input_settings", {}).get("stream_info", {}).get("stream_time", "")
|
|
892
|
+
if stream_time_str:
|
|
893
|
+
try:
|
|
894
|
+
timestamp_str = stream_time_str.replace(" UTC", "")
|
|
895
|
+
dt = datetime.strptime(timestamp_str, "%Y-%m-%d-%H:%M:%S.%f")
|
|
896
|
+
ts = dt.replace(tzinfo=timezone.utc).timestamp()
|
|
897
|
+
candidate = datetime.fromtimestamp(ts, timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
898
|
+
except:
|
|
899
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
900
|
+
else:
|
|
901
|
+
candidate = datetime.now(timezone.utc).strftime("%Y-%m-%d-%H:%M:%S.%f UTC")
|
|
902
|
+
self.start_timer = candidate
|
|
822
903
|
return self._format_timestamp(self.start_timer)
|
|
823
904
|
|
|
824
905
|
else:
|
|
825
|
-
if self.start_timer is not None:
|
|
906
|
+
if self.start_timer is not None and self.start_timer != "NA":
|
|
826
907
|
return self._format_timestamp(self.start_timer)
|
|
827
908
|
|
|
828
909
|
if self._tracking_start_time is None:
|
|
@@ -841,52 +922,6 @@ class VehicleMonitoringUseCase(BaseProcessor):
|
|
|
841
922
|
dt = dt.replace(minute=0, second=0, microsecond=0)
|
|
842
923
|
return dt.strftime('%Y:%m:%d %H:%M:%S')
|
|
843
924
|
|
|
844
|
-
def _format_timestamp(self, timestamp: Any) -> str:
|
|
845
|
-
"""Format a timestamp so that exactly two digits follow the decimal point (milliseconds).
|
|
846
|
-
|
|
847
|
-
The input can be either:
|
|
848
|
-
1. A numeric Unix timestamp (``float`` / ``int``) – it will first be converted to a
|
|
849
|
-
string in the format ``YYYY-MM-DD-HH:MM:SS.ffffff UTC``.
|
|
850
|
-
2. A string already following the same layout.
|
|
851
|
-
|
|
852
|
-
The returned value preserves the overall format of the input but truncates or pads
|
|
853
|
-
the fractional seconds portion to **exactly two digits**.
|
|
854
|
-
|
|
855
|
-
Example
|
|
856
|
-
-------
|
|
857
|
-
>>> self._format_timestamp("2025-08-19-04:22:47.187574 UTC")
|
|
858
|
-
'2025-08-19-04:22:47.18 UTC'
|
|
859
|
-
"""
|
|
860
|
-
|
|
861
|
-
# Convert numeric timestamps to the expected string representation first
|
|
862
|
-
if isinstance(timestamp, (int, float)):
|
|
863
|
-
timestamp = datetime.fromtimestamp(timestamp, timezone.utc).strftime(
|
|
864
|
-
'%Y-%m-%d-%H:%M:%S.%f UTC'
|
|
865
|
-
)
|
|
866
|
-
|
|
867
|
-
# Ensure we are working with a string from here on
|
|
868
|
-
if not isinstance(timestamp, str):
|
|
869
|
-
return str(timestamp)
|
|
870
|
-
|
|
871
|
-
# If there is no fractional component, simply return the original string
|
|
872
|
-
if '.' not in timestamp:
|
|
873
|
-
return timestamp
|
|
874
|
-
|
|
875
|
-
# Split out the main portion (up to the decimal point)
|
|
876
|
-
main_part, fractional_and_suffix = timestamp.split('.', 1)
|
|
877
|
-
|
|
878
|
-
# Separate fractional digits from the suffix (typically ' UTC')
|
|
879
|
-
if ' ' in fractional_and_suffix:
|
|
880
|
-
fractional_part, suffix = fractional_and_suffix.split(' ', 1)
|
|
881
|
-
suffix = ' ' + suffix # Re-attach the space removed by split
|
|
882
|
-
else:
|
|
883
|
-
fractional_part, suffix = fractional_and_suffix, ''
|
|
884
|
-
|
|
885
|
-
# Guarantee exactly two digits for the fractional part
|
|
886
|
-
fractional_part = (fractional_part + '00')[:2]
|
|
887
|
-
|
|
888
|
-
return f"{main_part}.{fractional_part}{suffix}"
|
|
889
|
-
|
|
890
925
|
def _count_categories(self, detections: list, config: VehicleMonitoringConfig) -> dict:
|
|
891
926
|
counts = {}
|
|
892
927
|
for det in detections:
|
|
@@ -29,7 +29,7 @@ matrice_analytics/post_processing/core/config_utils.py,sha256=QuAS-_JKSoNOtfUWgr
|
|
|
29
29
|
matrice_analytics/post_processing/face_reg/__init__.py,sha256=yntaiGlW9vdjBpPZQXNuovALihJPzRlFyUE88l3MhBA,1364
|
|
30
30
|
matrice_analytics/post_processing/face_reg/compare_similarity.py,sha256=NlFc8b2a74k0PqSFAbuM_fUbA1BT3pr3VUgvSqRpJzQ,23396
|
|
31
31
|
matrice_analytics/post_processing/face_reg/embedding_manager.py,sha256=qbh0df3-YbE0qvFDQvjpCg-JrsCZRJ5capjQ2LPOj1k,35619
|
|
32
|
-
matrice_analytics/post_processing/face_reg/face_recognition.py,sha256=
|
|
32
|
+
matrice_analytics/post_processing/face_reg/face_recognition.py,sha256=eXzd2hc3qYtYLOxc32l5KAvqS1pIZQTKUhG4wPRMwOc,92552
|
|
33
33
|
matrice_analytics/post_processing/face_reg/face_recognition_client.py,sha256=YaC73mN0yrHZYkjJ7nZIZen5YCVOwEX2gn6I1XpHTW0,27575
|
|
34
34
|
matrice_analytics/post_processing/face_reg/people_activity_logging.py,sha256=NhJXy9jCy_mlZiDXv8IeGyrRN_TL0kKCe3ZOlaNbZUw,13676
|
|
35
35
|
matrice_analytics/post_processing/ocr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -100,7 +100,7 @@ matrice_analytics/post_processing/usecases/cardiomegaly_classification.py,sha256
|
|
|
100
100
|
matrice_analytics/post_processing/usecases/cell_microscopy_segmentation.py,sha256=eQ_s5u3Vnvja6-FmI6ZPxlNkaZtG-pVjTu8NuLjZJ5M,43714
|
|
101
101
|
matrice_analytics/post_processing/usecases/chicken_pose_detection.py,sha256=-e8di7Am-E-FCQFrSY8qJTO1aWtdRAVJoE-VKBgcyyI,29291
|
|
102
102
|
matrice_analytics/post_processing/usecases/child_monitoring.py,sha256=z3oymoqq4hDGwA8MkdEONZW_Vx5CAZmvzZaNLsqmCfw,39380
|
|
103
|
-
matrice_analytics/post_processing/usecases/color_detection.py,sha256=
|
|
103
|
+
matrice_analytics/post_processing/usecases/color_detection.py,sha256=56oLhecGN8jaPcRLNpZ-AJYjhYqvcRq_BX7rjkPHW0s,92361
|
|
104
104
|
matrice_analytics/post_processing/usecases/color_map_utils.py,sha256=SP-AEVcjLmL8rxblu-ixqUJC2fqlcr7ab4hWo4Fcr_k,2677
|
|
105
105
|
matrice_analytics/post_processing/usecases/concrete_crack_detection.py,sha256=pxhOH_hG4hq9yytNepbGMdk2W_lTG8D1_2RAagaPBkg,40252
|
|
106
106
|
matrice_analytics/post_processing/usecases/crop_weed_detection.py,sha256=Ao1k5fJDYU_f6yZ8VO-jW8-esECV0-zY5Q570c_fako,35674
|
|
@@ -115,7 +115,7 @@ matrice_analytics/post_processing/usecases/face_emotion.py,sha256=eRfqBdryB0uNoO
|
|
|
115
115
|
matrice_analytics/post_processing/usecases/face_recognition.py,sha256=T5xAuv6b9OrkmTmoXgZs4LZ5XUsbvp9xCpeLBwdu7eI,40231
|
|
116
116
|
matrice_analytics/post_processing/usecases/fashion_detection.py,sha256=f9gpzMDhIW-gyn46k9jgf8nY7YeoqAnTxGOzksabFbE,40457
|
|
117
117
|
matrice_analytics/post_processing/usecases/field_mapping.py,sha256=JDwYX8pd2W-waDvBh98Y_o_uchJu7wEYbFxOliA4Iq4,39822
|
|
118
|
-
matrice_analytics/post_processing/usecases/fire_detection.py,sha256=
|
|
118
|
+
matrice_analytics/post_processing/usecases/fire_detection.py,sha256=3ZZZrIXtZ_Ui3d3nQxvj12pqFTgguRN4OiE0cQYNXhg,54614
|
|
119
119
|
matrice_analytics/post_processing/usecases/flare_analysis.py,sha256=3nf4fUeUwlP_UII0h5fQkUGPXbr32ZnJjaM-dukNSP8,42680
|
|
120
120
|
matrice_analytics/post_processing/usecases/flower_segmentation.py,sha256=4I7qMx9Ztxg_hy9KTVX-3qBhAN-QwDt_Yigf9fFjLus,52017
|
|
121
121
|
matrice_analytics/post_processing/usecases/gas_leak_detection.py,sha256=KL2ft7fXvjTas-65-QgcJm3W8KBsrwF44qibSXjfaLc,40557
|
|
@@ -126,7 +126,7 @@ matrice_analytics/post_processing/usecases/leaf.py,sha256=cwgB1ZNxkQFtkk-thSJrkX
|
|
|
126
126
|
matrice_analytics/post_processing/usecases/leaf_disease.py,sha256=bkiLccTdf4KUq3he4eCpBlKXb5exr-WBhQ_oWQ7os68,36225
|
|
127
127
|
matrice_analytics/post_processing/usecases/leak_detection.py,sha256=oOCLLVMuXVeXPHyN8FUrD3U9JYJJwIz-5fcEMgvLdls,40531
|
|
128
128
|
matrice_analytics/post_processing/usecases/license_plate_detection.py,sha256=dsavd92-wnyXCNrCzaRj24zH7BVvLSa09HkYsrOXYDM,50806
|
|
129
|
-
matrice_analytics/post_processing/usecases/license_plate_monitoring.py,sha256=
|
|
129
|
+
matrice_analytics/post_processing/usecases/license_plate_monitoring.py,sha256=hjc9tQkUzVwvWuNohw28P2SJNHb25P5ERZbNlRkSKOk,91379
|
|
130
130
|
matrice_analytics/post_processing/usecases/litter_monitoring.py,sha256=XaHAUGRBDJg_iVbu8hRMjTR-5TqrLj6ZNCRkInbzZTY,33255
|
|
131
131
|
matrice_analytics/post_processing/usecases/mask_detection.py,sha256=L_s6ZiT5zeXG-BsFcskb3HEG98DhLgqeMSDmCuwOteU,41501
|
|
132
132
|
matrice_analytics/post_processing/usecases/natural_disaster.py,sha256=ehxdPBoYcZWGVDOVn_mHFoz4lIE8LrveAkuXQj0n9XE,44253
|
|
@@ -134,7 +134,7 @@ matrice_analytics/post_processing/usecases/parking.py,sha256=lqTGqcjUZZPFw3tu11H
|
|
|
134
134
|
matrice_analytics/post_processing/usecases/parking_space_detection.py,sha256=xwhkJjGGKcT827URbasi3olYqhd95Sh0zsEIphwzcgY,39561
|
|
135
135
|
matrice_analytics/post_processing/usecases/pcb_defect_detection.py,sha256=xH3q-WoR3TwMUeUvWw1W7vPLdCUfu_Kl_gQ9dZFf1SE,43006
|
|
136
136
|
matrice_analytics/post_processing/usecases/pedestrian_detection.py,sha256=hPFtvpWXXEsbDavmuiXIhrosMNlOhGya--jukT-ZOHA,39288
|
|
137
|
-
matrice_analytics/post_processing/usecases/people_counting.py,sha256=
|
|
137
|
+
matrice_analytics/post_processing/usecases/people_counting.py,sha256=mlzezqESW2qifW2PmsygWMjHLw6v8I34p9L2RwbxZMo,35267
|
|
138
138
|
matrice_analytics/post_processing/usecases/people_counting_bckp.py,sha256=WM9te7oYyhu5f_bIMye_D5BpEn6CwA-6Kz95IMLmSbs,82209
|
|
139
139
|
matrice_analytics/post_processing/usecases/people_tracking.py,sha256=iXzGJgqKgWxvIVLqa1cFKkiF0DrHolwghSiJ2P8mDhc,90484
|
|
140
140
|
matrice_analytics/post_processing/usecases/pipeline_detection.py,sha256=VsLTXMAqx0tRw7Olrxqx7SBLolZR7p2aFOrdSXLS-kE,30796
|
|
@@ -158,7 +158,7 @@ matrice_analytics/post_processing/usecases/theft_detection.py,sha256=Rs_zKn2z9YM
|
|
|
158
158
|
matrice_analytics/post_processing/usecases/traffic_sign_monitoring.py,sha256=nDlEzHgMlUjy_VtJ7usnEzMcdSs-jouqaoJpJ8DYUMw,34351
|
|
159
159
|
matrice_analytics/post_processing/usecases/underground_pipeline_defect_detection.py,sha256=W_2joZStsP0jl2zn89-jtdtqqGv3vJ0amsalbE5WKwo,37647
|
|
160
160
|
matrice_analytics/post_processing/usecases/underwater_pollution_detection.py,sha256=jqP1ZKfDZe2-56Lyvgb2DxnbqRfvxm6pPL0Ck3esfBk,40356
|
|
161
|
-
matrice_analytics/post_processing/usecases/vehicle_monitoring.py,sha256=
|
|
161
|
+
matrice_analytics/post_processing/usecases/vehicle_monitoring.py,sha256=QsO-coozfy29rY6NszwA6A7nFBOGysfMz5S5VVY7Beg,52849
|
|
162
162
|
matrice_analytics/post_processing/usecases/warehouse_object_segmentation.py,sha256=5uZXTJL_A3tUEN08T-_ZQpUoJ9gqbuuMc4z2mT4sMnQ,43753
|
|
163
163
|
matrice_analytics/post_processing/usecases/waterbody_segmentation.py,sha256=JsCxDEMB8s4WDcezfJDr2zrjM-TCjB9hxOztzSvWmpY,45268
|
|
164
164
|
matrice_analytics/post_processing/usecases/weapon_detection.py,sha256=AhbVpJaa2I3aRCEAdIxovY5xd9370dUY4JllCQ8tdT4,37185
|
|
@@ -188,8 +188,8 @@ matrice_analytics/post_processing/utils/format_utils.py,sha256=UTF7A5h9j0_S12xH9
|
|
|
188
188
|
matrice_analytics/post_processing/utils/geometry_utils.py,sha256=BWfdM6RsdJTTLR1GqkWfdwpjMEjTCJyuBxA4zVGKdfk,9623
|
|
189
189
|
matrice_analytics/post_processing/utils/smoothing_utils.py,sha256=78U-yucAcjUiZ0NIAc9NOUSIT0PWP1cqyIPA_Fdrjp0,14699
|
|
190
190
|
matrice_analytics/post_processing/utils/tracking_utils.py,sha256=rWxuotnJ3VLMHIBOud2KLcu4yZfDp7hVPWUtNAq_2xw,8288
|
|
191
|
-
matrice_analytics-0.1.
|
|
192
|
-
matrice_analytics-0.1.
|
|
193
|
-
matrice_analytics-0.1.
|
|
194
|
-
matrice_analytics-0.1.
|
|
195
|
-
matrice_analytics-0.1.
|
|
191
|
+
matrice_analytics-0.1.44.dist-info/licenses/LICENSE.txt,sha256=_uQUZpgO0mRYL5-fPoEvLSbNnLPv6OmbeEDCHXhK6Qc,1066
|
|
192
|
+
matrice_analytics-0.1.44.dist-info/METADATA,sha256=fdA7eR44gue1uKeUrOE0fDpgx2bIsqXH2-h4uOuNiDY,14378
|
|
193
|
+
matrice_analytics-0.1.44.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
194
|
+
matrice_analytics-0.1.44.dist-info/top_level.txt,sha256=STAPEU-e-rWTerXaspdi76T_eVRSrEfFpURSP7_Dt8E,18
|
|
195
|
+
matrice_analytics-0.1.44.dist-info/RECORD,,
|
|
File without changes
|
{matrice_analytics-0.1.43.dist-info → matrice_analytics-0.1.44.dist-info}/licenses/LICENSE.txt
RENAMED
|
File without changes
|
|
File without changes
|