matrice 1.0.99139__py3-none-any.whl → 1.0.99141__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.
@@ -22,7 +22,7 @@ from ..core.config import BaseConfig, AlertConfig, ZoneConfig
22
22
 
23
23
  @dataclass
24
24
  class ConcreteCrackConfig(BaseConfig):
25
- """Configuration for concrete crack detection use case in concrete crack monitoring."""
25
+ """Configuration for Concrete Crack detection use case."""
26
26
  # Smoothing configuration
27
27
  enable_smoothing: bool = True
28
28
  smoothing_algorithm: str = "observability" # "window" or "observability"
@@ -31,14 +31,14 @@ class ConcreteCrackConfig(BaseConfig):
31
31
  smoothing_confidence_range_factor: float = 0.5
32
32
 
33
33
  #confidence thresholds
34
- confidence_threshold: float = 0.2
34
+ confidence_threshold: float = 0.6
35
35
 
36
36
  usecase_categories: List[str] = field(
37
- default_factory=lambda: ['Cracks']
37
+ default_factory=lambda: ["Cracks"]
38
38
  )
39
39
 
40
40
  target_categories: List[str] = field(
41
- default_factory=lambda: ['Cracks']
41
+ default_factory=lambda: ["Cracks"]
42
42
  )
43
43
 
44
44
  alert_config: Optional[AlertConfig] = None
@@ -55,23 +55,23 @@ class ConcreteCrackUseCase(BaseProcessor):
55
55
  CATEGORY_DISPLAY = {
56
56
  "Cracks": "Cracks",
57
57
  }
58
-
58
+
59
+
59
60
  def __init__(self):
60
61
  super().__init__("concrete_crack_detection")
61
62
  self.category = "general"
62
63
 
63
64
  self.CASE_TYPE: Optional[str] = 'concrete_crack_detection'
64
- self.CASE_VERSION: Optional[str] = '1.3'
65
-
65
+ self.CASE_VERSION: Optional[str] = '1.2'
66
66
  # List of categories to track
67
- self.target_categories = ['Cracks']
67
+ self.target_categories = ["Cracks"]
68
+
68
69
 
69
70
  # Initialize smoothing tracker
70
71
  self.smoothing_tracker = None
71
72
 
72
73
  # Initialize advanced tracker (will be created on first use)
73
74
  self.tracker = None
74
-
75
75
  # Initialize tracking state variables
76
76
  self._total_frame_counter = 0
77
77
  self._global_frame_offset = 0
@@ -88,6 +88,7 @@ class ConcreteCrackUseCase(BaseProcessor):
88
88
  self._ascending_alert_list: List[int] = []
89
89
  self.current_incident_end_timestamp: str = "N/A"
90
90
 
91
+
91
92
  def process(self, data: Any, config: ConfigProtocol, context: Optional[ProcessingContext] = None,
92
93
  stream_info: Optional[Dict[str, Any]] = None) -> ProcessingResult:
