Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -60,12 +60,24 @@ def test_fft_frequency(roi):
|
|
| 60 |
h, w = mag.shape
|
| 61 |
inner = mag[h // 3:2 * h // 3, w // 3:2 * w // 3].mean()
|
| 62 |
outer = mag.mean()
|
| 63 |
-
|
|
|
|
|
|
|
| 64 |
|
| 65 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 66 |
-
# ΓTAPE 3 :
|
| 67 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 68 |
def test_optical_flow(frames):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
if len(frames) < 2:
|
| 70 |
return 0.50
|
| 71 |
scores = []
|
|
@@ -79,17 +91,21 @@ def test_optical_flow(frames):
|
|
| 79 |
mag_std = np.std(magnitude)
|
| 80 |
mag_mean = np.mean(magnitude)
|
| 81 |
if mag_mean < 0.01:
|
| 82 |
-
scores.append(0.
|
| 83 |
else:
|
| 84 |
ratio = mag_std / mag_mean
|
| 85 |
-
if
|
| 86 |
-
scores.append(0.88) # Mouvement naturel
|
|
|
|
|
|
|
|
|
|
|
|
|
| 87 |
elif ratio < 0.15:
|
| 88 |
-
scores.append(0.
|
| 89 |
elif ratio > 4.0:
|
| 90 |
scores.append(0.22) # Saccades β Injection
|
| 91 |
else:
|
| 92 |
-
scores.append(0.
|
| 93 |
return float(np.mean(scores)) if scores else 0.50
|
| 94 |
|
| 95 |
def test_eye_region(frame):
|
|
@@ -147,15 +163,21 @@ def test_texture_lbp(roi):
|
|
| 147 |
return 0.22
|
| 148 |
|
| 149 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 150 |
-
# ΓTAPE 4 : VERDICT
|
| 151 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 152 |
def get_verdict(score_pct):
|
| 153 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
return "β
AUTHENTIQUE", "CohΓ©rence temporelle, colorimΓ©trique et texturale conforme."
|
| 155 |
-
elif score_pct >=
|
| 156 |
return "β οΈ SUSPECT", "IncohΓ©rences dΓ©tectΓ©es β vΓ©rification manuelle recommandΓ©e."
|
| 157 |
else:
|
| 158 |
-
return "π¨ DEEPFAKE DΓTECTΓ", "Anomalie majeure (IA gΓ©nΓ©rative : Sora/
|
| 159 |
|
| 160 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 161 |
# ΓTAPE 5 : PIPELINE PRINCIPAL
|
|
@@ -202,14 +224,15 @@ def analyze_video(video_path):
|
|
| 202 |
s6 = test_color_coherence(roi, frame)
|
| 203 |
s7 = test_texture_lbp(roi)
|
| 204 |
|
|
|
|
| 205 |
final = (
|
| 206 |
-
s1 * 0.
|
| 207 |
-
s2 * 0.
|
| 208 |
-
s3 * 0.
|
| 209 |
-
flow_score * 0.
|
| 210 |
-
s5 * 0.10 +
|
| 211 |
-
s6 * 0.15 +
|
| 212 |
-
s7 * 0.10
|
| 213 |
)
|
| 214 |
per_face_scores.append(final)
|
| 215 |
engine_log.append({
|
|
@@ -234,7 +257,7 @@ def analyze_video(video_path):
|
|
| 234 |
verdict, explication = get_verdict(global_score_pct)
|
| 235 |
sep = "β" * 52
|
| 236 |
rapport = (
|
| 237 |
-
f"π‘οΈ VideoShield v5.
|
| 238 |
f"VERDICT : {verdict}\n"
|
| 239 |
f"SCORE : {global_score_pct}%\n"
|
| 240 |
f"ANALYSE : {explication}\n"
|
|
@@ -242,13 +265,14 @@ def analyze_video(video_path):
|
|
| 242 |
f"{sep}\n"
|
| 243 |
f"Moteurs : Boundary | Noise | FFT | Optical Flow\n"
|
| 244 |
f" : Eye Region | Color LAB | LBP Texture\n"
|
| 245 |
-
f"Cibles : Sora 2.0 |
|
| 246 |
f"Standard : IASA TC-04 | ACoNum Tunisia 2026\n"
|
|
|
|
| 247 |
f"{sep}"
|
| 248 |
)
|
| 249 |
|
| 250 |
res_json = {
|
| 251 |
-
"version": "VideoShield v5.
|
| 252 |
"score": global_score_pct,
|
| 253 |
"verdict": verdict,
|
| 254 |
"flow_global": round(flow_score, 3),
|
|
@@ -287,13 +311,14 @@ def generate_iscc(video_path):
|
|
| 287 |
return f"β Erreur ISCC : {str(e)}"
|
| 288 |
|
| 289 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 290 |
-
# INTERFACE GRADIO V5
|
| 291 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 292 |
-
with gr.Blocks(title="VideoShield v5.
|
| 293 |
-
gr.Markdown("# π‘οΈ VideoShield v5.
|
| 294 |
gr.Markdown(
|
| 295 |
-
"DΓ©tection de deepfakes gΓ©nΓ©ratifs (Sora 2.0, Runway Gen-3, Kling, Pika 2) "
|
| 296 |
-
"via 7 moteurs forensiques OpenCV. Standard IASA TC-04 Β· ACoNum Tunisia 2026."
|
|
|
|
| 297 |
)
|
| 298 |
|
| 299 |
with gr.Tab("π Analyse Deepfake"):
|
|
|
|
| 60 |
h, w = mag.shape
|
| 61 |
inner = mag[h // 3:2 * h // 3, w // 3:2 * w // 3].mean()
|
| 62 |
outer = mag.mean()
|
| 63 |
+
ratio = inner / outer
|
| 64 |
+
# v5.1 : seuil durci (1.3 au lieu de 1.5) β deepfakes ont spectre trop lisse
|
| 65 |
+
return 0.90 if ratio < 1.3 else 0.40
|
| 66 |
|
| 67 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 68 |
+
# ΓTAPE 3 : MOTEURS V5.1 β recalibrΓ©s face aux deepfakes WhatsApp/Sora
|
| 69 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 70 |
def test_optical_flow(frames):
|
| 71 |
+
"""
|
| 72 |
+
v5.1 β Recalibration clΓ© :
|
| 73 |
+
Les deepfakes modernes (Sora 2.0, Wan, Kling) ont un flux optique
|
| 74 |
+
avec ratio std/mean proche de 1.0 β trop uniforme par rapport au
|
| 75 |
+
mouvement humain naturel (ratio attendu : 1.5β3.5).
|
| 76 |
+
Seuils resserrΓ©s :
|
| 77 |
+
- ratio < 0.80 ou 0.85 < ratio < 1.20 β suspect (trop lisse/uniforme)
|
| 78 |
+
- ratio 1.20β1.50 β ambigu
|
| 79 |
+
- ratio > 1.50 β naturel
|
| 80 |
+
"""
|
| 81 |
if len(frames) < 2:
|
| 82 |
return 0.50
|
| 83 |
scores = []
|
|
|
|
| 91 |
mag_std = np.std(magnitude)
|
| 92 |
mag_mean = np.mean(magnitude)
|
| 93 |
if mag_mean < 0.01:
|
| 94 |
+
scores.append(0.55)
|
| 95 |
else:
|
| 96 |
ratio = mag_std / mag_mean
|
| 97 |
+
if ratio > 1.60:
|
| 98 |
+
scores.append(0.88) # Mouvement naturel irrΓ©gulier
|
| 99 |
+
elif ratio > 1.30:
|
| 100 |
+
scores.append(0.62) # Ambigu
|
| 101 |
+
elif ratio > 0.80:
|
| 102 |
+
scores.append(0.18) # β
Zone deepfake typique (ratio ~1.0) β
|
| 103 |
elif ratio < 0.15:
|
| 104 |
+
scores.append(0.15) # Trop lisse β IA
|
| 105 |
elif ratio > 4.0:
|
| 106 |
scores.append(0.22) # Saccades β Injection
|
| 107 |
else:
|
| 108 |
+
scores.append(0.35)
|
| 109 |
return float(np.mean(scores)) if scores else 0.50
|
| 110 |
|
| 111 |
def test_eye_region(frame):
|
|
|
|
| 163 |
return 0.22
|
| 164 |
|
| 165 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 166 |
+
# ΓTAPE 4 : VERDICT v5.1 β seuils relevΓ©s
|
| 167 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 168 |
def get_verdict(score_pct):
|
| 169 |
+
"""
|
| 170 |
+
v5.1 : seuils durcis.
|
| 171 |
+
< 55% β DEEPFAKE DΓTECTΓ
|
| 172 |
+
55β72% β SUSPECT
|
| 173 |
+
> 72% β AUTHENTIQUE
|
| 174 |
+
"""
|
| 175 |
+
if score_pct > 72:
|
| 176 |
return "β
AUTHENTIQUE", "CohΓ©rence temporelle, colorimΓ©trique et texturale conforme."
|
| 177 |
+
elif score_pct >= 55:
|
| 178 |
return "β οΈ SUSPECT", "IncohΓ©rences dΓ©tectΓ©es β vΓ©rification manuelle recommandΓ©e."
|
| 179 |
else:
|
| 180 |
+
return "π¨ DEEPFAKE DΓTECTΓ", "Anomalie majeure dΓ©tectΓ©e (IA gΓ©nΓ©rative : Sora/Wan/Kling/Runway)."
|
| 181 |
|
| 182 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 183 |
# ΓTAPE 5 : PIPELINE PRINCIPAL
|
|
|
|
| 224 |
s6 = test_color_coherence(roi, frame)
|
| 225 |
s7 = test_texture_lbp(roi)
|
| 226 |
|
| 227 |
+
# v5.1 : poids optical flow augmentΓ© 25β35%, boundary rΓ©duit 10β5%
|
| 228 |
final = (
|
| 229 |
+
s1 * 0.05 + # boundary
|
| 230 |
+
s2 * 0.15 + # noise coherence
|
| 231 |
+
s3 * 0.10 + # FFT
|
| 232 |
+
flow_score * 0.35 + # β
optical flow (moteur principal)
|
| 233 |
+
s5 * 0.10 + # eye region
|
| 234 |
+
s6 * 0.15 + # color LAB
|
| 235 |
+
s7 * 0.10 # LBP texture
|
| 236 |
)
|
| 237 |
per_face_scores.append(final)
|
| 238 |
engine_log.append({
|
|
|
|
| 257 |
verdict, explication = get_verdict(global_score_pct)
|
| 258 |
sep = "β" * 52
|
| 259 |
rapport = (
|
| 260 |
+
f"π‘οΈ VideoShield v5.1 β Rapport d'AuthenticitΓ©\n{sep}\n"
|
| 261 |
f"VERDICT : {verdict}\n"
|
| 262 |
f"SCORE : {global_score_pct}%\n"
|
| 263 |
f"ANALYSE : {explication}\n"
|
|
|
|
| 265 |
f"{sep}\n"
|
| 266 |
f"Moteurs : Boundary | Noise | FFT | Optical Flow\n"
|
| 267 |
f" : Eye Region | Color LAB | LBP Texture\n"
|
| 268 |
+
f"Cibles : Sora 2.0 | Wan 2.1 | Kling | Pika 2 | Runway Gen-3\n"
|
| 269 |
f"Standard : IASA TC-04 | ACoNum Tunisia 2026\n"
|
| 270 |
+
f"Version : v5.1 β recalibrΓ©e juin 2026\n"
|
| 271 |
f"{sep}"
|
| 272 |
)
|
| 273 |
|
| 274 |
res_json = {
|
| 275 |
+
"version": "VideoShield v5.1",
|
| 276 |
"score": global_score_pct,
|
| 277 |
"verdict": verdict,
|
| 278 |
"flow_global": round(flow_score, 3),
|
|
|
|
| 311 |
return f"β Erreur ISCC : {str(e)}"
|
| 312 |
|
| 313 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 314 |
+
# INTERFACE GRADIO V5.1
|
| 315 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 316 |
+
with gr.Blocks(title="VideoShield v5.1", theme=gr.themes.Soft()) as demo:
|
| 317 |
+
gr.Markdown("# π‘οΈ VideoShield v5.1 β AuthenticitΓ© VidΓ©o IA")
|
| 318 |
gr.Markdown(
|
| 319 |
+
"DΓ©tection de deepfakes gΓ©nΓ©ratifs (Sora 2.0, Wan 2.1, Runway Gen-3, Kling, Pika 2) "
|
| 320 |
+
"via 7 moteurs forensiques OpenCV. Standard IASA TC-04 Β· ACoNum Tunisia 2026. "
|
| 321 |
+
"**v5.1** : flux optique recalibrΓ© β dΓ©tection ratio uniforme ~1.0 (signature deepfake)."
|
| 322 |
)
|
| 323 |
|
| 324 |
with gr.Tab("π Analyse Deepfake"):
|