Syphaxtwt commited on
Commit
ed4576b
·
verified ·
1 Parent(s): ec22840

Upload 3 files

Browse files
Files changed (3) hide show
  1. app.py +217 -0
  2. model_epoch_10.pth +3 -0
  3. requirements.txt +7 -0
app.py ADDED
@@ -0,0 +1,217 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import torch
3
+ import torch.nn as nn
4
+ from PIL import Image
5
+ from torchvision import transforms
6
+ import os
7
+ from datetime import datetime
8
+ from fpdf import FPDF
9
+
10
+ class MyCNN(nn.Module):
11
+ def __init__(self, in_channel, dropout=0.4):
12
+ super().__init__()
13
+ self.features = nn.Sequential(
14
+ nn.Conv2d(in_channel, 32, kernel_size=3, padding="same"), nn.ReLU(), nn.BatchNorm2d(32), nn.MaxPool2d(2),
15
+ nn.Conv2d(32, 64, kernel_size=3, padding="same"), nn.ReLU(), nn.BatchNorm2d(64), nn.MaxPool2d(2),
16
+ nn.Conv2d(64, 64, kernel_size=3, padding="same"), nn.ReLU(), nn.BatchNorm2d(64), nn.MaxPool2d(2),
17
+ nn.Conv2d(64, 64, kernel_size=3, padding="same"), nn.ReLU(), nn.BatchNorm2d(64), nn.MaxPool2d(2),
18
+ nn.Conv2d(64, 64, kernel_size=3, padding="same"), nn.ReLU(), nn.BatchNorm2d(64), nn.MaxPool2d(2)
19
+ )
20
+ self.classifier = nn.Sequential(
21
+ nn.Flatten(),
22
+ nn.Linear(7*7*64, 128), nn.ReLU(), nn.Dropout(dropout),
23
+ nn.Linear(128, 64), nn.ReLU(), nn.Dropout(dropout),
24
+ nn.Linear(64, 1)
25
+ )
26
+ def forward(self, x):
27
+ return self.classifier(self.features(x))
28
+
29
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
30
+ model = MyCNN(in_channel=3, dropout=0.4)
31
+ try:
32
+ model.load_state_dict(torch.load('model_epoch_10.pth', map_location=device))
33
+ model.to(device).eval()
34
+ except:
35
+ pass
36
+
37
+ transform = transforms.Compose([
38
+ transforms.Resize((224, 224)),
39
+ transforms.ToTensor(),
40
+ transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
41
+ ])
42
+
43
+ def generate_technical_report(verdict, real_conf, ai_conf):
44
+ pdf = FPDF()
45
+ pdf.add_page()
46
+ pdf.set_font("Courier", 'B', 16)
47
+ pdf.set_text_color(40, 40, 40)
48
+ pdf.cell(200, 10, txt="FORENSIC AUTHENTICITY ANALYSIS DATASHEET", ln=True, align='L')
49
+ pdf.set_draw_color(200, 200, 200)
50
+ pdf.line(10, 22, 200, 22)
51
+ pdf.ln(10)
52
+ pdf.set_font("Courier", size=10)
53
+ pdf.cell(200, 5, txt=f"Timestamp: {datetime.now().strftime('%Y-%m-%d %H:%M:%S UTC')}", ln=True)
54
+ pdf.cell(200, 5, txt=f"Neural Engine: MyCNN-v1.0", ln=True)
55
+ pdf.ln(10)
56
+ pdf.set_font("Courier", 'B', 12)
57
+ pdf.cell(200, 10, txt=f"ANALYSIS VERDICT: {verdict}", ln=True)
58
+ pdf.set_font("Courier", size=10)
59
+ pdf.cell(200, 7, txt=f"Probability Real: {real_conf:.4f}", ln=True)
60
+ pdf.cell(200, 7, txt=f"Probability AI: {ai_conf:.4f}", ln=True)
61
+ filename = f"Forensic_Report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pdf"
62
+ pdf.output(filename)
63
+ return filename
64
+
65
+ def analyze_image(image):
66
+ if image is None: return None, "", gr.update(visible=False)
67
+ img_tensor = transform(image.convert('RGB')).unsqueeze(0).to(device)
68
+ with torch.no_grad():
69
+ logits = model(img_tensor)
70
+ prob = torch.sigmoid(logits).item()
71
+ real_conf, ai_conf = prob, 1 - prob
72
+ verdict_text = "REAL" if real_conf > 0.5 else "AI GENERATED"
73
+ verdict_color = "#ffffff" if real_conf > 0.5 else "#f4812a"
74
+ verdict_html = f"""
75
+ <div style="text-align:center;">
76
+ <p style="color:#888; font-size:10px; letter-spacing:2px; margin:0;">VERDICT</p>
77
+ <h2 style="color:{verdict_color}; font-size:28px; font-weight:800; margin:0; font-family:'Rajdhani';">{verdict_text}</h2>
78
+ </div>
79
+ """
80
+ report_path = generate_technical_report(verdict_text, real_conf, ai_conf)
81
+ return {"Real Photo": real_conf, "AI Generated": ai_conf}, verdict_html, gr.update(value=report_path, visible=True)
82
+
83
+ def clear_all():
84
+ return None, None, "", gr.update(visible=False)
85
+
86
+ custom_css = """
87
+ @import url('https://fonts.googleapis.com/css2?family=Rajdhani:wght@400;500;700&display=swap');
88
+ body::-webkit-scrollbar { display: none; }
89
+ body {
90
+ -ms-overflow-style: none;
91
+ scrollbar-width: none;
92
+ background-color: #080a0c !important;
93
+ font-family: 'Rajdhani', sans-serif !important;
94
+ }
95
+ .gradio-container {
96
+ background-color: #080a0c !important;
97
+ font-family: 'Rajdhani', sans-serif !important;
98
+ }
99
+ #main-wrap { max-width: 1000px !important; margin: 40px auto !important; }
100
+ .outer-card {
101
+ background: #101214 !important;
102
+ border: 1px solid #1f2226 !important;
103
+ border-radius: 4px !important;
104
+ padding: 20px !important;
105
+ }
106
+ .inner-dotted {
107
+ border: 1px dashed #333 !important;
108
+ background: #0c0e10 !important;
109
+ border-radius: 2px !important;
110
+ padding: 15px !important;
111
+ margin-top: 10px;
112
+ }
113
+ .header-area { text-align: center; margin-bottom: 30px; border-bottom: 1px solid #1f2226; padding-bottom: 30px; }
114
+ .header-area h1 {
115
+ color: #ffffff;
116
+ font-family: 'Rajdhani', sans-serif !important;
117
+ font-weight: 700;
118
+ letter-spacing: 3px;
119
+ font-size: 42px;
120
+ margin-bottom: 0px;
121
+ text-transform: uppercase;
122
+ }
123
+ .tech-sub {
124
+ color: #aaaaaa;
125
+ font-family: 'Rajdhani', sans-serif !important;
126
+ font-size: 16px;
127
+ margin-top: 12px;
128
+ max-width: 800px;
129
+ margin-left: auto;
130
+ margin-right: auto;
131
+ line-height: 1.5;
132
+ }
133
+ #submit-btn { background: #f4812a !important; color: #000000 !important; font-weight: 700 !important; border-radius: 2px !important; border: none !important; cursor: pointer; transition: 0.2s; font-family: 'Rajdhani' !important; }
134
+ #submit-btn:hover { background: #cccccc !important; }
135
+ #clear-btn { background: #1a1c1e !important; color: #ffffff !important; font-weight: 700 !important; border-radius: 2px !important; border: 1px solid #2d3135 !important; cursor: pointer; font-family: 'Rajdhani' !important; }
136
+ .guide-box { margin-top: 20px; padding: 15px; background: #101214; border-radius: 4px; border: 1px solid #1f2226; }
137
+ .guide-text { color: #555; font-size: 13px; text-transform: uppercase; letter-spacing: 1px; font-weight: 600; font-family: 'Rajdhani' !important; }
138
+ .label-box span { display: none !important; }
139
+ .gradio-container .prose h2 {
140
+ margin: 0 !important;
141
+ color: #ffffff !important;
142
+ font-size: 16px !important;
143
+ letter-spacing: 1px;
144
+ text-transform: uppercase;
145
+ font-family: 'Rajdhani' !important;
146
+ }
147
+ .source-link { text-align: center; margin-top: 50px; }
148
+ .source-link a {
149
+ color: #ffffff;
150
+ text-decoration: none;
151
+ font-size: 20px;
152
+ letter-spacing: 1px;
153
+ transition: 0.3s;
154
+ font-family: 'Rajdhani', sans-serif !important;
155
+ font-weight: 500;
156
+ }
157
+ .source-link a:hover { color: #f4812a; }
158
+ """
159
+
160
+ with gr.Blocks(css=custom_css) as demo:
161
+ with gr.Column(elem_id="main-wrap"):
162
+ gr.HTML("""
163
+ <div class="header-area">
164
+ <h1>AI Image Authentication</h1>
165
+ <div class="tech-sub">
166
+ Forensic Neural Analysis Interface
167
+ </div>
168
+ </div>
169
+ """)
170
+ with gr.Row(equal_height=True):
171
+ with gr.Column(scale=1, elem_classes="outer-card"):
172
+ gr.Markdown("## 01. SOURCE MATERIAL")
173
+ with gr.Column(elem_classes="inner-dotted"):
174
+ input_img = gr.Image(label="Source", type="pil", show_label=False, container=False)
175
+ with gr.Row():
176
+ clear_btn = gr.Button("CLEAR", elem_id="clear-btn")
177
+ submit_btn = gr.Button("SUBMIT ANALYSIS", elem_id="submit-btn")
178
+ with gr.Column(scale=1, elem_classes="outer-card"):
179
+ gr.Markdown("## 02. FORENSIC OUTPUT")
180
+ with gr.Column(elem_classes="inner-dotted"):
181
+ out_verdict = gr.HTML("<div style='text-align:center; padding:15px; color:#444;'>Awaiting input analysis...</div>")
182
+ out_label = gr.Label(num_top_classes=2, label="Confidence", elem_classes="label-box")
183
+ gr.HTML("<div style='height:15px;'></div>")
184
+ report_file = gr.File(label="DATASHEET", visible=False)
185
+ with gr.Row(elem_classes="guide-box"):
186
+ gr.HTML("""
187
+ <div style="display:flex; justify-content:space-around; width:100%; text-align:center;">
188
+ <div class="guide-text">STEP 1: UPLOAD TARGET IMAGE</div>
189
+ <div class="guide-text" style="color:#222;">|</div>
190
+ <div class="guide-text">STEP 2: INITIATE CNN SCAN</div>
191
+ <div class="guide-text" style="color:#222;">|</div>
192
+ <div class="guide-text">STEP 3: EXPORT TECHNICAL PDF</div>
193
+ </div>
194
+ """)
195
+ gr.HTML("""
196
+ <div class="source-link">
197
+ <a href="https://github.com/rkcode2025" target="_blank">SOURCE CODE</a>
198
+ </div>
199
+ """)
200
+ gr.HTML("""
201
+ <div style="text-align:center; margin-top:10px; border-top:1px solid #1f2226; padding-top:20px; color:#333; font-size:10px; letter-spacing:1px;">
202
+ SYSTEM STATUS: OPERATIONAL • BUILD: 5.0.4 • HARDWARE: ACCELERATED
203
+ </div>
204
+ """)
205
+ submit_btn.click(
206
+ fn=analyze_image,
207
+ inputs=input_img,
208
+ outputs=[out_label, out_verdict, report_file],
209
+ show_progress="full"
210
+ )
211
+ clear_btn.click(
212
+ fn=clear_all,
213
+ outputs=[input_img, out_label, out_verdict, report_file]
214
+ )
215
+
216
+ if __name__ == "__main__":
217
+ demo.launch()
model_epoch_10.pth ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9317e0178364f8724f8f2e6854c8f99ad0f11e5da6aedd3bd65211f91babf436
3
+ size 2179249
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ torch
2
+ torchvision
3
+ gradio
4
+ fpdf
5
+ datasets
6
+ tqdm
7
+ Pillow