NOBODY204 commited on
Commit
3524290
Β·
verified Β·
1 Parent(s): ce97a4a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +44 -35
app.py CHANGED
@@ -9,7 +9,7 @@ import io, warnings
9
  warnings.filterwarnings("ignore")
10
 
11
  # ═══════════════════════════════════════════════════
12
- # πŸ›‘οΈ MEDIASHIELD v3.0 β€” ARCHIVE & FORENSIC SUITE
13
  # ═══════════════════════════════════════════════════
14
 
15
  def apply_gamma_correction(img):
@@ -23,89 +23,98 @@ def apply_gamma_correction(img):
23
  return cv2.LUT(img, table), f"πŸŒ™ Mode Sombre (LumiΓ¨re: {brightness:.1f})"
24
  return img, "β˜€οΈ LumiΓ¨re Standard"
25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  def verify_natural_grain(img):
27
- """Distingue le lissage IA du grain organique d'une photo rΓ©elle."""
28
  gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
29
  local_var = ndimage.generic_filter(gray, np.var, size=3)
30
  avg_var = np.mean(local_var)
31
- # Un score très bas (< 0.8) indique une texture mathématiquement 'trop' parfaite (IA)
32
- if avg_var < 0.8:
33
- return True, avg_var
34
- return False, avg_var
35
 
36
  def analyze_forensics(img_input):
37
  if img_input is None: return None, "❌ Aucune image chargΓ©e."
38
 
39
- # 1. Nettoyage et Correction Gamma
40
  img_cv = cv2.cvtColor(img_input, cv2.COLOR_RGBA2RGB) if img_input.shape[2] == 4 else img_input.copy()
41
  img_ready, light_msg = apply_gamma_correction(img_cv)
42
  pil_img = Image.fromarray(img_ready)
43
 
44
- # 2. Analyse du Grain (Anti-Faux Positifs Archives)
45
- is_too_smooth, grain_val = verify_natural_grain(img_ready)
46
 
47
- # 3. Analyse de Chrominance (Signatures Couleurs IA)
 
 
 
48
  ycrcb = cv2.cvtColor(img_ready, cv2.COLOR_RGB2YCrCb)
49
  cr_var = ndimage.generic_filter(ycrcb[:,:,1], np.var, size=5)
50
  chroma_uniformity = np.std(cr_var) / (np.mean(cr_var) + 1e-8)
51
-
52
- # 4. FFT (Recherche de motifs de grille IA)
53
- gray_f = cv2.cvtColor(img_ready, cv2.COLOR_RGB2GRAY).astype(np.float32)
54
- f_shift = np.fft.fftshift(np.fft.fft2(gray_f))
55
- fft_vis = np.log(np.abs(f_shift) + 1)
56
 
57
- # 5. ELA (Error Level Analysis)
58
  buf = io.BytesIO()
59
  pil_img.save(buf, format="JPEG", quality=90)
60
  recomp = Image.open(io.BytesIO(buf.getvalue())).convert("RGB")
61
  ela_diff = ImageChops.difference(pil_img, recomp)
62
  ela_vis = ImageEnhance.Brightness(ela_diff).enhance(10)
63
 
64
- # 6. Système de Score S2T Ariana
65
  score = 0
66
  reasons = []
67
 
 
 
 
 
68
  if is_too_smooth:
69
- score += 25
70
- reasons.append(f"⚑ Texture suspecte (Grain trop faible: {grain_val:.2f})")
71
  else:
72
- score -= 10
73
  reasons.append("βœ… Grain organique dΓ©tectΓ© (Photo rΓ©elle)")
74
 
75
  if chroma_uniformity < 0.9:
76
- score += 30
77
  reasons.append("⚠️ Bruit chromatique uniforme (Signature IA)")
78
 
79
- if np.mean(np.array(ela_diff)) < 1.2:
80
- score += 20
81
- reasons.append("πŸ” Compression suspecte (ELA trop lisse)")
82
-
83
- # Bornage du score
84
  score = max(0, min(100, score))