93
94
  """
@@ -107,8 +108,6 @@ class ConcreteCrackUseCase(BaseProcessor):
107
108
  input_format = match_results_structure(data)
108
109
  context.input_format = input_format
109
110
  context.confidence_threshold = config.confidence_threshold
110
-
111
-
112
111
 
113
112
  if config.confidence_threshold is not None:
114
113
  processed_data = filter_by_confidence(data, config.confidence_threshold)
@@ -117,19 +116,15 @@ class ConcreteCrackUseCase(BaseProcessor):
117
116
  processed_data = data
118
117
 
119
118
  self.logger.debug(f"Did not apply confidence filtering with threshold since nothing was provided")
120
- print("---------------------processed_1-----------------------------------")
121
- print(processed_data)
119
+
122
120
  # Step 2: Apply category mapping if provided
123
121
  if config.index_to_category:
124
122
  processed_data = apply_category_mapping(processed_data, config.index_to_category)
125
123
  self.logger.debug("Applied category mapping")
126
- print("---------------------processed_2-----------------------------------")
127
- print(processed_data)
124
+
128
125
  if config.target_categories:
129
126
  processed_data = [d for d in processed_data if d.get('category') in self.target_categories]
130
127
  self.logger.debug(f"Applied category filtering")
131
- print("---------------------processed_3-----------------------------------")
132
- print(processed_data)
133
128
 
134
129
  # Apply bbox smoothing if enabled
135
130
  if config.enable_smoothing:
@@ -143,9 +138,8 @@ class ConcreteCrackUseCase(BaseProcessor):
143
138
  enable_smoothing=True
144
139
  )
145
140
  self.smoothing_tracker = BBoxSmoothingTracker(smoothing_config)
146
- print("---------------------processed_4-----------------------------------")
147
141
  processed_data = bbox_smoothing(processed_data, self.smoothing_tracker.config, self.smoothing_tracker)
148
- print(processed_data)
142
+
149
143
  # Advanced tracking (BYTETracker-like)
150
144
  try:
151
145
  from ..advanced_tracker import AdvancedTracker
@@ -153,15 +147,29 @@ class ConcreteCrackUseCase(BaseProcessor):
153
147
 
154
148
  # Create tracker instance if it doesn't exist (preserves state across frames)
155
149
  if self.tracker is None:
156
- tracker_config = TrackerConfig()
150
+ # Configure tracker thresholds based on the use-case confidence threshold so that
151
+ # low-confidence detections (e.g. < 0.7) can still be initialised as tracks when
152
+ # the user passes a lower `confidence_threshold` in the post-processing config.
153
+ if config.confidence_threshold is not None:
154
+ tracker_config = TrackerConfig(
155
+ track_high_thresh=float(config.confidence_threshold),
156
+ # Allow even lower detections to participate in secondary association
157
+ track_low_thresh=max(0.05, float(config.confidence_threshold) / 2),
158
+ new_track_thresh=float(config.confidence_threshold)
159
+ )
160
+ else:
161
+ tracker_config = TrackerConfig()
157
162
  self.tracker = AdvancedTracker(tracker_config)
158
- self.logger.info("Initialized AdvancedTracker for Monitoring and tracking")
163
+ self.logger.info(
164
+ "Initialized AdvancedTracker for Monitoring and tracking with thresholds: "
165
+ f"high={tracker_config.track_high_thresh}, "
166
+ f"low={tracker_config.track_low_thresh}, "
167
+ f"new={tracker_config.new_track_thresh}"
168
+ )
159
169
 
160
170
  # The tracker expects the data in the same format as input
161
171
  # It will add track_id and frame_id to each detection
162
172
  processed_data = self.tracker.update(processed_data)
163
- print("---------------------processed_4-----------------------------------")
164
- print(processed_data)
165
173
 
166
174
  except Exception as e:
167
175
  # If advanced tracker fails, fallback to unsmoothed detections
@@ -189,16 +197,14 @@ class ConcreteCrackUseCase(BaseProcessor):
189
197
  # Add total unique counts after tracking using only local state
190
198
  total_counts = self.get_total_counts()
191
199
  counting_summary['total_counts'] = total_counts
192
- print("---------------------counting_summ-----------------------------------")
193
- print(counting_summary)
200
+
194
201
  alerts = self._check_alerts(counting_summary, frame_number, config)
195
202
  predictions = self._extract_predictions(processed_data)
196
203
 
197
204
  # Step: Generate structured incidents, tracking stats and business analytics with frame-based keys
198
205
  incidents_list = self._generate_incidents(counting_summary, alerts, config, frame_number, stream_info)
199
206
  tracking_stats_list = self._generate_tracking_stats(counting_summary, alerts, config, frame_number, stream_info)
200
- # business_analytics_list = self._generate_business_analytics(counting_summary, alerts, config, frame_number, stream_info, is_empty=True)
201
- business_analytics_list = []
207
+ business_analytics_list = self._generate_business_analytics(counting_summary, alerts, config, stream_info, is_empty=True)
202
208
  summary_list = self._generate_summary(counting_summary, incidents_list, tracking_stats_list, business_analytics_list, alerts)
203
209
 
204
210
  # Extract frame-based dictionaries from the lists
@@ -213,8 +219,8 @@ class ConcreteCrackUseCase(BaseProcessor):
213
219
  "alerts": alerts,
214
220
  "human_text": summary}
215
221
  }
216
-
217
-
222
+
223
+
218
224
  context.mark_completed()
219
225
 
220
226
  # Build result object following the new pattern
@@ -276,8 +282,8 @@ class ConcreteCrackUseCase(BaseProcessor):
276
282
  "threshold_level": threshold,
277
283
  "ascending": get_trend(self._ascending_alert_list, lookback=900, threshold=0.8),
278
284
  "settings": {t: v for t, v in zip(getattr(config.alert_config, 'alert_type', ['Default']) if hasattr(config.alert_config, 'alert_type') else ['Default'],
279
- getattr(config.alert_config, 'alert_value', ['JSON']) if hasattr(config.alert_config, 'alert_value') else ['JSON'])
280
- }
285
+ getattr(config.alert_config, 'alert_value', ['JSON']) if hasattr(config.alert_config, 'alert_value') else ['JSON'])
286
+ }
281
287
  })
282
288
  elif category in summary.get("per_category_count", {}):
283
289
  count = summary.get("per_category_count", {})[category]
@@ -289,15 +295,15 @@ class ConcreteCrackUseCase(BaseProcessor):
289
295
  "threshold_level": threshold,
290
296
  "ascending": get_trend(self._ascending_alert_list, lookback=900, threshold=0.8),
291
297
  "settings": {t: v for t, v in zip(getattr(config.alert_config, 'alert_type', ['Default']) if hasattr(config.alert_config, 'alert_type') else ['Default'],
292
- getattr(config.alert_config, 'alert_value', ['JSON']) if hasattr(config.alert_config, 'alert_value') else ['JSON'])
293
- }
298
+ getattr(config.alert_config, 'alert_value', ['JSON']) if hasattr(config.alert_config, 'alert_value') else ['JSON'])
299
+ }
294
300
  })
295
301
  else:
296
302
  pass
297
303
  return alerts
298
304
 
299
305
  def _generate_incidents(self, counting_summary: Dict, alerts: List, config: ConcreteCrackConfig,
300
- frame_number: Optional[int] = None, stream_info: Optional[Dict[str, Any]] = None) -> List[
306
+ frame_number: Optional[int] = None, stream_info: Optional[Dict[str, Any]] = None) -> List[
301
307
  Dict]:
302
308
  """Generate structured incidents for the output format with frame-based keys."""
303
309
 
@@ -355,12 +361,12 @@ class ConcreteCrackUseCase(BaseProcessor):
355
361
  intensity = min(10.0, total_detections / 3.0)
356
362
  self._ascending_alert_list.append(0)
357
363
 
358
- # Generate human text in new format
364
+ # Generate human text in new format
359
365
  human_text_lines = [f"INCIDENTS DETECTED @ {current_timestamp}:"]
360
366
  human_text_lines.append(f"\tSeverity Level: {(self.CASE_TYPE,level)}")
361
367
  human_text = "\n".join(human_text_lines)
362
368
 
363
- alert_settings = []
369
+ alert_settings=[]
364
370
  if config.alert_config and hasattr(config.alert_config, 'alert_type'):
365
371
  alert_settings.append({
366
372
  "alert_type": getattr(config.alert_config, 'alert_type', ['Default']) if hasattr(config.alert_config, 'alert_type') else ['Default'],
@@ -373,17 +379,16 @@ class ConcreteCrackUseCase(BaseProcessor):
373
379
  })
374
380
 
375
381
  event= self.create_incident(incident_id=self.CASE_TYPE+'_'+str(frame_number), incident_type=self.CASE_TYPE,
376
- severity_level=level, human_text=human_text, camera_info=camera_info, alerts=alerts, alert_settings=alert_settings,
377
- start_time=start_timestamp, end_time=self.current_incident_end_timestamp,
378
- level_settings= {"low": 1, "medium": 3, "significant":4, "critical": 7})
382
+ severity_level=level, human_text=human_text, camera_info=camera_info, alerts=alerts, alert_settings=alert_settings,
383
+ start_time=start_timestamp, end_time=self.current_incident_end_timestamp,
384
+ level_settings= {"low": 1, "medium": 3, "significant":4, "critical": 7})
379
385
  incidents.append(event)
380
386
 
381
387
  else:
382
388
  self._ascending_alert_list.append(0)
383
389
  incidents.append({})
384
-
390
+
385
391
  return incidents
386
-
387
392
  def _generate_tracking_stats(
388
393
  self,
389
394
  counting_summary: Dict,
@@ -421,8 +426,7 @@ class ConcreteCrackUseCase(BaseProcessor):
421
426
  "category": cat,
422
427
  "count": count
423
428
  })
424
- print("-----------------------------total_counts---------------------------------------")
425
- print(total_counts)
429
+
426
430
  # Build current_counts array in expected format
427
431
  current_counts = []
428
432
  for cat, count in per_category_count.items():
@@ -431,8 +435,7 @@ class ConcreteCrackUseCase(BaseProcessor):
431
435
  "category": cat,
432
436
  "count": count
433
437
  })
434
- print("----------------------------------current_counts---------------------------------------")
435
- print(current_counts)
438
+
436
439
  # Prepare detections without confidence scores (as per eg.json)
437
440
  detections = []
438
441
  for detection in counting_summary.get("detections", []):
@@ -484,9 +487,7 @@ class ConcreteCrackUseCase(BaseProcessor):
484
487
  human_text_lines.append("Alerts: None")
485
488
 
486
489
  human_text = "\n".join(human_text_lines)
487
- print("-------------------------------human_text-----------------------------------------------------")
488
- print(human_text)
489
- reset_settings = [
490
+ reset_settings=[
490
491
  {
491
492
  "interval_type": "daily",
492
493
  "reset_time": {
@@ -497,14 +498,14 @@ class ConcreteCrackUseCase(BaseProcessor):
497
498
  ]
498
499
 
499
500
  tracking_stat=self.create_tracking_stats(total_counts=total_counts, current_counts=current_counts,
500
- detections=detections, human_text=human_text, camera_info=camera_info, alerts=alerts, alert_settings=alert_settings,
501
- reset_settings=reset_settings, start_time=high_precision_start_timestamp ,
502
- reset_time=high_precision_reset_timestamp)
501
+ detections=detections, human_text=human_text, camera_info=camera_info, alerts=alerts, alert_settings=alert_settings,
502
+ reset_settings=reset_settings, start_time=high_precision_start_timestamp ,
503
+ reset_time=high_precision_reset_timestamp)
503
504
 
504
505
  tracking_stats.append(tracking_stat)
505
506
  return tracking_stats
506
507
 
507
- def _generate_business_analytics(self, counting_summary: Dict, zone_analysis: Dict, config: ConcreteCrackConfig, stream_info: Optional[Dict[str, Any]] = None, is_empty=False) -> List[Dict]:
508
+ def _generate_business_analytics(self, counting_summary: Dict, alerts:Any, config: ConcreteCrackConfig, stream_info: Optional[Dict[str, Any]] = None, is_empty=False) -> List[Dict]:
508
509
  """Generate standardized business analytics for the agg_summary structure."""
509
510
  if is_empty:
510
511
  return []
@@ -587,6 +588,12 @@ class ConcreteCrackUseCase(BaseProcessor):
587
588
  Return total unique track_id count for each category.
588
589
  """
