coderuday21 commited on
Commit
105a05d
·
1 Parent(s): 2d5ff7e

AI/Hybrid overhaul: bidirectional AI fusion, stronger hybrid sensitivity, keep large unclassified regions

Browse files
Files changed (1) hide show
  1. app/detection_engine.py +37 -15
app/detection_engine.py CHANGED
@@ -348,15 +348,8 @@ def feature_based_method(img1, img2, num_clusters=4, sensitivity=0.5):
348
  return change_mask
349
 
350
 
351
- def ai_deep_learning_method(img1, img2, sensitivity=0.5):
352
- """
353
- Advanced multi-signal fusion:
354
- - Multi-scale color difference (LAB)
355
- - Structural dissimilarity (SSIM)
356
- - Texture change (LBP)
357
- - Edge change (Canny)
358
- All fused with learned weights and adaptive thresholding.
359
- """
360
  if img1.shape != img2.shape:
361
  img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0]))
362
 
@@ -445,7 +438,7 @@ def ai_deep_learning_method(img1, img2, sensitivity=0.5):
445
  _, change_mask = cv2.threshold(change_mask, 127, 255, cv2.THRESH_BINARY)
446
 
447
  debug = {
448
- "method": "AI-Based Deep Learning",
449
  "threshold_used": int(thr_score * 255),
450
  "threshold_percentile_q": q,
451
  "threshold_score": thr_score,
@@ -457,6 +450,30 @@ def ai_deep_learning_method(img1, img2, sensitivity=0.5):
457
  return change_mask, debug
458
 
459
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
460
  def hybrid_method(img1, img2, sensitivity=0.5):
461
  """Hybrid: weighted fusion of all methods with confidence-based merging."""
462
  if img1.shape != img2.shape:
@@ -477,11 +494,10 @@ def hybrid_method(img1, img2, sensitivity=0.5):
477
  # - diff only: 0.2*255 ≈ 51
478
  # - feature only: 0.3*255 ≈ 76
479
  # - ai only: 0.5*255 ≈ 127
480
- # Original threshold (140) effectively removed "ai-only" pixels.
481
- # Lower the threshold so AI (one of the key signals) can contribute.
482
- base_thr = 105
483
  sens = float(np.clip(sensitivity, 0.0, 1.0))
484
- hybrid_thr = int(np.clip(base_thr + int((0.5 - sens) * 30), 70, 160))
485
  _, final_mask = cv2.threshold(combined.astype(np.uint8), hybrid_thr, 255, cv2.THRESH_BINARY)
486
  final_mask = _clean_mask(final_mask)
487
  debug = {
@@ -1603,7 +1619,13 @@ def analyze_change_regions(change_mask, image, min_area=400, use_ensemble=True,
1603
  object_type, confidence = classify_object_type(image, (x, y, w, h))
1604
 
1605
  if object_type is None:
1606
- continue
 
 
 
 
 
 
1607
 
1608
  region_id += 1
1609
  region = {
 
348
  return change_mask
349
 
350
 
351
+ def _ai_fusion_core(img1, img2, sensitivity=0.5):
352
+ """One-direction AI fusion core. Returns (mask, debug)."""
 
 
 
 
 
 
 
353
  if img1.shape != img2.shape:
354
  img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0]))
355
 
 
438
  _, change_mask = cv2.threshold(change_mask, 127, 255, cv2.THRESH_BINARY)
439
 
440
  debug = {
441
+ "method": "AI-Core",
442
  "threshold_used": int(thr_score * 255),
443
  "threshold_percentile_q": q,
444
  "threshold_score": thr_score,
 
450
  return change_mask, debug
451
 
452
 
453
+ def ai_deep_learning_method(img1, img2, sensitivity=0.5):
454
+ """
455
+ Bidirectional AI fusion for robustness:
456
+ - run core on (before, after) and (after, before)
457
+ - combine with OR then clean
458
+ This improves stability for asymmetric scenes / normalization drift.
459
+ """
460
+ fwd_mask, fwd_debug = _ai_fusion_core(img1, img2, sensitivity=sensitivity)
461
+ rev_mask, rev_debug = _ai_fusion_core(img2, img1, sensitivity=sensitivity)
462
+
463
+ combined = cv2.bitwise_or(fwd_mask, rev_mask)
464
+ combined = _clean_mask(combined, sensitivity=sensitivity)
465
+
466
+ debug = {
467
+ "method": "AI-Based Deep Learning",
468
+ "threshold_used": fwd_debug.get("threshold_used"),
469
+ "bidirectional": True,
470
+ "forward": fwd_debug,
471
+ "reverse": rev_debug,
472
+ "sensitivity": float(sensitivity),
473
+ }
474
+ return combined, debug
475
+
476
+
477
  def hybrid_method(img1, img2, sensitivity=0.5):
478
  """Hybrid: weighted fusion of all methods with confidence-based merging."""
479
  if img1.shape != img2.shape:
 
494
  # - diff only: 0.2*255 ≈ 51
495
  # - feature only: 0.3*255 ≈ 76
496
  # - ai only: 0.5*255 ≈ 127
497
+ # Keep threshold low enough that ai-only regions can pass.
498
+ base_thr = 98
 
499
  sens = float(np.clip(sensitivity, 0.0, 1.0))
500
+ hybrid_thr = int(np.clip(base_thr + int((0.5 - sens) * 36), 60, 150))
501
  _, final_mask = cv2.threshold(combined.astype(np.uint8), hybrid_thr, 255, cv2.THRESH_BINARY)
502
  final_mask = _clean_mask(final_mask)
503
  debug = {
 
1619
  object_type, confidence = classify_object_type(image, (x, y, w, h))
1620
 
1621
  if object_type is None:
1622
+ # Do not silently drop large coherent regions; keep them as generic
1623
+ # ground-change candidates so key changes are still surfaced.
1624
+ if raw_area >= max(min_area * 2, 800) and fill_ratio >= 0.18:
1625
+ object_type = "Unclassified Ground Change"
1626
+ confidence = max(0.2, min(0.5, fill_ratio))
1627
+ else:
1628
+ continue
1629
 
1630
  region_id += 1
1631
  region = {