Spaces:
Runtime error
Runtime error
Sync from GitHub via hub-sync
Browse files
services/report_service.py
CHANGED
|
@@ -205,12 +205,12 @@ def _resolve_media_path(value: Any) -> Path | None:
|
|
| 205 |
return None
|
| 206 |
|
| 207 |
|
| 208 |
-
def _image_from_base64(data: Any, max_width: float, max_height: float) -> Image:
|
| 209 |
-
"""Decode base64 image, embed as bytes in PDF, or return
|
| 210 |
raw = _clean(data)
|
| 211 |
if not raw:
|
| 212 |
logger.debug("No base64 image data provided")
|
| 213 |
-
return
|
| 214 |
try:
|
| 215 |
encoded = raw.split(",", 1)[1] if "," in raw else raw
|
| 216 |
blob = base64.b64decode(encoded)
|
|
@@ -224,15 +224,15 @@ def _image_from_base64(data: Any, max_width: float, max_height: float) -> Image:
|
|
| 224 |
stream.seek(0)
|
| 225 |
return _scaled_image(stream, width, height, max_width, max_height)
|
| 226 |
except Exception as exc: # noqa: BLE001
|
| 227 |
-
logger.warning(f"Base64 image decode failed: {exc}
|
| 228 |
-
return
|
| 229 |
|
| 230 |
|
| 231 |
-
def _image_from_path(path: Path | None, max_width: float, max_height: float) -> Image:
|
| 232 |
-
"""Load image from path, embed as bytes in PDF, or return
|
| 233 |
if path is None:
|
| 234 |
logger.debug("No image path provided")
|
| 235 |
-
return
|
| 236 |
try:
|
| 237 |
# Read the file as bytes and wrap in BytesIO for embedding in PDF
|
| 238 |
with open(path, 'rb') as f:
|
|
@@ -247,8 +247,8 @@ def _image_from_path(path: Path | None, max_width: float, max_height: float) ->
|
|
| 247 |
stream.seek(0)
|
| 248 |
return _scaled_image(stream, width, height, max_width, max_height)
|
| 249 |
except Exception as exc: # noqa: BLE001
|
| 250 |
-
logger.warning(f"Image not found at {path}: {exc}
|
| 251 |
-
return
|
| 252 |
|
| 253 |
|
| 254 |
def _scaled_image(source: Any, width: int, height: int, max_width: float, max_height: float) -> Image:
|
|
@@ -778,41 +778,64 @@ def _forensic_visuals(analysis_json: dict[str, Any], styles: dict[str, Paragraph
|
|
| 778 |
if media_type not in {"image", "screenshot", "video"}:
|
| 779 |
return []
|
| 780 |
expl = _as_dict(analysis_json.get("explainability"))
|
| 781 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 782 |
(
|
| 783 |
"Error Level Analysis (ELA)",
|
| 784 |
"Heatmap indicating areas of high compression loss, often associated with digital splicing.",
|
| 785 |
-
|
| 786 |
-
|
| 787 |
),
|
| 788 |
(
|
| 789 |
"Manipulation Region Overlay",
|
| 790 |
"Bounding boxes highlight regions the visual model treated as suspicious or manipulated.",
|
| 791 |
-
|
| 792 |
-
|
| 793 |
),
|
| 794 |
]
|
| 795 |
-
|
| 796 |
-
|
| 797 |
-
|
| 798 |
-
|
| 799 |
-
|
| 800 |
-
|
| 801 |
-
|
| 802 |
-
Paragraph(_xml(caption), styles["caption"]),
|
| 803 |
-
]
|
| 804 |
)
|
| 805 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 806 |
table.setStyle(
|
| 807 |
TableStyle(
|
| 808 |
[
|
| 809 |
("BACKGROUND", (0, 0), (-1, -1), PANEL),
|
| 810 |
("BOX", (0, 0), (-1, -1), 0.5, LINE),
|
| 811 |
("VALIGN", (0, 0), (-1, -1), "TOP"),
|
| 812 |
-
("LEFTPADDING", (0, 0), (-1, -1), 6),
|
| 813 |
("RIGHTPADDING", (0, 0), (-1, -1), 6),
|
| 814 |
-
("TOPPADDING", (0, 0), (-1, -1), 6),
|
| 815 |
-
("BOTTOMPADDING", (0, 0), (-1, -1), 6),
|
| 816 |
]
|
| 817 |
)
|
| 818 |
)
|
|
|
|
| 205 |
return None
|
| 206 |
|
| 207 |
|
| 208 |
+
def _image_from_base64(data: Any, max_width: float, max_height: float) -> Image | None:
|
| 209 |
+
"""Decode base64 image, embed as bytes in PDF, or return None with error logging."""
|
| 210 |
raw = _clean(data)
|
| 211 |
if not raw:
|
| 212 |
logger.debug("No base64 image data provided")
|
| 213 |
+
return None
|
| 214 |
try:
|
| 215 |
encoded = raw.split(",", 1)[1] if "," in raw else raw
|
| 216 |
blob = base64.b64decode(encoded)
|
|
|
|
| 224 |
stream.seek(0)
|
| 225 |
return _scaled_image(stream, width, height, max_width, max_height)
|
| 226 |
except Exception as exc: # noqa: BLE001
|
| 227 |
+
logger.warning(f"Base64 image decode failed: {exc}")
|
| 228 |
+
return None
|
| 229 |
|
| 230 |
|
| 231 |
+
def _image_from_path(path: Path | None, max_width: float, max_height: float) -> Image | None:
|
| 232 |
+
"""Load image from path, embed as bytes in PDF, or return None with error logging."""
|
| 233 |
if path is None:
|
| 234 |
logger.debug("No image path provided")
|
| 235 |
+
return None
|
| 236 |
try:
|
| 237 |
# Read the file as bytes and wrap in BytesIO for embedding in PDF
|
| 238 |
with open(path, 'rb') as f:
|
|
|
|
| 247 |
stream.seek(0)
|
| 248 |
return _scaled_image(stream, width, height, max_width, max_height)
|
| 249 |
except Exception as exc: # noqa: BLE001
|
| 250 |
+
logger.warning(f"Image not found at {path}: {exc}")
|
| 251 |
+
return None
|
| 252 |
|
| 253 |
|
| 254 |
def _scaled_image(source: Any, width: int, height: int, max_width: float, max_height: float) -> Image:
|
|
|
|
| 778 |
if media_type not in {"image", "screenshot", "video"}:
|
| 779 |
return []
|
| 780 |
expl = _as_dict(analysis_json.get("explainability"))
|
| 781 |
+
|
| 782 |
+
candidates = [
|
| 783 |
+
(
|
| 784 |
+
"AI Activation Heatmap",
|
| 785 |
+
"Grad-CAM++ activation showing regions the AI model focused on when making its decision.",
|
| 786 |
+
expl.get("heatmap_base64"),
|
| 787 |
+
expl.get("heatmap_url"),
|
| 788 |
+
),
|
| 789 |
(
|
| 790 |
"Error Level Analysis (ELA)",
|
| 791 |
"Heatmap indicating areas of high compression loss, often associated with digital splicing.",
|
| 792 |
+
expl.get("ela_base64"),
|
| 793 |
+
expl.get("ela_url"),
|
| 794 |
),
|
| 795 |
(
|
| 796 |
"Manipulation Region Overlay",
|
| 797 |
"Bounding boxes highlight regions the visual model treated as suspicious or manipulated.",
|
| 798 |
+
expl.get("boxes_base64"),
|
| 799 |
+
expl.get("boxes_url"),
|
| 800 |
),
|
| 801 |
]
|
| 802 |
+
|
| 803 |
+
visuals: list[tuple[str, str, Image]] = []
|
| 804 |
+
for title, caption, b64_data, url_data in candidates:
|
| 805 |
+
img = (
|
| 806 |
+
_image_from_base64(b64_data, 78 * mm, 58 * mm)
|
| 807 |
+
or _image_from_path(_resolve_media_path(url_data), 78 * mm, 58 * mm)
|
| 808 |
+
or _placeholder_image(78 * mm, 58 * mm)
|
|
|
|
|
|
|
| 809 |
)
|
| 810 |
+
visuals.append((title, caption, img))
|
| 811 |
+
|
| 812 |
+
rows = []
|
| 813 |
+
current_row = []
|
| 814 |
+
for title, caption, image in visuals:
|
| 815 |
+
current_row.append([
|
| 816 |
+
Paragraph(f"<b>{_xml(title)}</b>", styles["body"]),
|
| 817 |
+
image,
|
| 818 |
+
Paragraph(_xml(caption), styles["caption"]),
|
| 819 |
+
])
|
| 820 |
+
if len(current_row) == 2:
|
| 821 |
+
rows.append(current_row)
|
| 822 |
+
current_row = []
|
| 823 |
+
|
| 824 |
+
if current_row:
|
| 825 |
+
current_row.append([])
|
| 826 |
+
rows.append(current_row)
|
| 827 |
+
|
| 828 |
+
table = Table(rows, colWidths=[88 * mm, 88 * mm])
|
| 829 |
table.setStyle(
|
| 830 |
TableStyle(
|
| 831 |
[
|
| 832 |
("BACKGROUND", (0, 0), (-1, -1), PANEL),
|
| 833 |
("BOX", (0, 0), (-1, -1), 0.5, LINE),
|
| 834 |
("VALIGN", (0, 0), (-1, -1), "TOP"),
|
| 835 |
+
("LEFTPADDING", (0, 0), (-1, -1), 6),
|
| 836 |
("RIGHTPADDING", (0, 0), (-1, -1), 6),
|
| 837 |
+
("TOPPADDING", (0, 0), (-1, -1), 6),
|
| 838 |
+
("BOTTOMPADDING", (0, 0), (-1, -1), 6),
|
| 839 |
]
|
| 840 |
)
|
| 841 |
)
|
trained_models/config.json
DELETED
|
@@ -1,34 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"architectures": [
|
| 3 |
-
"ViTForImageClassification"
|
| 4 |
-
],
|
| 5 |
-
"attention_probs_dropout_prob": 0.0,
|
| 6 |
-
"dtype": "float32",
|
| 7 |
-
"encoder_stride": 16,
|
| 8 |
-
"hidden_act": "gelu",
|
| 9 |
-
"hidden_dropout_prob": 0.0,
|
| 10 |
-
"hidden_size": 768,
|
| 11 |
-
"id2label": {
|
| 12 |
-
"0": "fake",
|
| 13 |
-
"1": "real"
|
| 14 |
-
},
|
| 15 |
-
"image_size": 224,
|
| 16 |
-
"initializer_range": 0.02,
|
| 17 |
-
"intermediate_size": 3072,
|
| 18 |
-
"label2id": {
|
| 19 |
-
"fake": "0",
|
| 20 |
-
"real": "1"
|
| 21 |
-
},
|
| 22 |
-
"layer_norm_eps": 1e-12,
|
| 23 |
-
"model_type": "vit",
|
| 24 |
-
"num_attention_heads": 12,
|
| 25 |
-
"num_channels": 3,
|
| 26 |
-
"num_hidden_layers": 12,
|
| 27 |
-
"patch_size": 16,
|
| 28 |
-
"pooler_act": "tanh",
|
| 29 |
-
"pooler_output_size": 768,
|
| 30 |
-
"problem_type": "single_label_classification",
|
| 31 |
-
"qkv_bias": true,
|
| 32 |
-
"transformers_version": "5.0.0",
|
| 33 |
-
"use_cache": false
|
| 34 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
trained_models/deepfake_densenet121_threshold.json
DELETED
|
@@ -1,9 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"threshold": 0.7596627473831177,
|
| 3 |
-
"label_mapping": {
|
| 4 |
-
"fake": 0,
|
| 5 |
-
"real": 1
|
| 6 |
-
},
|
| 7 |
-
"image_size": 224,
|
| 8 |
-
"score_meaning": "score >= threshold predicts real; score < threshold predicts fake"
|
| 9 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
trained_models/densenet121_faces.pt
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:fd7320650302fca5588b497daec135dbec4eeca3c4e2030567f105914c013fd3
|
| 3 |
-
size 29474603
|
|
|
|
|
|
|
|
|
|
|
|
trained_models/densenet121_faces_meta.json
DELETED
|
@@ -1,21 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"threshold": 0.7596627473831177,
|
| 3 |
-
"image_size": 224,
|
| 4 |
-
"label_mapping": {
|
| 5 |
-
"fake": 0,
|
| 6 |
-
"real": 1
|
| 7 |
-
},
|
| 8 |
-
"score_meaning": "score >= threshold predicts real; score < threshold predicts fake",
|
| 9 |
-
"normalize_mean": [
|
| 10 |
-
0.485,
|
| 11 |
-
0.456,
|
| 12 |
-
0.406
|
| 13 |
-
],
|
| 14 |
-
"normalize_std": [
|
| 15 |
-
0.229,
|
| 16 |
-
0.224,
|
| 17 |
-
0.225
|
| 18 |
-
],
|
| 19 |
-
"source_keras": "deepfake_densenet121_high_acc.keras",
|
| 20 |
-
"architecture": "DenseNet121 + GlobalAvgPool + Linear(1024,256)+ReLU+BN+Dropout(0.3)+Linear(256,1)+Sigmoid"
|
| 21 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
trained_models/model.safetensors
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:ba81c341754d4bff4063b244e9aedececbd5298598c5cc954228b519e32c5f2c
|
| 3 |
-
size 343223968
|
|
|
|
|
|
|
|
|
|
|
|
trained_models/training_args.bin
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:20e4abfdaf3550867003b25ade080870f7e9f67ef5a154661d5c8a2b28047ef2
|
| 3 |
-
size 5201
|
|
|
|
|
|
|
|
|
|
|
|