nadizik commited on
Commit
4dc0321
·
verified ·
1 Parent(s): 11a1299

Upload INTERFERENCE_GUi.py

Browse files
Files changed (1) hide show
  1. INTERFERENCE_GUi.py +158 -0
INTERFERENCE_GUi.py ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import tkinter as tk
4
+ from tkinter import ttk
5
+ import numpy as np
6
+ from scipy.interpolate import interp1d
7
+ import torch
8
+ import torch.nn as nn
9
+ import torch.nn.functional as F
10
+
11
+ def get_base_dir():
12
+ if getattr(sys, 'frozen', False):
13
+ return getattr(sys, '_MEIPASS', os.path.dirname(sys.executable))
14
+ return os.path.dirname(os.path.abspath(__file__))
15
+
16
+ class TaranCore(nn.Module):
17
+ """Gesture Classification MLP matching exact model.pth tensor dimensions (128 -> 64 -> 32 -> 8)."""
18
+
19
+ def __init__(self, in_d=128, hid1_d=64, hid2_d=32, out_d=8):
20
+ super().__init__()
21
+ self.net = nn.Sequential(
22
+ nn.Linear(in_d, hid1_d),
23
+ nn.LeakyReLU(0.1),
24
+ nn.Linear(hid1_d, hid2_d),
25
+ nn.LeakyReLU(0.1),
26
+ nn.Linear(hid2_d, out_d)
27
+ )
28
+
29
+ def forward(self, x, temp=0.45):
30
+ if x.shape[0] == 1:
31
+ self.eval()
32
+ logits = self.net(x)
33
+ return F.softmax(logits / temp, dim=-1)
34
+
35
+ def process_pattern(points, target_pts=64):
36
+ pts = np.array(points, dtype=np.float32)
37
+ if len(pts) < 5:
38
+ return np.zeros(target_pts * 2, dtype=np.float32)
39
+
40
+ pts -= np.mean(pts, axis=0)
41
+ norm = np.max(np.abs(pts))
42
+ if norm > 0:
43
+ pts /= norm
44
+
45
+ try:
46
+ dist = np.sqrt(np.sum(np.diff(pts, axis=0) ** 2, axis=1))
47
+ dist = np.concatenate(([0], np.cumsum(dist)))
48
+ d_norm = dist / dist[-1]
49
+ d_norm, u_idx = np.unique(d_norm, return_index=True)
50
+ pts = pts[u_idx]
51
+
52
+ fx = interp1d(d_norm, pts[:, 0], fill_value="extrapolate")
53
+ fy = interp1d(d_norm, pts[:, 1], fill_value="extrapolate")
54
+ steps = np.linspace(0, 1, target_pts)
55
+ return np.vstack((fx(steps), fy(steps))).T.flatten()
56
+ except Exception:
57
+ return np.zeros(target_pts * 2, dtype=np.float32)
58
+
59
+ class GestureTesterApp:
60
+ def __init__(self, root, model):
61
+ self.root = root
62
+ self.root.title("TaranCore Gesture Recognizer - Interactive Test")
63
+ self.root.geometry("600x550")
64
+ self.root.resizable(False, False)
65
+ self.model = model
66
+ self.points = []
67
+
68
+ # UI Components
69
+ self.label_title = ttk.Label(root, text="Draw a gesture using Mouse or Touchpad", font=("Arial", 12, "bold"))
70
+ self.label_title.pack(pady=10)
71
+
72
+ self.canvas = tk.Canvas(root, width=400, height=300, bg="white", relief="ridge", bd=2)
73
+ self.canvas.pack(pady=5)
74
+
75
+ self.canvas.bind("<ButtonPress-1>", self.on_press)
76
+ self.canvas.bind("<B1-Motion>", self.on_drag)
77
+ self.canvas.bind("<ButtonRelease-1>", self.on_release)
78
+
79
+ self.label_result = ttk.Label(root, text="Result: Draw something...", font=("Arial", 14, "bold"), foreground="blue")
80
+ self.label_result.pack(pady=10)
81
+
82
+ self.frame_probs = ttk.Frame(root)
83
+ # Исправлено: padx=20 вместо px=20
84
+ self.frame_probs.pack(pady=5, fill="x", padx=20)
85
+
86
+ self.prob_labels = []
87
+ for i in range(8):
88
+ lbl = ttk.Label(self.frame_probs, text=f"Class {i}: 0.0%", font=("Consolas", 9))
89
+ lbl.grid(row=i // 4, column=i % 4, padx=15, pady=2)
90
+ self.prob_labels.append(lbl)
91
+
92
+ self.btn_clear = ttk.Button(root, text="Clear Canvas", command=self.clear_canvas)
93
+ self.btn_clear.pack(pady=15)
94
+
95
+ def on_press(self, event):
96
+ self.clear_canvas()
97
+ self.points.append((event.x, event.y))
98
+
99
+ def on_drag(self, event):
100
+ if self.points:
101
+ x_prev, y_prev = self.points[-1]
102
+ self.canvas.create_line(x_prev, y_prev, event.x, event.y, fill="black", width=3, capstyle=tk.ROUND, smooth=True)
103
+ self.points.append((event.x, event.y))
104
+
105
+ def on_release(self, event):
106
+ if len(self.points) < 5:
107
+ self.label_result.config(text="Result: Gesture too short!", foreground="red")
108
+ return
109
+
110
+ vector = process_pattern(self.points)
111
+ input_tensor = torch.FloatTensor(vector).unsqueeze(0)
112
+
113
+ with torch.no_grad():
114
+ probs = self.model(input_tensor).numpy().flatten()
115
+
116
+ predicted_class = int(np.argmax(probs))
117
+ confidence = float(probs[predicted_class] * 100)
118
+
119
+ self.label_result.config(
120
+ text=f"Detected: Class {predicted_class} ({confidence:.1f}%)",
121
+ foreground="green"
122
+ )
123
+
124
+ for idx, prob in enumerate(probs):
125
+ self.prob_labels[idx].config(text=f"Class {idx}: {prob * 100:.1f}%")
126
+
127
+ def clear_canvas(self):
128
+ self.canvas.delete("all")
129
+ self.points.clear()
130
+ self.label_result.config(text="Result: Draw something...", foreground="blue")
131
+
132
+ def main():
133
+ base_dir = get_base_dir()
134
+ weights_path = os.path.join(base_dir, "model.pth")
135
+
136
+ if not os.path.exists(weights_path):
137
+ print(f"[ERROR] Weights file not found: {weights_path}")
138
+ return
139
+
140
+ model = TaranCore(in_d=128, hid1_d=64, hid2_d=32, out_d=8)
141
+
142
+ try:
143
+ state_dict = torch.load(weights_path, map_location="cpu")
144
+ model.load_state_dict(state_dict)
145
+ model.eval()
146
+ except Exception as e:
147
+ print(f"[ERROR] Failed to load model state: {e}")
148
+ return
149
+
150
+ root = tk.Tk()
151
+ app = GestureTesterApp(root, model)
152
+ root.mainloop()
153
+
154
+
155
+ if __name__ == "__main__":
156
+ import multiprocessing
157
+ multiprocessing.freeze_support()
158
+ main()