ar07xd commited on
Commit
e431769
·
verified ·
1 Parent(s): 966eea4

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 placeholder with error logging."""
210
  raw = _clean(data)
211
  if not raw:
212
  logger.debug("No base64 image data provided")
213
- return _placeholder_image(max_width, max_height)
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} — using placeholder")
228
- return _placeholder_image(max_width, max_height)
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 placeholder with error logging."""
233
  if path is None:
234
  logger.debug("No image path provided")
235
- return _placeholder_image(max_width, max_height)
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} — using placeholder")
251
- return _placeholder_image(max_width, max_height)
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
- visuals: list[tuple[str, str, Image | None]] = [
 
 
 
 
 
 
 
782
  (
783
  "Error Level Analysis (ELA)",
784
  "Heatmap indicating areas of high compression loss, often associated with digital splicing.",
785
- _image_from_base64(expl.get("ela_base64"), 78 * mm, 58 * mm)
786
- or _image_from_path(_resolve_media_path(expl.get("ela_url")), 78 * mm, 58 * mm),
787
  ),
788
  (
789
  "Manipulation Region Overlay",
790
  "Bounding boxes highlight regions the visual model treated as suspicious or manipulated.",
791
- _image_from_base64(expl.get("boxes_base64"), 78 * mm, 58 * mm)
792
- or _image_from_path(_resolve_media_path(expl.get("boxes_url")), 78 * mm, 58 * mm),
793
  ),
794
  ]
795
- cells: list[Any] = []
796
- for title, caption, image in visuals:
797
- # Images are never None now (placeholder returned if unavailable)
798
- cells.append(
799
- [
800
- Paragraph(f"<b>{_xml(title)}</b>", styles["body"]),
801
- image,
802
- Paragraph(_xml(caption), styles["caption"]),
803
- ]
804
  )
805
- table = Table([cells], colWidths=[88 * mm, 88 * mm])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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), # Reduced from 10
813
  ("RIGHTPADDING", (0, 0), (-1, -1), 6),
814
- ("TOPPADDING", (0, 0), (-1, -1), 6), # Reduced from 10
815
- ("BOTTOMPADDING", (0, 0), (-1, -1), 6), # Reduced from 10
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