85
  verdict = "πŸ”΄ IA DΓ‰TECTΓ‰E" if score > 55 else "🟠 SUSPECT" if score > 35 else "🟒 AUTHENTIQUE"
86
 
87
- # Visualisation des preuves
88
  fig, axes = plt.subplots(1, 3, figsize=(15, 5))
89
  axes[0].imshow(img_cv); axes[0].set_title(f'Original ({light_msg})')
90
- axes[1].imshow(fft_vis, cmap='magma'); axes[1].set_title('Spectre FrΓ©quence (FFT)')
91
- axes[2].imshow(ela_vis); axes[2].set_title('Analyse ELA (Compression)')
92
  for ax in axes: ax.axis('off')
93
  plt.tight_layout()
94
 
95
- report = f"πŸ›‘οΈ RAPPORT MEDIASHIELD v3.0\nVERDICT : {verdict}\nIndice de confiance IA : {score}/100\n\nDiagnostic :\n" + "\n".join(reasons)
96
  return fig, report
97
 
98
  # ═══════════════════════════════════════════════════
99
- # INTERFACE UTILISATEUR (GRADIO)
100
  # ═══════════════════════════════════════════════════
101
 
102
- with gr.Blocks(title="MediaShield v3.0", theme=gr.themes.Soft()) as demo:
103
- gr.Markdown("# πŸ›‘οΈ MediaShield v3.0")
104
- gr.Markdown("**Expertise Forensic S2T** : DΓ©tection IA, analyse de grain et correction d'archives.")
105
 
106
  with gr.Row():
107
  with gr.Column(scale=1):
108
- input_file = gr.Image(label="Charger une image (Photo ou Archive)", type="numpy")
109
  run_btn = gr.Button("LANCER L'ANALYSE", variant="primary")
110
  with gr.Column(scale=2):
111
  output_plot = gr.Plot(label="Preuves visuelles")
 
9
  warnings.filterwarnings("ignore")
10
 
11
  # ═══════════════════════════════════════════════════
12
+ # πŸ›‘οΈ MEDIASHIELD v3.1 β€” NANO BANANA EDITION
13
  # ═══════════════════════════════════════════════════
14
 
15
  def apply_gamma_correction(img):
 
23
  return cv2.LUT(img, table), f"πŸŒ™ Mode Sombre (LumiΓ¨re: {brightness:.1f})"
24
  return img, "β˜€οΈ LumiΓ¨re Standard"
25
 
26
+ def detect_nano_signatures(img):
27
+ """DΓ©tecte les gradients trop parfaits et anomalies de Gemini."""
28
+ gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY).astype(np.float32)
29
+ # Analyse de la variance des gradients (Laplacien)
30
+ laplacian = cv2.Laplacian(gray, cv2.CV_64F)
31
+ smoothness_score = np.var(laplacian)
32
+
33
+ # FFT pour dΓ©tection de pΓ©riodicitΓ©
34
+ f = np.fft.fft2(gray)
35
+ fshift = np.fft.fftshift(f)
36
+ magnitude_spectrum = 20 * np.log(np.abs(fshift) + 1)
37
+
38
+ # Un score de smoothness < 4.5 est un fort indicateur IA
39
+ is_nano_candidate = (smoothness_score < 4.5)
40
+ return is_nano_candidate, smoothness_score, magnitude_spectrum
41
+
42
  def verify_natural_grain(img):
43
+ """Distingue le lissage IA du grain organique."""
44
  gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
45
  local_var = ndimage.generic_filter(gray, np.var, size=3)
46
  avg_var = np.mean(local_var)
47
+ return (avg_var < 0.8), avg_var
 
 
 
48
 
49
  def analyze_forensics(img_input):
50
  if img_input is None: return None, "❌ Aucune image chargΓ©e."
51
 
52
+ # 1. Traitement Image
53
  img_cv = cv2.cvtColor(img_input, cv2.COLOR_RGBA2RGB) if img_input.shape[2] == 4 else img_input.copy()