589
590
  return {cat: len(ids) for cat, ids in getattr(self, '_per_category_total_track_ids', {}).items()}
591
+
592
+
593
+ def _format_timestamp_for_stream(self, timestamp: float) -> str:
594
+ """Format timestamp for streams (YYYY:MM:DD HH:MM:SS format)."""
595
+ dt = datetime.fromtimestamp(timestamp, tz=timezone.utc)
596
+ return dt.strftime('%Y:%m:%d %H:%M:%S')
590
597
 
591
598
  def _format_timestamp_for_video(self, timestamp: float) -> str:
592
599
  """Format timestamp for video chunks (HH:MM:SS.ms format)."""
@@ -595,11 +602,6 @@ class ConcreteCrackUseCase(BaseProcessor):
595
602
  seconds = round(float(timestamp % 60),2)
596
603
  return f"{hours:02d}:{minutes:02d}:{seconds:.1f}"
597
604
 
598
- def _format_timestamp_for_stream(self, timestamp: float) -> str:
599
- """Format timestamp for streams (YYYY:MM:DD HH:MM:SS format)."""
600
- dt = datetime.fromtimestamp(timestamp, tz=timezone.utc)
601
- return dt.strftime('%Y:%m:%d %H:%M:%S')
602
-
603
605
  def _get_current_timestamp_str(self, stream_info: Optional[Dict[str, Any]], precision=False, frame_id: Optional[str]=None) -> str:
