Abraham E. Tavarez
commited on
Commit
Β·
9358900
1
Parent(s):
e2d190f
report generated
Browse files- app.py +34 -15
- pyproject.toml +1 -0
- report/report.py +0 -57
- uv.lock +8 -0
app.py
CHANGED
@@ -2,52 +2,68 @@ import gradio as gr
|
|
2 |
from detector.face import verify_faces, analyze_face
|
3 |
from detector.voice import verify_voices
|
4 |
from detector.video import verify_faces_in_video
|
5 |
-
from
|
6 |
|
7 |
# Holds latest results
|
8 |
last_face_result = None
|
9 |
last_voice_result = None
|
10 |
-
last_video_results =
|
11 |
|
12 |
|
13 |
def start_scan(image, audio):
|
14 |
return "Scanning in progress...", None
|
15 |
|
16 |
def compare_faces(img1_path, img2_path):
|
|
|
17 |
result = verify_faces(img1_path, img2_path)
|
|
|
18 |
|
19 |
if "error" in result:
|
20 |
return f"β Error: {result['error']}"
|
21 |
|
22 |
if result["verified"]:
|
23 |
-
|
|
|
|
|
|
|
24 |
else:
|
25 |
-
|
|
|
|
|
26 |
|
27 |
|
28 |
def compare_voices(audio1, audio2):
|
|
|
29 |
result = verify_voices(audio1, audio2)
|
|
|
30 |
|
31 |
if "error" in result:
|
32 |
return f"β Error: {result['error']}"
|
33 |
|
34 |
if result["match"]:
|
35 |
-
|
|
|
|
|
36 |
else:
|
37 |
-
|
|
|
|
|
38 |
|
39 |
|
40 |
def scan_video(video_path, ref_img):
|
|
|
41 |
results = verify_faces_in_video(video_path, ref_img)
|
42 |
report = ""
|
43 |
-
|
44 |
for r in results:
|
45 |
if "error" in r:
|
46 |
report += f"\nβ οΈ Frame {r['frame']}: {r['error']}"
|
|
|
47 |
else:
|
48 |
status = "β
Match" if r["verified"] else "β Mismatch"
|
49 |
report += f"\nπΌ Frame {r['frame']}: {status} (Distance: {r['distance']})"
|
50 |
|
|
|
51 |
return report
|
52 |
|
53 |
def generate_report():
|
@@ -61,16 +77,19 @@ with gr.Blocks(title="Deepfake Watchdog") as demo:
|
|
61 |
# Face Verification
|
62 |
gr.Markdown("### π· Face Verification")
|
63 |
with gr.Tab("Face Verification"):
|
64 |
-
|
65 |
-
audio = gr.Audio(label="Upload your voice (optional)", type="filepath")
|
|
|
|
|
|
|
66 |
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
|
75 |
# Voice Verification
|
76 |
gr.Markdown("### π€ Voice Verification")
|
|
|
2 |
from detector.face import verify_faces, analyze_face
|
3 |
from detector.voice import verify_voices
|
4 |
from detector.video import verify_faces_in_video
|
5 |
+
from reports.pdf_report import generate_pdf_report
|
6 |
|
7 |
# Holds latest results
|
8 |
last_face_result = None
|
9 |
last_voice_result = None
|
10 |
+
last_video_results = None
|
11 |
|
12 |
|
13 |
def start_scan(image, audio):
|
14 |
return "Scanning in progress...", None
|
15 |
|
16 |
def compare_faces(img1_path, img2_path):
|
17 |
+
global last_face_result
|
18 |
result = verify_faces(img1_path, img2_path)
|
19 |
+
result_text = ""
|
20 |
|
21 |
if "error" in result:
|
22 |
return f"β Error: {result['error']}"
|
23 |
|
24 |
if result["verified"]:
|
25 |
+
result_text = f"β
Match! Distance: {result['distance']:.4f} (Threshold: {result['threshold']})"
|
26 |
+
last_face_result = result_text
|
27 |
+
return result_text
|
28 |
+
|
29 |
else:
|
30 |
+
result_text = f"β No Match. Distance: {result['distance']:.4f} (Threshold: {result['threshold']})"
|
31 |
+
last_face_result = result_text
|
32 |
+
return result_text
|
33 |
|
34 |
|
35 |
def compare_voices(audio1, audio2):
|
36 |
+
global last_voice_result
|
37 |
result = verify_voices(audio1, audio2)
|
38 |
+
result_text = ""
|
39 |
|
40 |
if "error" in result:
|
41 |
return f"β Error: {result['error']}"
|
42 |
|
43 |
if result["match"]:
|
44 |
+
result_text = f"β
Same speaker detected. Similarity: {result['similarity']} (Threshold: {result['threshold']})"
|
45 |
+
last_voice_result = result_text
|
46 |
+
return result_text
|
47 |
else:
|
48 |
+
result_text = f"β Different speakers. Similarity: {result['similarity']} (Threshold: {result['threshold']})"
|
49 |
+
last_voice_result = result_text
|
50 |
+
return result_text
|
51 |
|
52 |
|
53 |
def scan_video(video_path, ref_img):
|
54 |
+
global last_video_results
|
55 |
results = verify_faces_in_video(video_path, ref_img)
|
56 |
report = ""
|
57 |
+
last_video_results = results
|
58 |
for r in results:
|
59 |
if "error" in r:
|
60 |
report += f"\nβ οΈ Frame {r['frame']}: {r['error']}"
|
61 |
+
# last_video_results.append(report)
|
62 |
else:
|
63 |
status = "β
Match" if r["verified"] else "β Mismatch"
|
64 |
report += f"\nπΌ Frame {r['frame']}: {status} (Distance: {r['distance']})"
|
65 |
|
66 |
+
# last_video_results.append(report)
|
67 |
return report
|
68 |
|
69 |
def generate_report():
|
|
|
77 |
# Face Verification
|
78 |
gr.Markdown("### π· Face Verification")
|
79 |
with gr.Tab("Face Verification"):
|
80 |
+
image1 = gr.Image(label="Upload your face", type="filepath")
|
81 |
+
# audio = gr.Audio(label="Upload your voice (optional)", type="filepath")
|
82 |
+
image2 = gr.Image(label="Upload another face", type="filepath")
|
83 |
+
|
84 |
+
# face_btn = gr.Button("Compare Faces")
|
85 |
|
86 |
+
run_button = gr.Button("Compare Faces")
|
87 |
+
output_text = gr.Textbox(label="Result")
|
88 |
+
# output_gallery = gr.Gallery(label="Matched Results")
|
89 |
|
90 |
+
run_button.click(
|
91 |
+
compare_faces, inputs=[image1, image2], outputs=[output_text]
|
92 |
+
)
|
93 |
|
94 |
# Voice Verification
|
95 |
gr.Markdown("### π€ Voice Verification")
|
pyproject.toml
CHANGED
@@ -6,6 +6,7 @@ readme = "README.md"
|
|
6 |
requires-python = ">=3.12"
|
7 |
dependencies = [
|
8 |
"deepface>=0.0.93",
|
|
|
9 |
"gradio[mcp]>=5.32.1",
|
10 |
"opencv-python-headless>=4.11.0.86",
|
11 |
"pydub>=0.25.1",
|
|
|
6 |
requires-python = ">=3.12"
|
7 |
dependencies = [
|
8 |
"deepface>=0.0.93",
|
9 |
+
"fpdf>=1.7.2",
|
10 |
"gradio[mcp]>=5.32.1",
|
11 |
"opencv-python-headless>=4.11.0.86",
|
12 |
"pydub>=0.25.1",
|
report/report.py
DELETED
@@ -1,57 +0,0 @@
|
|
1 |
-
from fpdf import FPDF
|
2 |
-
import os
|
3 |
-
import datetime
|
4 |
-
|
5 |
-
class ReportGenerator(FPDF):
|
6 |
-
def header(self):
|
7 |
-
self.set_font("Arial", "B", 16)
|
8 |
-
self.cell(0, 10, "Deepfake Watchdog Report", ln=1, align="C")
|
9 |
-
self.ln(5)
|
10 |
-
|
11 |
-
def add_section_title(self, title):
|
12 |
-
self.set_font("Arial", "B", 12)
|
13 |
-
self.cell(0, 10, title, ln=1, align="L")
|
14 |
-
self.ln(2)
|
15 |
-
|
16 |
-
def add_text(self, text):
|
17 |
-
self.set_font("Arial", "", 12)
|
18 |
-
self.multi_cell(0, 8, text)
|
19 |
-
self.ln(2)
|
20 |
-
|
21 |
-
def add_image(self, image_path, w=60):
|
22 |
-
if os.path.exists(image_path):
|
23 |
-
self.image(image_path, w=w)
|
24 |
-
self.ln(5)
|
25 |
-
else:
|
26 |
-
print(f"Image not found: {image_path}")
|
27 |
-
|
28 |
-
# Generate PDF Report
|
29 |
-
def generate_pdf_report(face_result, voice_result, video_results, output_path=f"report{datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.pdf"):
|
30 |
-
pdf = ReportGenerator()
|
31 |
-
pdf.add_page()
|
32 |
-
|
33 |
-
# Section 1: Face Verification
|
34 |
-
pdf.add_section_title("Face Verification Results")
|
35 |
-
pdf.add_text(face_result)
|
36 |
-
|
37 |
-
# Section 2: Voice Verification
|
38 |
-
pdf.add_section_title("Voice Verification Results")
|
39 |
-
pdf.add_text(voice_result)
|
40 |
-
|
41 |
-
# Section 3: Video Verification
|
42 |
-
pdf.add_section_title("Video Verification Results")
|
43 |
-
|
44 |
-
for frame in video_results:
|
45 |
-
if "error" in frame:
|
46 |
-
pdf.add_text(f"{frame['frame']}: ERROR - {frame['error']}")
|
47 |
-
else:
|
48 |
-
status = "β
Match" if frame["verified"] else "β Mismatch"
|
49 |
-
pdf.add_text(f"{frame['frame']} - {status} (Distance: {frame['distance']})")
|
50 |
-
|
51 |
-
if not frame["verified"]:
|
52 |
-
pdf.add_image(frame["frame"], w=80)
|
53 |
-
|
54 |
-
pdf.output(output_path)
|
55 |
-
print(f"PDF report generated at: {output_path}")
|
56 |
-
return output_path
|
57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uv.lock
CHANGED
@@ -274,6 +274,7 @@ version = "0.1.0"
|
|
274 |
source = { virtual = "." }
|
275 |
dependencies = [
|
276 |
{ name = "deepface" },
|
|
|
277 |
{ name = "gradio", extra = ["mcp"] },
|
278 |
{ name = "opencv-python-headless" },
|
279 |
{ name = "pydub" },
|
@@ -284,6 +285,7 @@ dependencies = [
|
|
284 |
[package.metadata]
|
285 |
requires-dist = [
|
286 |
{ name = "deepface", specifier = ">=0.0.93" },
|
|
|
287 |
{ name = "gradio", extras = ["mcp"], specifier = ">=5.32.1" },
|
288 |
{ name = "opencv-python-headless", specifier = ">=4.11.0.86" },
|
289 |
{ name = "pydub", specifier = ">=0.25.1" },
|
@@ -371,6 +373,12 @@ wheels = [
|
|
371 |
{ url = "https://files.pythonhosted.org/packages/b8/25/155f9f080d5e4bc0082edfda032ea2bc2b8fab3f4d25d46c1e9dd22a1a89/flatbuffers-25.2.10-py2.py3-none-any.whl", hash = "sha256:ebba5f4d5ea615af3f7fd70fc310636fbb2bbd1f566ac0a23d98dd412de50051", size = 30953, upload-time = "2025-02-11T04:26:44.484Z" },
|
372 |
]
|
373 |
|
|
|
|
|
|
|
|
|
|
|
|
|
374 |
[[package]]
|
375 |
name = "fsspec"
|
376 |
version = "2025.5.1"
|
|
|
274 |
source = { virtual = "." }
|
275 |
dependencies = [
|
276 |
{ name = "deepface" },
|
277 |
+
{ name = "fpdf" },
|
278 |
{ name = "gradio", extra = ["mcp"] },
|
279 |
{ name = "opencv-python-headless" },
|
280 |
{ name = "pydub" },
|
|
|
285 |
[package.metadata]
|
286 |
requires-dist = [
|
287 |
{ name = "deepface", specifier = ">=0.0.93" },
|
288 |
+
{ name = "fpdf", specifier = ">=1.7.2" },
|
289 |
{ name = "gradio", extras = ["mcp"], specifier = ">=5.32.1" },
|
290 |
{ name = "opencv-python-headless", specifier = ">=4.11.0.86" },
|
291 |
{ name = "pydub", specifier = ">=0.25.1" },
|
|
|
373 |
{ url = "https://files.pythonhosted.org/packages/b8/25/155f9f080d5e4bc0082edfda032ea2bc2b8fab3f4d25d46c1e9dd22a1a89/flatbuffers-25.2.10-py2.py3-none-any.whl", hash = "sha256:ebba5f4d5ea615af3f7fd70fc310636fbb2bbd1f566ac0a23d98dd412de50051", size = 30953, upload-time = "2025-02-11T04:26:44.484Z" },
|
374 |
]
|
375 |
|
376 |
+
[[package]]
|
377 |
+
name = "fpdf"
|
378 |
+
version = "1.7.2"
|
379 |
+
source = { registry = "https://pypi.org/simple" }
|
380 |
+
sdist = { url = "https://files.pythonhosted.org/packages/37/c6/608a9e6c172bf9124aa687ec8b9f0e8e5d697d59a5f4fad0e2d5ec2a7556/fpdf-1.7.2.tar.gz", hash = "sha256:125840783289e7d12552b1e86ab692c37322e7a65b96a99e0ea86cca041b6779", size = 39504, upload-time = "2015-01-21T00:07:47.493Z" }
|
381 |
+
|
382 |
[[package]]
|
383 |
name = "fsspec"
|
384 |
version = "2025.5.1"
|