-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathghostati.html
More file actions
223 lines (202 loc) · 11.2 KB
/
ghostati.html
File metadata and controls
223 lines (202 loc) · 11.2 KB
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
<!doctype html>
<html lang="it">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Ghòstati</title>
<!-- Se mi rompi il cazzo perchè ho messo dei google fonts: hai ragione e fai bene. -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=League+Script&family=Outfit:wght@400;600;700;800;900&family=JetBrains+Mono:wght@400;700&display=swap"
rel="stylesheet">
<meta name="description"
content="Laboratorio Web AR per lo sviluppo e il test di trucco anti-riconoscimento biometrico (CV Dazzle)." />
<meta property="og:title" content="Ghòstati | Face Lab" />
<meta property="og:description"
content="Laboratorio Web AR in tempo reale per lo sviluppo di camuffamenti anti-riconoscimento biometrico (CV Dazzle) via plugin." />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://sindacato.nina.watch/ghostati/" />
<meta property="og:image" content="https://sindacato.nina.watch/ghostati/facerec-transparency.png" />
<meta property="og:site_name" content="NINA" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<link rel="sitemap" type="application/xml" title="Sitemap" href="sitemap.xml" />
<meta name="generator" content="Hand-coded with rage against the algorithm" />
<link rel="source" href="https://github.com/vecna/ghostati" />
<link rel="stylesheet" href="styles/ghostati.css" />
</head>
<body>
<!-- The fullscreen background -->
<div class="viewer fullscreen" id="viewer">
<div class="status-pill"><span id="statusDot" class="status-dot"></span><span
id="statusText">inizializzazione...</span></div>
<div id="placeholder">Caricamento modelli e richiesta webcam…</div>
<video id="video" autoplay muted playsinline></video>
<img id="previewImage" alt="preview diagnostica" />
<canvas id="overlay"></canvas>
<canvas id="mesh3dOverlay"></canvas>
<canvas id="bboxOverlay"></canvas>
</div>
<!-- Mobile Floating UI Layers -->
<!-- Top Left: Main Actions -->
<div class="floating-container top-left">
<button id="scanBtn" class="floating-btn main-action" title="Scansiona Faccia">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<path d="M3 7V5a2 2 0 0 1 2-2h2" />
<path d="M17 3h2a2 2 0 0 1 2 2v2" />
<path d="M21 17v2a2 2 0 0 1-2 2h-2" />
<path d="M7 21H5a2 2 0 0 1-2-2v-2" />
<path d="M8 14s1.5 2 4 2 4-2 4-2" />
<path d="M9 9h.01" />
<path d="M15 9h.01" />
</svg>
</button>
<button id="copyMakeupBtn" class="floating-btn main-action" disabled title="Copia volto truccato">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
</svg>
</button>
<button id="fullscreenBtn" class="floating-btn main-action" title="Fullscreen">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"></path>
</svg>
</button>
</div>
<!-- Top Right: Settings Toggle -->
<div class="floating-container top-right">
<button id="toggleSettingsBtn" class="floating-btn" title="Impostazioni">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<circle cx="12" cy="12" r="3"></circle>
<path
d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z">
</path>
</svg>
</button>
</div>
<!-- Middle Right: Vertical Actions -->
<div class="floating-container right-sidebar">
<button id="saveBtn" class="floating-btn side-action" title="Salva faccia">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"></path>
</svg>
</button>
<div class="badge-container">
<button id="findBtn" class="floating-btn side-action" title="Trova faccia">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
</button>
<span id="dbCountBadge" class="notification-badge" style="display: none;">0</span>
</div>
<button id="clearDbBtn" class="floating-btn side-action" title="Azzera archivio">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<polyline points="3 6 5 6 21 6"></polyline>
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
</svg>
</button>
<button id="switchCameraBtn" class="floating-btn side-action" title="Gira webcam">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"></path>
<path d="M3 3v5h5"></path>
</svg>
</button>
</div>
<!-- Plugin 3D parameters panel — visible only when an active 3D plugin declares `params` -->
<div id="plugin3dParamsPanel" aria-hidden="true">
<!-- Generato dinamicamente da plugins3d-loader.js -->
</div>
<!-- Bottom: Logs -->
<div class="logbox floating-logbox" id="logBox">
<div class="log-line">In attesa dell’avvio della webcam…</div>
</div>
<!-- Settings Drawer / Menu Overlay -->
<div id="settingsDrawer" class="settings-drawer hidden">
<div class="drawer-header">
<h2>Ghòstati! Menu</h2>
<button id="closeSettingsBtn" class="icon-btn" title="Chiudi">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
<div class="drawer-content scrollable">
<!-- Info intro -->
<p class="small-note">Laboratorio Web AR in tempo reale per lo sviluppo di camuffamenti.</p>
<!-- Ghostyles Section -->
<div class="panel-header">
<p style="margin-top:0;">Overlay live ancorati ai landmark del volto.</p>
</div>
<div class="stack" id="ghostylesContainer">
<!-- Generati dinamicamente -->
</div>
<!-- Ghostyles 3D Section -->
<div class="panel-header">
<p style="margin-top:0;">Pattern 3D ancorati alla mesh facciale (MediaPipe, 478 landmark).</p>
</div>
<div class="stack" id="ghostyles3dContainer">
<!-- Generati dinamicamente da plugins3d-loader.js -->
</div>
<div style="padding: 0 16px 12px;">
<select id="fpsSelect"
style="width: 100%; padding: 10px 14px; background: rgba(0, 0, 0, 0.4); border: 1px solid rgba(255, 255, 255, 0.08); border-radius: 10px; color: var(--muted); font-size: 13px; font-weight: 600; text-align: left; cursor: pointer; outline: none; appearance: none; -webkit-appearance: none;">
<option value="30">⚙️ Frequenza analisi: 30ms (Pesante)</option>
<option value="60">⚙️ Frequenza analisi: 60ms (Veloce)</option>
<option value="90">⚙️ Frequenza analisi: 90ms (Media)</option>
<option value="120" selected>⚙️ Frequenza analisi: 120ms (Ecosostenibile)</option>
</select>
</div>
<div id="ghostyleDetails" class="stack"
style="padding-top: 0; border-top: 1px solid rgba(255,255,255,0.05); margin-top: 0px; background-color: var(--accent-2); border-radius: 12px; padding: 12px;">
<input type="url" id="remoteGhostyleUrl"
style="background: rgba(0,0,0,0.3); font-size:12px; text-align: left; padding: 10px; cursor: text; width: 100%; border: 1px solid rgba(255,255,255,0.1); border-radius: 6px; color: white; margin-bottom: 8px;"
placeholder="https://.../urleffect.js" />
<button id="loadRemoteGhostyleBtn" class="secondary-btn">Carica Ghostyle Remoto</button>
<a href="ghostati-docs.html" class="btn-link"
style="text-align: center; color: var(--bg); display: block; margin-top: 8px; text-decoration: none;">📖
Documentazione</a>
</div>
<!-- Controls -->
<div class="stack">
<!-- Il bottone mirror esiste ancora ma potremmo nasconderlo tramite CSS se gestito via JS, lo lascio nel DOM per fallback -->
<button id="mirrorToggle" class="secondary-btn" style="display: none;">Mirror webcam</button>
<button id="clearOverlayBtn" class="secondary-btn">Pulisci overlay manuale</button>
</div>
<!-- Metrics / Info -->
<div class="list-card">
<h3>Archivio locale</h3>
<div class="metric"><span>Volti salvati</span><strong id="dbCount">0</strong></div>
<div class="metric"><span>Prossimo ID</span><strong id="nextId">0</strong></div>
<div class="metric"><span>Soglia match</span><strong id="thresholdLabel">0.58</strong></div>
<div class="metric"><span>Opacità stimata</span><strong>0.45</strong></div>
</div>
<div class="list-card" style="margin-bottom: 40px;">
<h3>Modalità attiva</h3>
<div class="metric"><span>Effetto</span><strong id="effectName">nessuno</strong></div>
<div class="metric"><span>Tracking</span><strong id="effectTracking">off</strong></div>
<div class="metric"><span>Rendering</span><strong>live su landmark</strong></div>
</div>
</div>
</div>
<!-- Scripts -->
<script src="https://cdn.jsdelivr.net/gh/justadudewhohacks/face-api.js@0.22.2/dist/face-api.min.js"></script>
<script src="scripts/ghostati.js"></script>
<script src="scripts/ghostati-mobile-ui.js"></script>
<script src="scripts/bbox-overlay.js"></script>
<script src="scripts/auto-find-loop.js"></script>
<script type="module" src="scripts/mediapipe-loop.js"></script>
<script src="scripts/ghostyle3d-uv-renderer.js"></script>
<script src="scripts/plugins3d-loader.js"></script>
</body>
</html>