54
  img_ready, light_msg = apply_gamma_correction(img_cv)
55
  pil_img = Image.fromarray(img_ready)
56
 
57
+ # 2. DΓ©tection SpΓ©cifique Nano Banana
58
+ is_nano, s_score, fft_map = detect_nano_signatures(img_ready)
59
 
60
+ # 3. Autres analyses Forensic
61
+ is_too_smooth, grain_val = verify_natural_grain(img_ready)
62
+
63
+ # 4. Chrominance & ELA
64
  ycrcb = cv2.cvtColor(img_ready, cv2.COLOR_RGB2YCrCb)
65
  cr_var = ndimage.generic_filter(ycrcb[:,:,1], np.var, size=5)
66
  chroma_uniformity = np.std(cr_var) / (np.mean(cr_var) + 1e-8)
 
 
 
 
 
67
 
 
68
  buf = io.BytesIO()
69
  pil_img.save(buf, format="JPEG", quality=90)
70
  recomp = Image.open(io.BytesIO(buf.getvalue())).convert("RGB")
71
  ela_diff = ImageChops.difference(pil_img, recomp)
72
  ela_vis = ImageEnhance.Brightness(ela_diff).enhance(10)
73
 
74
+ # 5. Calcul du Score Final
75
  score = 0
76
  reasons = []
77
 
78
+ if is_nano:
79
+ score += 40
80
+ reasons.append(f"🚨 Signature NANO BANANA : Gradients trop lisses (Score: {s_score:.2f})")
81
+
82
  if is_too_smooth:
83
+ score += 20
84
+ reasons.append(f"⚑ Texture suspecte (Grain faible: {grain_val:.2f})")
85
  else:
86
+ score -= 15
87
  reasons.append("βœ… Grain organique dΓ©tectΓ© (Photo rΓ©elle)")
88
 
89
  if chroma_uniformity < 0.9:
90
+ score += 25
91
  reasons.append("⚠️ Bruit chromatique uniforme (Signature IA)")
92
 
 
 
 
 
 
93
  score = max(0, min(100, score))
94
  verdict = "πŸ”΄ IA DΓ‰TECTΓ‰E" if score > 55 else "🟠 SUSPECT" if score > 35 else "🟒 AUTHENTIQUE"
95
 
96
+ # 6. Visualisation
97
  fig, axes = plt.subplots(1, 3, figsize=(15, 5))
98
  axes[0].imshow(img_cv); axes[0].set_title(f'Original ({light_msg})')
99
+ axes[1].imshow(fft_map, cmap='magma'); axes[1].set_title('Spectre Nano (FFT)')
100
+ axes[2].imshow(ela_vis); axes[2].set_title('Analyse ELA')
101
  for ax in axes: ax.axis('off')
102
  plt.tight_layout()
103
 
104
+ report = f"πŸ›‘οΈ RAPPORT MEDIASHIELD v3.1\nVERDICT : {verdict}\nIndice de confiance IA : {score}/100\n\nDiagnostic :\n" + "\n".join(reasons)
105
  return fig, report
106
 
107
  # ═══════════════════════════════════════════════════
108
+ # INTERFACE UTILISATEUR
109
  # ═══════════════════════════════════════════════════
110
 
111
+ with gr.Blocks(title="MediaShield v3.1", theme=gr.themes.Soft()) as demo:
112
+ gr.Markdown("# πŸ›‘οΈ MediaShield v3.1 (Nano Edition)")
113
+ gr.Markdown("Expertise Forensic optimisée pour les archives et la détection des modèles Gemini.")
114
 
115
  with gr.Row():
116
  with gr.Column(scale=1):
117
+ input_file = gr.Image(label="Charger l'archive", type="numpy")
118
  run_btn = gr.Button("LANCER L'ANALYSE", variant="primary")
119
  with gr.Column(scale=2):
120
  output_plot = gr.Plot(label="Preuves visuelles")