Upload explanation.py with huggingface_hub
Browse files- explanation.py +39 -10
explanation.py
CHANGED
|
@@ -104,21 +104,50 @@ def generate_forensic_report(verdict: ForensicVerdict) -> str:
|
|
| 104 |
|
| 105 |
"""
|
| 106 |
|
| 107 |
-
#
|
| 108 |
modality_info = verdict.reasoning_tree.get("modality", {})
|
| 109 |
detected_modality = modality_info.get("detected", "UNKNOWN")
|
| 110 |
n_adjustments = modality_info.get("adjustments_applied", 0)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 111 |
|
| 112 |
if detected_modality != "UNKNOWN" and n_adjustments > 0:
|
| 113 |
-
modality_labels = {
|
| 114 |
-
"PORTRAIT_MODE": "smartphone portrait/bokeh mode",
|
| 115 |
-
"MESSAGING": "messaging app (WhatsApp, Telegram, etc.)",
|
| 116 |
-
"SOCIAL_MEDIA": "social media platform",
|
| 117 |
-
"SCREENSHOT": "screen capture",
|
| 118 |
-
"SMARTPHONE": "standard smartphone camera",
|
| 119 |
-
"DSLR": "DSLR/mirrorless camera",
|
| 120 |
-
}
|
| 121 |
-
label = modality_labels.get(detected_modality, detected_modality)
|
| 122 |
|
| 123 |
report += f"""---
|
| 124 |
|
|
|
|
| 104 |
|
| 105 |
"""
|
| 106 |
|
| 107 |
+
# Modality section — ALWAYS shown for diagnostic transparency
|
| 108 |
modality_info = verdict.reasoning_tree.get("modality", {})
|
| 109 |
detected_modality = modality_info.get("detected", "UNKNOWN")
|
| 110 |
n_adjustments = modality_info.get("adjustments_applied", 0)
|
| 111 |
+
indicators = modality_info.get("indicators", {})
|
| 112 |
+
|
| 113 |
+
modality_labels = {
|
| 114 |
+
"PORTRAIT_MODE": "smartphone portrait/bokeh mode",
|
| 115 |
+
"MESSAGING": "messaging app (WhatsApp, Telegram, etc.)",
|
| 116 |
+
"SOCIAL_MEDIA": "social media platform",
|
| 117 |
+
"SCREENSHOT": "screen capture",
|
| 118 |
+
"SMARTPHONE": "standard smartphone camera",
|
| 119 |
+
"DSLR": "DSLR/mirrorless camera",
|
| 120 |
+
"MACRO_DSLR": "DSLR macro/shallow DoF photography",
|
| 121 |
+
"UNKNOWN": "unknown (no suppression applied)",
|
| 122 |
+
}
|
| 123 |
+
label = modality_labels.get(detected_modality, detected_modality)
|
| 124 |
+
|
| 125 |
+
report += f"""---
|
| 126 |
+
|
| 127 |
+
## 📱 Capture Modality Detection
|
| 128 |
+
|
| 129 |
+
**Detected:** {detected_modality} — {label}
|
| 130 |
+
**Confidence:** {modality_info.get('confidence', 0):.0%}
|
| 131 |
+
**Tests recalibrated:** {n_adjustments}
|
| 132 |
+
|
| 133 |
+
**Detection signals:**
|
| 134 |
+
- Bayer CFA pattern: {'✅ Present' if indicators.get('has_bayer') else '❌ Absent'} (margin={indicators.get('bayer_margin', 0)})
|
| 135 |
+
- Peak sharpness (p95): {indicators.get('p95_sharpness', '?')}
|
| 136 |
+
- Bimodal ratio: {indicators.get('bimodal_ratio', '?')}
|
| 137 |
+
- Sharpness ratio (center/edge): {indicators.get('sharpness_ratio', '?')}
|
| 138 |
+
- Blur uniformity: {indicators.get('blur_uniformity', '?')}
|
| 139 |
+
- Has genuine detail: {indicators.get('has_detail', '?')}
|
| 140 |
+
"""
|
| 141 |
+
if indicators.get('safety_override'):
|
| 142 |
+
report += f"- ⚠️ **Safety override:** {indicators['safety_override']}\n"
|
| 143 |
+
if indicators.get('modality_scores'):
|
| 144 |
+
report += f"- Modality scores: {indicators['modality_scores']}\n"
|
| 145 |
+
if indicators.get('macro_detected'):
|
| 146 |
+
report += f"- 🔬 Macro photography detected (bg_color_std={indicators.get('bg_color_std', '?')})\n"
|
| 147 |
+
if indicators.get('portrait_detected'):
|
| 148 |
+
report += f"- 📱 Portrait mode detected\n"
|
| 149 |
|
| 150 |
if detected_modality != "UNKNOWN" and n_adjustments > 0:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
|
| 152 |
report += f"""---
|
| 153 |
|