import gradio as gr import torch import torch.nn as nn from PIL import Image from torchvision import transforms import os from datetime import datetime from fpdf import FPDF class MyCNN(nn.Module): def __init__(self, in_channel, dropout=0.4): super().__init__() self.features = nn.Sequential( nn.Conv2d(in_channel, 32, kernel_size=3, padding="same"), nn.ReLU(), nn.BatchNorm2d(32), nn.MaxPool2d(2), nn.Conv2d(32, 64, kernel_size=3, padding="same"), nn.ReLU(), nn.BatchNorm2d(64), nn.MaxPool2d(2), nn.Conv2d(64, 64, kernel_size=3, padding="same"), nn.ReLU(), nn.BatchNorm2d(64), nn.MaxPool2d(2), nn.Conv2d(64, 64, kernel_size=3, padding="same"), nn.ReLU(), nn.BatchNorm2d(64), nn.MaxPool2d(2), nn.Conv2d(64, 64, kernel_size=3, padding="same"), nn.ReLU(), nn.BatchNorm2d(64), nn.MaxPool2d(2) ) self.classifier = nn.Sequential( nn.Flatten(), nn.Linear(7*7*64, 128), nn.ReLU(), nn.Dropout(dropout), nn.Linear(128, 64), nn.ReLU(), nn.Dropout(dropout), nn.Linear(64, 1) ) def forward(self, x): return self.classifier(self.features(x)) device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model = MyCNN(in_channel=3, dropout=0.4) try: model.load_state_dict(torch.load('model_epoch_10.pth', map_location=device)) model.to(device).eval() except: pass transform = transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]) ]) def generate_technical_report(verdict, real_conf, ai_conf): pdf = FPDF() pdf.add_page() pdf.set_font("Courier", 'B', 16) pdf.set_text_color(40, 40, 40) pdf.cell(200, 10, txt="FORENSIC AUTHENTICITY ANALYSIS DATASHEET", ln=True, align='L') pdf.set_draw_color(200, 200, 200) pdf.line(10, 22, 200, 22) pdf.ln(10) pdf.set_font("Courier", size=10) pdf.cell(200, 5, txt=f"Timestamp: {datetime.now().strftime('%Y-%m-%d %H:%M:%S UTC')}", ln=True) pdf.cell(200, 5, txt=f"Neural Engine: MyCNN-v1.0", ln=True) pdf.ln(10) pdf.set_font("Courier", 'B', 12) pdf.cell(200, 10, txt=f"ANALYSIS VERDICT: {verdict}", ln=True) pdf.set_font("Courier", size=10) pdf.cell(200, 7, txt=f"Probability Real: {real_conf:.4f}", ln=True) pdf.cell(200, 7, txt=f"Probability AI: {ai_conf:.4f}", ln=True) filename = f"Forensic_Report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pdf" pdf.output(filename) return filename def analyze_image(image): if image is None: return None, "", gr.update(visible=False) img_tensor = transform(image.convert('RGB')).unsqueeze(0).to(device) with torch.no_grad(): logits = model(img_tensor) prob = torch.sigmoid(logits).item() real_conf, ai_conf = prob, 1 - prob verdict_text = "REAL" if real_conf > 0.5 else "AI GENERATED" verdict_color = "#ffffff" if real_conf > 0.5 else "#f4812a" verdict_html = f"""

VERDICT

{verdict_text}

""" report_path = generate_technical_report(verdict_text, real_conf, ai_conf) return {"Real Photo": real_conf, "AI Generated": ai_conf}, verdict_html, gr.update(value=report_path, visible=True) def clear_all(): return None, None, "", gr.update(visible=False) custom_css = """ @import url('https://fonts.googleapis.com/css2?family=Rajdhani:wght@400;500;700&display=swap'); body::-webkit-scrollbar { display: none; } body { -ms-overflow-style: none; scrollbar-width: none; background-color: #080a0c !important; font-family: 'Rajdhani', sans-serif !important; } .gradio-container { background-color: #080a0c !important; font-family: 'Rajdhani', sans-serif !important; } #main-wrap { max-width: 1000px !important; margin: 40px auto !important; } .outer-card { background: #101214 !important; border: 1px solid #1f2226 !important; border-radius: 4px !important; padding: 20px !important; } .inner-dotted { border: 1px dashed #333 !important; background: #0c0e10 !important; border-radius: 2px !important; padding: 15px !important; margin-top: 10px; } .header-area { text-align: center; margin-bottom: 30px; border-bottom: 1px solid #1f2226; padding-bottom: 30px; } .header-area h1 { color: #ffffff; font-family: 'Rajdhani', sans-serif !important; font-weight: 700; letter-spacing: 3px; font-size: 42px; margin-bottom: 0px; text-transform: uppercase; } .tech-sub { color: #aaaaaa; font-family: 'Rajdhani', sans-serif !important; font-size: 16px; margin-top: 12px; max-width: 800px; margin-left: auto; margin-right: auto; line-height: 1.5; } #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; } #submit-btn:hover { background: #cccccc !important; } #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; } .guide-box { margin-top: 20px; padding: 15px; background: #101214; border-radius: 4px; border: 1px solid #1f2226; } .guide-text { color: #555; font-size: 13px; text-transform: uppercase; letter-spacing: 1px; font-weight: 600; font-family: 'Rajdhani' !important; } .label-box span { display: none !important; } .gradio-container .prose h2 { margin: 0 !important; color: #ffffff !important; font-size: 16px !important; letter-spacing: 1px; text-transform: uppercase; font-family: 'Rajdhani' !important; } .source-link { text-align: center; margin-top: 50px; } .source-link a { color: #ffffff; text-decoration: none; font-size: 20px; letter-spacing: 1px; transition: 0.3s; font-family: 'Rajdhani', sans-serif !important; font-weight: 500; } .source-link a:hover { color: #f4812a; } """ with gr.Blocks(css=custom_css) as demo: with gr.Column(elem_id="main-wrap"): gr.HTML("""

AI Image Authentication

Forensic Neural Analysis Interface
""") with gr.Row(equal_height=True): with gr.Column(scale=1, elem_classes="outer-card"): gr.Markdown("## 01. SOURCE MATERIAL") with gr.Column(elem_classes="inner-dotted"): input_img = gr.Image(label="Source", type="pil", show_label=False, container=False) with gr.Row(): clear_btn = gr.Button("CLEAR", elem_id="clear-btn") submit_btn = gr.Button("SUBMIT ANALYSIS", elem_id="submit-btn") with gr.Column(scale=1, elem_classes="outer-card"): gr.Markdown("## 02. FORENSIC OUTPUT") with gr.Column(elem_classes="inner-dotted"): out_verdict = gr.HTML("
Awaiting input analysis...
") out_label = gr.Label(num_top_classes=2, label="Confidence", elem_classes="label-box") gr.HTML("
") report_file = gr.File(label="DATASHEET", visible=False) with gr.Row(elem_classes="guide-box"): gr.HTML("""
STEP 1: UPLOAD TARGET IMAGE
|
STEP 2: INITIATE CNN SCAN
|
STEP 3: EXPORT TECHNICAL PDF
""") gr.HTML(""" """) gr.HTML("""
SYSTEM STATUS: OPERATIONAL • BUILD: 5.0.4 • HARDWARE: ACCELERATED
""") submit_btn.click( fn=analyze_image, inputs=input_img, outputs=[out_label, out_verdict, report_file], show_progress="full" ) clear_btn.click( fn=clear_all, outputs=[input_img, out_label, out_verdict, report_file] ) if __name__ == "__main__": demo.launch()