AMontiB commited on
Commit
d73ae17
·
1 Parent(s): 2e6d263
Files changed (1) hide show
  1. app.py +31 -200
app.py CHANGED
@@ -1,205 +1,36 @@
1
- import gradio as gr
2
- import numpy as np
3
- from PIL import Image
4
- import tempfile
5
  import os
 
 
6
 
7
- # Import all the tool modules
8
- from CFA import analyze_region, on_upload_image as cfa_upload, move_selection_box as cfa_move_box
9
- from JPEG_Ghost import run_analysis, on_upload_image as jpeg_upload, move_selection_box as jpeg_move_box
10
- from PRNU import analyze_image_forgery
11
- from shadows import build_gradio_interface
12
-
13
- # Configuration
14
- BOX_SIZE_CFA = 128
15
- BOX_SIZE_JPEG = 256
16
-
17
- # Store state for each tool
18
- class ToolState:
19
- def __init__(self):
20
- self.cfa_original_image = None
21
- self.cfa_box_coords = (0, 0)
22
- self.jpeg_original_image = None
23
- self.jpeg_box_coords = (0, 0)
24
-
25
- state = ToolState()
26
-
27
- # CFA Analysis Functions
28
- def cfa_interface():
29
- with gr.Blocks() as interface:
30
- gr.Markdown("# 🎨 Color Filter Array Analysis")
31
- gr.Markdown("Analyzes artifacts introduced during the camera's raw image processing to detect spliced or copy-pasted regions.")
32
-
33
- with gr.Row():
34
- cfa_image_display = gr.Image(type="numpy", label="Upload Image & Click to Select 128x128 Region")
35
- cfa_output_plot = gr.Plot(label="Analysis Results")
36
-
37
- cfa_analyze_button = gr.Button("Analyze Region", variant="primary")
38
-
39
- # Event handlers for CFA
40
- def on_cfa_upload(image):
41
- result = cfa_upload(image)
42
- state.cfa_original_image = result[1]
43
- state.cfa_box_coords = result[2]
44
- return result[0]
45
-
46
- def on_cfa_click(evt: gr.SelectData):
47
- if state.cfa_original_image is not None:
48
- result = cfa_move_box(state.cfa_original_image, evt)
49
- state.cfa_box_coords = result[1]
50
- return result[0]
51
- return state.cfa_original_image
52
-
53
- def on_cfa_analyze():
54
- if state.cfa_original_image is not None:
55
- return analyze_region(state.cfa_original_image, state.cfa_box_coords)
56
- return None
57
-
58
- cfa_image_display.upload(on_cfa_upload, inputs=[cfa_image_display], outputs=[cfa_image_display])
59
- cfa_image_display.select(on_cfa_click, inputs=[], outputs=[cfa_image_display])
60
- cfa_analyze_button.click(on_cfa_analyze, inputs=[], outputs=[cfa_output_plot])
61
-
62
- return interface
63
 