604
606
  """Get formatted current timestamp based on stream type."""
605
607
  if not stream_info:
@@ -675,6 +677,7 @@ class ConcreteCrackUseCase(BaseProcessor):
675
677
  dt = dt.replace(minute=0, second=0, microsecond=0)
676
678
  return dt.strftime('%Y:%m:%d %H:%M:%S')
677
679
 
680
+
678
681
  def _count_categories(self, detections: list, config: ConcreteCrackConfig) -> dict:
679
682
  """
680
683
  Count the number of detections per category and return a summary dict.
@@ -686,10 +689,6 @@ class ConcreteCrackUseCase(BaseProcessor):
686
689
  cat = det.get('category', 'unknown')
687
690
  counts[cat] = counts.get(cat, 0) + 1
688
691
  # Each detection dict will now include 'track_id' (and possibly 'frame_id')
689
- print("---------------------------------COUNTS-------------------------------------")
690
- print(counts)
691
- print("---------------------------------Detections-------------------------------------")
692
- print(detections)
693
692
  return {
694
693
  "total_count": sum(counts.values()),
695
694
  "per_category_count": counts,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matrice
3
- Version: 1.0.99139
3
+ Version: 1.0.99141
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
@@ -166,7 +166,7 @@ matrice/deploy/utils/post_processing/usecases/chicken_pose_detection.py,sha256=-
166
166
  matrice/deploy/utils/post_processing/usecases/child_monitoring.py,sha256=z3oymoqq4hDGwA8MkdEONZW_Vx5CAZmvzZaNLsqmCfw,39380
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
- matrice/deploy/utils/post_processing/usecases/concrete_crack_detection.py,sha256=9IVHC2z3FKu8Pg-UjQfNpIjx_4ssE520us3leeBe-dk,40624
169
+ matrice/deploy/utils/post_processing/usecases/concrete_crack_detection.py,sha256=pxhOH_hG4hq9yytNepbGMdk2W_lTG8D1_2RAagaPBkg,40252
170
170
  matrice/deploy/utils/post_processing/usecases/crop_weed_detection.py,sha256=i7BWhC-D7liOg9fzFHFg_upd1fdvXlVHYzDRyHL-AdM,40322
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
@@ -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.99139.dist-info/licenses/LICENSE.txt,sha256=2bm9uFabQZ3Ykb_SaSU_uUbAj2-htc6WJQmS_65qD00,1073
229
- matrice-1.0.99139.dist-info/METADATA,sha256=MvsxaJXsosePJ1fRCShaeA1k7WYQJRn5JIgT-0Okd2M,14624
230
- matrice-1.0.99139.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
231
- matrice-1.0.99139.dist-info/top_level.txt,sha256=P97js8ur6o5ClRqMH3Cjoab_NqbJ6sOQ3rJmVzKBvMc,8
232
- matrice-1.0.99139.dist-info/RECORD,,
228
+ matrice-1.0.99141.dist-info/licenses/LICENSE.txt,sha256=2bm9uFabQZ3Ykb_SaSU_uUbAj2-htc6WJQmS_65qD00,1073
229
+ matrice-1.0.99141.dist-info/METADATA,sha256=7aK3PJ9ODjlD7ASl79Bf8RxjOtZd474MsY2WvUoBAlA,14624
230
+ matrice-1.0.99141.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
231
+ matrice-1.0.99141.dist-info/top_level.txt,sha256=P97js8ur6o5ClRqMH3Cjoab_NqbJ6sOQ3rJmVzKBvMc,8
232
+ matrice-1.0.99141.dist-info/RECORD,,