Anish commited on
Commit
cd801e4
·
1 Parent(s): f49287c

[Updated Features] > Updated explainer and attribution with a new model, and support for better heatmap.

Browse files
backend/app/ai/attribution.py CHANGED
@@ -1,56 +1,83 @@
1
  import torch
2
  import cv2
3
  import numpy as np
4
- import timm
5
  from PIL import Image
6
- from torchvision import transforms
 
7
 
8
- model = timm.create_model("efficientnet_b0", pretrained=True)
9
- model.eval()
10
 
11
- transform = transforms.Compose([
12
- transforms.Resize((224, 224)),
13
- transforms.ToTensor(),
14
- transforms.Normalize(
15
- mean=[0.485, 0.456, 0.406],
16
- std=[0.229, 0.224, 0.225]
17
- )
18
- ])
19
 
20
  def generate_attribution(image_path: str, save_path: str) -> dict:
21
- img = Image.open(image_path).convert("RGB")
22
- x = transform(img).unsqueeze(0)
23
-
24
- x.requires_grad = True
25
-
26
- features = model.forward_features(x)
27
-
28
- score = features.mean()
29
- model.zero_grad()
30
- score.backward()
31
-
32
- gradients = x.grad[0].numpy()
33
- weights = np.mean(gradients, axis=(1, 2))
34
-
35
- cam = np.zeros(gradients.shape[1:], dtype=np.float32)
36
- for i, w in enumerate(weights):
37
- cam += w * np.maximum(gradients[i], 0)
38
-
39
- cam = cv2.resize(cam, (img.width, img.height))
40
- if cam.max() != 0:
41
- cam = cam / cam.max()
42
-
43
- heatmap = np.uint8(255 * cam)
44
- heatmap_colored = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
45
- original = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
46
- overlay = cv2.addWeighted(original, 0.6, heatmap_colored, 0.4, 0)
47
- cv2.imwrite(save_path, overlay)
48
-
49
- y, x_coord = np.unravel_index(np.argmax(cam), cam.shape)
50
-
51
- return {
52
- "heatmap_path": save_path,
53
- "top_regions": [
54
- {"x": int(x_coord), "y": int(y), "importance": float(cam.max())}
55
- ]
56
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import torch
2
  import cv2
3
  import numpy as np
 
4
  from PIL import Image
5
+ from transformers import AutoImageProcessor, AutoModelForImageClassification
6
+ import logging
7
 
8
+ logger = logging.getLogger(__name__)
 
9
 
10
+ model_id = "prithivMLmods/Deep-Fake-Detector-Model"
11
+ processor = AutoImageProcessor.from_pretrained(model_id)
12
+ model = AutoModelForImageClassification.from_pretrained(model_id)
13
+ model.eval()
 
 
 
 
14
 
15
  def generate_attribution(image_path: str, save_path: str) -> dict:
16
+ try:
17
+ img = Image.open(image_path).convert("RGB")
18
+ original_cv = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
19
+
20
+ inputs = processor(images=img, return_tensors="pt")
21
+ x = inputs["pixel_values"]
22
+
23
+ target_layer = model.vision_model.encoder.layers[-1].layer_norm1
24
+
25
+ activations = []
26
+ gradients = []
27
+
28
+ def forward_hook(module, args, output):
29
+ activations.append(output.detach())
30
+
31
+ def backward_hook(module, grad_input, grad_output):
32
+ gradients.append(grad_output[0].detach())
33
+
34
+ handle_forward = target_layer.register_forward_hook(forward_hook)
35
+ handle_backward = target_layer.register_full_backward_hook(backward_hook)
36
+
37
+ outputs = model(x)
38
+ logits = outputs.logits
39
+ target_class = logits.argmax(dim=-1).item()
40
+
41
+ score = logits[0, target_class]
42
+ model.zero_grad()
43
+ score.backward()
44
+
45
+ handle_forward.remove()
46
+ handle_backward.remove()
47
+
48
+ act = activations[0][0]
49
+ grad = gradients[0][0]
50
+ weights = torch.mean(grad, dim=0)
51
+
52
+ cam = torch.zeros(act.shape[0])
53
+ for i in range(act.shape[1]):
54
+ cam += weights[i] * act[:, i]
55
+
56
+ cam = cam.numpy()
57
+ cam = cam.reshape(14, 14)
58
+
59
+ cam = np.maximum(cam, 0)
60
+ cam = cam - np.min(cam)
61
+ if np.max(cam) != 0:
62
+ cam = cam / np.max(cam)
63
+
64
+ cam_resized = cv2.resize(cam, (img.width, img.height), interpolation=cv2.INTER_CUBIC)
65
+
66
+ heatmap_uint8 = np.uint8(255 * cam_resized)
67
+ heatmap_colored = cv2.applyColorMap(heatmap_uint8, cv2.COLORMAP_INFERNO)
68
+ overlay = cv2.addWeighted(original_cv, 0.6, heatmap_colored, 0.4, 0)
69
+
70
+ cv2.imwrite(save_path, overlay)
71
+
72
+ y, x_coord = np.unravel_index(np.argmax(cam_resized), cam_resized.shape)
73
+
74
+ return {
75
+ "heatmap_path": save_path,
76
+ "top_regions": [
77
+ {"x": int(x_coord), "y": int(y), "importance": float(np.max(cam_resized))}
78
+ ]
79
+ }
80
+
81
+ except Exception as e:
82
+ logger.error(f"Failed to generate attribution map: {str(e)}")
83
+ raise
backend/app/ai/explainer.py CHANGED
@@ -2,38 +2,75 @@ import torch
2
  import numpy as np
3
  import cv2
4
  from PIL import Image
5
- import matplotlib.pyplot as plt
6
- import timm
7
 
8
- model = timm.create_model("efficientnet_b0", pretrained=True)
 
 
 
 
9
  model.eval()
10
 
11
  def generate_heatmap(image_path: str, save_path: str):
12
- img = Image.open(image_path).convert("RGB")
13
- img = img.resize((224, 224))
14
-
15
- img_np = np.array(img) / 255.0
16
- input_tensor = torch.tensor(img_np.transpose(2, 0, 1)).unsqueeze(0).float()
17
-
18
- input_tensor.requires_grad = True
19
-
20
- features = model.forward_features(input_tensor)
21
-
22
- score = features.mean()
23
- score.backward()
24
-
25
- gradient = input_tensor.grad[0].numpy()
26
- heatmap = np.mean(np.abs(gradient), axis=0)
27
-
28
- heatmap = cv2.resize(heatmap, (img.width, img.height))
29
- heatmap = heatmap / heatmap.max()
30
-
31
- heatmap = cv2.applyColorMap(np.uint8(255 * heatmap), cv2.COLORMAP_JET)
32
-
33
- original = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
34
-
35
- overlay = cv2.addWeighted(original, 0.6, heatmap, 0.4, 0)
36
-
37
- cv2.imwrite(save_path, overlay)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
- return save_path
 
 
 
2
  import numpy as np
3
  import cv2
4
  from PIL import Image
5
+ from transformers import AutoImageProcessor, AutoModelForImageClassification
6
+ import logging
7
 
8
+ logger = logging.getLogger(__name__)
9
+
10
+ model_id = "prithivMLmods/Deep-Fake-Detector-Model"
11
+ processor = AutoImageProcessor.from_pretrained(model_id)
12
+ model = AutoModelForImageClassification.from_pretrained(model_id)
13
  model.eval()
14
 
15
  def generate_heatmap(image_path: str, save_path: str):
16
+ try:
17
+ img = Image.open(image_path).convert("RGB")
18
+ original_cv = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
19
+
20
+ inputs = processor(images=img, return_tensors="pt")
21
+ x = inputs["pixel_values"]
22
+
23
+ target_layer = model.vision_model.encoder.layers[-1].layer_norm1
24
+
25
+ activations = []
26
+ gradients = []
27
+
28
+ def forward_hook(module, args, output):
29
+ activations.append(output.detach())
30
+
31
+ def backward_hook(module, grad_input, grad_output):
32
+ gradients.append(grad_output[0].detach())
33
+
34
+ handle_forward = target_layer.register_forward_hook(forward_hook)
35
+ handle_backward = target_layer.register_full_backward_hook(backward_hook)
36
+
37
+ outputs = model(x)
38
+ logits = outputs.logits
39
+ target_class = logits.argmax(dim=-1).item()
40
+ score = logits[0, target_class]
41
+
42
+ model.zero_grad()
43
+ score.backward()
44
+
45
+ handle_forward.remove()
46
+ handle_backward.remove()
47
+
48
+ act = activations[0][0]
49
+ grad = gradients[0][0]
50
+ weights = torch.mean(grad, dim=0)
51
+
52
+ cam = torch.zeros(act.shape[0])
53
+ for i in range(act.shape[1]):
54
+ cam += weights[i] * act[:, i]
55
+
56
+ cam = cam.numpy()
57
+ cam = cam.reshape(14, 14)
58
+
59
+ cam = np.maximum(cam, 0)
60
+ cam = cam - np.min(cam)
61
+ if np.max(cam) != 0:
62
+ cam = cam / np.max(cam)
63
+
64
+ heatmap_resized = cv2.resize(cam, (img.width, img.height), interpolation=cv2.INTER_CUBIC)
65
+
66
+ heatmap_uint8 = np.uint8(255 * heatmap_resized)
67
+ heatmap_colored = cv2.applyColorMap(heatmap_uint8, cv2.COLORMAP_INFERNO)
68
+
69
+ overlay = cv2.addWeighted(original_cv, 0.6, heatmap_colored, 0.4, 0)
70
+ cv2.imwrite(save_path, overlay)
71
+
72
+ return save_path
73
 
74
+ except Exception as e:
75
+ logger.error(f"Failed to generate heatmap: {str(e)}")
76
+ raise
backend/app/ai/video/frame_detector.py CHANGED
@@ -1,6 +1,5 @@
1
  import torch
2
- import torch.nn as nn
3
- from torchvision import models, transforms
4
  from PIL import Image
5
  import numpy as np
6
  import logging
@@ -12,23 +11,15 @@ class FrameDetector:
12
  self.device = torch.device("cpu")
13
 
14
  try:
15
- self.model = models.efficientnet_b0(weights=models.EfficientNet_B0_Weights.IMAGENET1K_V1)
16
-
17
- for param in self.model.parameters():
18
- param.requires_grad = False
19
-
20
- num_ftrs = self.model.classifier[1].in_features
21
- self.model.classifier[1] = nn.Linear(num_ftrs, 1)
22
-
23
  self.model = self.model.to(self.device)
24
  self.model.eval()
25
 
26
- self.transforms = transforms.Compose([
27
- transforms.Resize((224, 224)),
28
- transforms.ToTensor(),
29
- transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
30
- ])
31
- logger.info("EfficientNet-B0 CPU Inference Engine Initialized Successfully.")
32
 
33
  except Exception as e:
34
  logger.error(f"FATAL: Could not boot AI model: {str(e)}")
@@ -45,13 +36,16 @@ class FrameDetector:
45
  rgb_frame = frame[:, :, ::-1]
46
  pil_image = Image.fromarray(rgb_frame)
47
 
48
- input_tensor = self.transforms(pil_image).unsqueeze(0).to(self.device)
49
 
50
  with torch.no_grad():
51
- raw_score = self.model(input_tensor)
52
- probability = torch.sigmoid(raw_score).item()
 
 
 
53
 
54
- return probability
55
 
56
  except Exception as e:
57
  logger.error(f"AI Frame Prediction Crashed: {str(e)}")
 
1
  import torch
2
+ from transformers import AutoImageProcessor, AutoModelForImageClassification
 
3
  from PIL import Image
4
  import numpy as np
5
  import logging
 
11
  self.device = torch.device("cpu")
12
 
13
  try:
14
+ model_id = "prithivMLmods/Deep-Fake-Detector-Model"
15
+ self.processor = ViTImageProcessor.from_pretrained(model_id)
16
+ self.model = ViTForImageClassification.from_pretrained(model_id)
 
 
 
 
 
17
  self.model = self.model.to(self.device)
18
  self.model.eval()
19
 
20
+ logger.info(f"Loaded {model_id} CPU Inference Engine Successfully.")
21
+
22
+ self.fake_label_idx = 1 if "fake" in str(self.model.config.id2label.get(1, "").lower()) else 0
 
 
 
23
 
24
  except Exception as e:
25
  logger.error(f"FATAL: Could not boot AI model: {str(e)}")
 
36
  rgb_frame = frame[:, :, ::-1]
37
  pil_image = Image.fromarray(rgb_frame)
38
 
39
+ inputs = self.processor(images=pil_image, return_tensors="pt").to(self.device)
40
 
41
  with torch.no_grad():
42
+ outputs = self.model(**inputs)
43
+ logits = outputs.logits
44
+
45
+ probs = torch.nn.functional.softmax(logits, dim=-1)
46
+ ai_probability = probs[0][self.fake_label_idx].item()
47
 
48
+ return ai_probability
49
 
50
  except Exception as e:
51
  logger.error(f"AI Frame Prediction Crashed: {str(e)}")
backend/app/ai/video/noise_entropy_detector.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import cv2
2
+ import numpy as np
3
+ import logging
4
+ from scipy.stats import entropy
5
+ from typing import Optional
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+ def compute_noise_entropy_anomaly(frame: np.ndarray) -> Optional[float]:
10
+ try:
11
+ if frame is None or frame.size == 0:
12
+ return None
13
+
14
+ gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
15
+ gray_small = cv2.resize(gray_frame, (512, 512), interpolation=cv2.INTER_AREA)
16
+
17
+ hist = cv2.calcHist([gray_small], [0], None, [256], [0, 256])
18
+ hist_prob = hist.ravel() / hist.sum()
19
+
20
+ img_entropy = entropy(hist_prob, base=2)
21
+
22
+ laplacian = cv2.Laplacian(gray_small, cv2.CV_64F)
23
+ noise_variance = laplacian.var()
24
+
25
+ score = 0.0
26
+ if img_entropy < 5.5:
27
+ score += 0.4
28
+
29
+ if noise_variance < 50 or noise_variance > 3000:
30
+ score += 0.6
31
+
32
+ return float(min(score, 1.0))
33
+
34
+ except Exception as e:
35
+ logger.error(f"Noise/Entropy Analysis Crash: {str(e)}")
36
+ return 0.0