64
- # JPEG Ghost Analysis Functions
65
- def jpeg_interface():
66
- with gr.Blocks() as interface:
67
- gr.Markdown("# 👻 JPEG Ghost Detection")
68
- gr.Markdown("Detects forgeries by identifying regions with different JPEG compression levels using recompression analysis.")
69
-
70
- with gr.Row():
71
- with gr.Column(scale=1):
72
- jpeg_image_display = gr.Image(type="numpy", label="Upload Image & Click to Select 256x256 Region")
73
- qf1_slider = gr.Slider(minimum=1, maximum=100, value=70, step=1, label="QF1: Background Quality")
74
- qf2_slider = gr.Slider(minimum=1, maximum=100, value=85, step=1, label="QF2: Final Composite Quality")
75
- gr.Markdown("#### Analysis QF Range")
76
- with gr.Row():
77
- qf_start_slider = gr.Slider(minimum=50, maximum=100, value=50, step=5, label="Start")
78
- qf_end_slider = gr.Slider(minimum=50, maximum=100, value=90, step=5, label="End")
79
- jpeg_analyze_button = gr.Button("Analyze Image", variant="primary")
80
-
81
- with gr.Column(scale=2):
82
- jpeg_composite_display = gr.Image(type="numpy", label="Generated Composite Image")
83
- jpeg_difference_plot = gr.Plot(label="Difference Maps")
84
-
85
- # Event handlers for JPEG Ghost
86
- def on_jpeg_upload(image):
87
- result = jpeg_upload(image)
88
- state.jpeg_original_image = result[1]
89
- state.jpeg_box_coords = result[2]
90
- return result[0]
91
-
92
- def on_jpeg_click(evt: gr.SelectData):
93
- if state.jpeg_original_image is not None:
94
- result = jpeg_move_box(state.jpeg_original_image, evt)
95
- state.jpeg_box_coords = result[1]
96
- return result[0]
97
- return state.jpeg_original_image
98
-
99
- def on_jpeg_analyze(qf1, qf2, qf_start, qf_end):
100
- if state.jpeg_original_image is not None:
101
- result = run_analysis(state.jpeg_original_image, state.jpeg_box_coords, qf1, qf2, qf_start, qf_end)
102
- return result
103
- return None, None
104
-
105
- jpeg_image_display.upload(on_jpeg_upload, inputs=[jpeg_image_display], outputs=[jpeg_image_display])
106
- jpeg_image_display.select(on_jpeg_click, inputs=[], outputs=[jpeg_image_display])
107
- jpeg_analyze_button.click(
108
- on_jpeg_analyze,
109
- inputs=[qf1_slider, qf2_slider, qf_start_slider, qf_end_slider],
110
- outputs=[jpeg_composite_display, jpeg_difference_plot]
111
- )
112
-
113
- return interface
114
-
115
- # PRNU Analysis Functions
116
- def prnu_interface():
117
- with gr.Blocks() as interface:
118
- gr.Markdown("# 📸 PRNU-Based Image Forgery Detector")
119
- gr.Markdown("""
120
- Uses Photo-Response Non-Uniformity (PRNU) pattern to detect tampered regions.
121
- **Requirements:** You need a camera fingerprint file (.dat format) for analysis.
122
- """)
123
-
124
- with gr.Row():
125
- prnu_fingerprint = gr.File(label="Upload Camera Fingerprint (.dat file)")
126
- prnu_image = gr.Image(type="numpy", label="Upload Image to Analyze")
127
-
128
- prnu_analyze_button = gr.Button("Analyze Image", variant="primary")
129
-
130
- with gr.Row():
131
- prnu_pce_plot = gr.Plot(label="PCE Map")
132
- prnu_image_plot = gr.Plot(label="Analyzed Image")
133
-
134
- def on_prnu_analyze(fingerprint, image):
135
- if fingerprint is None:
136
- raise gr.Error("Please upload a camera fingerprint file!")
137
- if image is None:
138
- raise gr.Error("Please upload an image to analyze!")
139
- return analyze_image_forgery(fingerprint, image)
140
-
141
- prnu_analyze_button.click(
142
- on_prnu_analyze,
143
- inputs=[prnu_fingerprint, prnu_image],
144
- outputs=[prnu_pce_plot, prnu_image_plot]
145
- )
146
-
147
- return interface
148
-
149
- # Shadow Analysis Functions
150
- def shadow_interface():
151
- return build_gradio_interface()
152
-
153
- # Main App
154
- with gr.Blocks(theme=gr.themes.Soft(), title="Digital Image Forensics Toolkit") as demo:
155
- gr.Markdown("""
156
- # 🕵️‍♂️ Digital Image Forensics Toolkit
157
-
158
- This toolkit provides multiple forensic algorithms to detect image manipulations and forgeries.
159
- Select a tool from the dropdown below to begin analysis.
160
- """)
161
-
162
- with gr.Row():
163
- tool_selector = gr.Dropdown(
164
- choices=[
165
- "🎨 Color Filter Array (CFA) Analysis",
166
- "👻 JPEG Ghost Detection",
167
- "📸 PRNU Analysis",
168
- "☀️ Shadow Consistency Analysis"
169
- ],
170
- label="Select Forensic Tool",
171
- value="🎨 Color Filter Array (CFA) Analysis"
172
- )
173
-
174
- tool_output = gr.Tabs()
175
-
176
- # Create all interfaces but only show the selected one
177
- with tool_output:
178
- with gr.TabItem("CFA Analysis") as cfa_tab:
179
- cfa_interface()
180
- with gr.TabItem("JPEG Ghost") as jpeg_tab:
181
- jpeg_interface()
182
- with gr.TabItem("PRNU Analysis") as prnu_tab:
183
- prnu_interface()
184
- with gr.TabItem("Shadow Analysis") as shadow_tab:
185
- shadow_interface()
186
-
187
- # Map tool selection to tabs
188
- tool_map = {
189
- "🎨 Color Filter Array (CFA) Analysis": 0,
190
- "👻 JPEG Ghost Detection": 1,
191
- "📸 PRNU Analysis": 2,
192
- "☀️ Shadow Consistency Analysis": 3
193
- }
194
-
195
- def select_tool(tool_name):
196
- return gr.Tabs(selected=tool_map.get(tool_name, 0))
197
-
198
- tool_selector.change(
199
- select_tool,
200
- inputs=[tool_selector],
201
- outputs=[tool_output]
202
- )
203
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  if __name__ == "__main__":
205
- demo.launch(share=True)
 
 
 
 
 
1
  import os
2
+ os.environ["GRADIO_ANALYTICS_ENABLED"] = "False"
3
+ os.environ["GRADIO_IS_E2E_TEST"] = "True"
4
 
5
+ # Fix for the JSON schema issue
6
+ import warnings
7
+ warnings.filterwarnings("ignore", category=DeprecationWarning)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
+ import gradio as gr
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
+ # Import the UI-creation functions from your tool scripts
12
+ import CFA as CFA_tool
13
+ import JPEG_Ghost as JPEG_Ghost_tool
14
+ #import PRNU as PRNU_tool
15
+ import shadow as shadows_tool
16
+
17
+ # Create the tabbed interface
18
+ demo = gr.TabbedInterface(
19
+ interface_list=[
20
+ CFA_tool.create_ui(),
21
+ JPEG_Ghost_tool.create_ui(),
22
+ PRNU_tool.create_ui(),
23
+ shadows_tool.build_gradio_interface()
24
+ ],
25
+ tab_names=[
26
+ "🎨 CFA Analysis",
27
+ "👻 JPEG Ghost",
28
+ "📸 PRNU Analysis",
29
+ "☀️ Shadow Analysis"
30
+ ],
31
+ title="Digital Image Forensics Toolkit 🕵️‍♂️"
32
+ )
33
+
34
+ # Launch the app
35
  if __name__ == "__main__":
36
+ demo.launch()