File size: 2,917 Bytes
56d9c2e
 
 
 
 
 
 
 
c3c1d28
56d9c2e
 
 
c3c1d28
56d9c2e
 
 
 
 
af414f6
56d9c2e
 
 
 
 
 
 
 
 
af414f6
 
c3c1d28
af414f6
56d9c2e
af414f6
56d9c2e
 
 
 
 
 
 
 
 
c3c1d28
 
56d9c2e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
af414f6
56d9c2e
 
 
 
af414f6
56d9c2e
 
c3c1d28
56d9c2e
 
c3c1d28
56d9c2e
 
c3c1d28
 
56d9c2e
 
 
c3c1d28
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import os
import string
import torch
import torch.nn as nn
import gradio as gr
from PIL import Image
from torchvision import transforms

# ---------- Config ----------
CHARS = string.digits + string.ascii_uppercase
NUM_CLASSES = len(CHARS)
CAPTCHA_LEN = 6
IMG_W, IMG_H = 200, 80        # ต้องตรงกับ Colab ที่เทรน
DEVICE = torch.device("cpu")

CHAR2IDX = {c: i for i, c in enumerate(CHARS)}
IDX2CHAR = {i: c for c, i in CHAR2IDX.items()}

# ---------- Model ----------
class CaptchaNet(nn.Module):
    def __init__(self):
        super().__init__()
        self.cnn = nn.Sequential(
            nn.Conv2d(1, 32, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
            nn.Conv2d(32, 64, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
            nn.Conv2d(64, 128, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2),
        )
        with torch.no_grad():
            dummy = torch.zeros(1, 1, IMG_H, IMG_W)
            d = self.cnn(dummy).flatten(1).shape[1]
            print(f"Flatten size: {d}")
        
        self.fc = nn.Sequential(
            nn.Linear(d, 512), nn.ReLU(), nn.Dropout(0.4),
            nn.Linear(512, CAPTCHA_LEN * NUM_CLASSES)
        )
    def forward(self, x):
        x = self.cnn(x).flatten(1)
        x = self.fc(x)
        return x.view(-1, CAPTCHA_LEN, NUM_CLASSES)

# โหลดโมเดล
model = CaptchaNet().to(DEVICE)
if os.path.exists("model.pt"):
    model.load_state_dict(torch.load("model.pt", map_location=DEVICE, weights_only=True))
    print("✅ โหลดโมเดลสำเร็จ")
else:
    print("⚠️ ไม่พบไฟล์ model.pt")

model.eval()

# Transform
tf = transforms.Compose([
    transforms.Grayscale(),
    transforms.Resize((IMG_H, IMG_W)),
    transforms.ToTensor(),
])

def predict_captcha(image: Image.Image):
    if image is None:
        return "กรุณาอัปโหลดรูปภาพ CAPTCHA 6 หลัก"
    
    x = tf(image).unsqueeze(0).to(DEVICE)
    with torch.no_grad():
        out = model(x).argmax(-1)[0].cpu().tolist()
    result = "".join(IDX2CHAR.get(i, "?") for i in out)
    return result

# Gradio UI (เวอร์ชันใหม่)
demo = gr.Interface(
    fn=predict_captcha,
    inputs=gr.Image(type="pil", label="📤 อัปโหลดรูป CAPTCHA 6 หลัก (0-9 และ A-Z)"),
    outputs=gr.Textbox(label="🔠 ผลลัพธ์ที่โมเดลทำนาย"),
    title="🛡️ CAPTCHA Solver 6 หลัก",
    description="โมเดลเทรนด้วยภาพสังเคราะห์ 6 ตัวอักษร\nอัปโหลดรูปแล้วกด Submit",
    # ไม่ใส่ theme และ allow_flagging ที่นี่
)

if __name__ == "__main__":
    demo.launch(
        server_name="0.0.0.0",
        server_port=7860,
        share=False,
        show_error=True
    )