Spaces:
Running
Running
Add 1 files
Browse files- index.html +505 -384
index.html
CHANGED
@@ -3,446 +3,567 @@
|
|
3 |
<head>
|
4 |
<meta charset="UTF-8">
|
5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
-
<title>
|
7 |
<script src="https://cdn.tailwindcss.com"></script>
|
|
|
8 |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
9 |
<style>
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
background-color: #f8f5f2;
|
15 |
-
color: #333;
|
16 |
}
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
}
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
min-height: 60vh;
|
27 |
}
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
backdrop-filter: blur(5px);
|
32 |
}
|
33 |
-
|
34 |
-
|
35 |
-
content: '';
|
36 |
-
position: absolute;
|
37 |
-
left: -30px;
|
38 |
-
top: 0;
|
39 |
-
width: 20px;
|
40 |
-
height: 20px;
|
41 |
-
border-radius: 50%;
|
42 |
-
background-color: #8b5a2b;
|
43 |
-
border: 3px solid #f8f5f2;
|
44 |
}
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
position: absolute;
|
49 |
-
left: -20px;
|
50 |
-
top: 0;
|
51 |
-
bottom: 0;
|
52 |
-
width: 2px;
|
53 |
-
background-color: #8b5a2b;
|
54 |
}
|
55 |
-
|
56 |
-
|
57 |
-
|
|
|
58 |
}
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
height: 2px;
|
65 |
-
background: #8b5a2b;
|
66 |
-
transition: width .3s;
|
67 |
}
|
68 |
-
|
69 |
-
|
70 |
width: 100%;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
}
|
72 |
</style>
|
73 |
</head>
|
74 |
-
<body>
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
<
|
79 |
-
|
80 |
-
<img src="https://www.avatarmeherbabatrust.org/wp-content/uploads/2020/04/AMB-logo.png" alt="Meher Baba Logo" class="h-12">
|
81 |
-
<span class="ml-3 title-font text-xl text-gray-800">Avatar Meher Baba</span>
|
82 |
-
</div>
|
83 |
-
<div class="hidden md:flex space-x-8">
|
84 |
-
<a href="#home" class="nav-link text-gray-700 hover:text-amber-800 transition duration-300">Home</a>
|
85 |
-
<a href="#about" class="nav-link text-gray-700 hover:text-amber-800 transition duration-300">About</a>
|
86 |
-
<a href="#teachings" class="nav-link text-gray-700 hover:text-amber-800 transition duration-300">Teachings</a>
|
87 |
-
<a href="#timeline" class="nav-link text-gray-700 hover:text-amber-800 transition duration-300">Timeline</a>
|
88 |
-
<a href="#contact" class="nav-link text-gray-700 hover:text-amber-800 transition duration-300">Contact</a>
|
89 |
-
</div>
|
90 |
-
<button class="md:hidden text-gray-700 focus:outline-none">
|
91 |
-
<i class="fas fa-bars text-2xl"></i>
|
92 |
-
</button>
|
93 |
-
</div>
|
94 |
-
</div>
|
95 |
-
</nav>
|
96 |
-
|
97 |
-
<!-- Hero Section -->
|
98 |
-
<section id="home" class="hero-image flex items-center justify-center relative">
|
99 |
-
<div class="text-center px-6">
|
100 |
-
<h1 class="title-font text-4xl md:text-6xl text-white mb-6">Avatar Meher Baba</h1>
|
101 |
-
<p class="text-xl md:text-2xl text-white mb-8">"Don't worry, be happy"</p>
|
102 |
-
<a href="#about" class="bg-amber-800 hover:bg-amber-700 text-white px-6 py-3 rounded-full transition duration-300 inline-block">
|
103 |
-
Learn More
|
104 |
-
</a>
|
105 |
-
</div>
|
106 |
-
<div class="absolute bottom-0 left-0 right-0 flex justify-center pb-4">
|
107 |
-
<a href="#about" class="text-white animate-bounce">
|
108 |
-
<i class="fas fa-chevron-down text-2xl"></i>
|
109 |
-
</a>
|
110 |
-
</div>
|
111 |
-
</section>
|
112 |
-
|
113 |
-
<!-- About Section -->
|
114 |
-
<section id="about" class="py-20 bg-white">
|
115 |
-
<div class="container mx-auto px-6">
|
116 |
-
<div class="text-center mb-16">
|
117 |
-
<h2 class="title-font text-3xl md:text-4xl text-gray-800 mb-4">The Silent Master</h2>
|
118 |
-
<div class="w-20 h-1 bg-amber-800 mx-auto"></div>
|
119 |
-
</div>
|
120 |
-
|
121 |
-
<div class="flex flex-col md:flex-row items-center">
|
122 |
-
<div class="md:w-1/2 mb-10 md:mb-0 md:pr-10">
|
123 |
-
<img src="https://www.avatarmeherbabatrust.org/wp-content/uploads/2020/04/Meher-Baba.jpg" alt="Meher Baba" class="rounded-lg shadow-xl w-full max-w-md mx-auto">
|
124 |
-
</div>
|
125 |
-
<div class="md:w-1/2">
|
126 |
-
<h3 class="title-font text-2xl text-gray-800 mb-4">Merwan Sheriar Irani (1894-1969)</h3>
|
127 |
-
<p class="text-gray-600 mb-4">
|
128 |
-
Avatar Meher Baba, born Merwan Sheriar Irani, was an Indian spiritual master who declared himself to be the Avatar (an incarnation of God) of the age. He maintained silence from 1925 until his death in 1969, communicating first through an alphabet board and later through unique hand gestures.
|
129 |
-
</p>
|
130 |
-
<p class="text-gray-600 mb-4">
|
131 |
-
Meher Baba's teachings emphasize love, compassion, and the unity of all life. He taught that the purpose of life is to realize one's true nature as divine and that all paths ultimately lead to God.
|
132 |
-
</p>
|
133 |
-
<p class="text-gray-600 mb-6">
|
134 |
-
His simple yet profound message "Don't worry, be happy" has touched millions of hearts worldwide. Baba worked tirelessly for the spiritual upliftment of humanity while maintaining complete silence for 44 years.
|
135 |
-
</p>
|
136 |
-
<div class="flex space-x-4">
|
137 |
-
<a href="#teachings" class="bg-amber-800 hover:bg-amber-700 text-white px-6 py-2 rounded-full transition duration-300 inline-block">
|
138 |
-
His Teachings
|
139 |
-
</a>
|
140 |
-
<a href="#timeline" class="border border-amber-800 text-amber-800 hover:bg-amber-50 px-6 py-2 rounded-full transition duration-300 inline-block">
|
141 |
-
His Life
|
142 |
-
</a>
|
143 |
-
</div>
|
144 |
-
</div>
|
145 |
-
</div>
|
146 |
-
</div>
|
147 |
-
</section>
|
148 |
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
<!-- Teachings Section -->
|
165 |
-
<section id="teachings" class="py-20 bg-white">
|
166 |
-
<div class="container mx-auto px-6">
|
167 |
-
<div class="text-center mb-16">
|
168 |
-
<h2 class="title-font text-3xl md:text-4xl text-gray-800 mb-4">Core Teachings</h2>
|
169 |
-
<div class="w-20 h-1 bg-amber-800 mx-auto"></div>
|
170 |
-
</div>
|
171 |
-
|
172 |
-
<div class="grid md:grid-cols-3 gap-8">
|
173 |
-
<div class="bg-amber-50 p-8 rounded-lg shadow-md hover:shadow-lg transition duration-300">
|
174 |
-
<div class="text-amber-800 mb-4">
|
175 |
-
<i class="fas fa-heart text-4xl"></i>
|
176 |
-
</div>
|
177 |
-
<h3 class="title-font text-xl text-gray-800 mb-3">Love and Compassion</h3>
|
178 |
-
<p class="text-gray-600">
|
179 |
-
Meher Baba emphasized that love is the fundamental force in the universe. True love is selfless and unconditional, extending to all beings without distinction.
|
180 |
-
</p>
|
181 |
-
</div>
|
182 |
-
|
183 |
-
<div class="bg-amber-50 p-8 rounded-lg shadow-md hover:shadow-lg transition duration-300">
|
184 |
-
<div class="text-amber-800 mb-4">
|
185 |
-
<i class="fas fa-universal-access text-4xl"></i>
|
186 |
-
</div>
|
187 |
-
<h3 class="title-font text-xl text-gray-800 mb-3">The Path of Awakening</h3>
|
188 |
-
<p class="text-gray-600">
|
189 |
-
Baba taught that all spiritual paths ultimately lead to the same goal. The journey involves shedding the ego and realizing one's true divine nature.
|
190 |
-
</p>
|
191 |
-
</div>
|
192 |
-
|
193 |
-
<div class="bg-amber-50 p-8 rounded-lg shadow-md hover:shadow-lg transition duration-300">
|
194 |
-
<div class="text-amber-800 mb-4">
|
195 |
-
<i class="fas fa-hand-holding-heart text-4xl"></i>
|
196 |
-
</div>
|
197 |
-
<h3 class="title-font text-xl text-gray-800 mb-3">Service to Others</h3>
|
198 |
-
<p class="text-gray-600">
|
199 |
-
Selfless service is a direct path to spiritual growth. Helping others without expectation purifies the heart and brings one closer to God.
|
200 |
-
</p>
|
201 |
-
</div>
|
202 |
-
</div>
|
203 |
-
|
204 |
-
<div class="mt-12 text-center">
|
205 |
-
<a href="#" class="border border-amber-800 text-amber-800 hover:bg-amber-800 hover:text-white px-6 py-3 rounded-full transition duration-300 inline-block">
|
206 |
-
Explore More Teachings
|
207 |
-
</a>
|
208 |
-
</div>
|
209 |
-
</div>
|
210 |
-
</section>
|
211 |
-
|
212 |
-
<!-- Timeline Section -->
|
213 |
-
<section id="timeline" class="py-20 bg-amber-50">
|
214 |
-
<div class="container mx-auto px-6">
|
215 |
-
<div class="text-center mb-16">
|
216 |
-
<h2 class="title-font text-3xl md:text-4xl text-gray-800 mb-4">Life Timeline</h2>
|
217 |
-
<div class="w-20 h-1 bg-amber-800 mx-auto"></div>
|
218 |
-
</div>
|
219 |
-
|
220 |
-
<div class="relative max-w-3xl mx-auto">
|
221 |
-
<div class="timeline space-y-8 pl-12">
|
222 |
-
<!-- Timeline Item -->
|
223 |
-
<div class="timeline-item relative pl-6">
|
224 |
-
<div class="bg-white p-6 rounded-lg shadow-md">
|
225 |
-
<h3 class="title-font text-xl text-gray-800 mb-2">Birth</h3>
|
226 |
-
<div class="text-amber-800 mb-2">February 25, 1894</div>
|
227 |
-
<p class="text-gray-600">
|
228 |
-
Born as Merwan Sheriar Irani in Poona, India, to Persian Zoroastrian parents.
|
229 |
-
</p>
|
230 |
</div>
|
231 |
</div>
|
232 |
|
233 |
-
|
234 |
-
|
235 |
-
<div class="
|
236 |
-
<
|
237 |
-
|
238 |
-
|
239 |
-
At age 19, Merwan had a series of profound spiritual experiences after meeting Hazrat Babajan, one of the five Perfect Masters of the age.
|
240 |
-
</p>
|
241 |
</div>
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
<p class="text-gray-600">
|
250 |
-
Merwan declared himself to be the Avatar (God in human form) and took the name Meher Baba, meaning "Compassionate Father."
|
251 |
-
</p>
|
252 |
</div>
|
253 |
</div>
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
<
|
261 |
-
|
262 |
-
</p>
|
263 |
</div>
|
264 |
</div>
|
265 |
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
<div class="
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
<h2 class="title-font text-3xl md:text-4xl text-gray-800 mb-4">Connect With Us</h2>
|
286 |
-
<div class="w-20 h-1 bg-amber-800 mx-auto"></div>
|
287 |
-
</div>
|
288 |
-
|
289 |
-
<div class="max-w-4xl mx-auto">
|
290 |
-
<div class="bg-amber-50 rounded-lg shadow-md overflow-hidden">
|
291 |
-
<div class="md:flex">
|
292 |
-
<div class="md:w-1/2 p-8 md:p-12">
|
293 |
-
<h3 class="title-font text-2xl text-gray-800 mb-6">Meher Baba Centers</h3>
|
294 |
-
<p class="text-gray-600 mb-6">
|
295 |
-
There are Meher Baba centers and groups around the world where you can learn more about his teachings and connect with fellow followers.
|
296 |
-
</p>
|
297 |
-
<div class="space-y-4">
|
298 |
-
<div class="flex items-start">
|
299 |
-
<i class="fas fa-map-marker-alt text-amber-800 mt-1 mr-3"></i>
|
300 |
-
<div>
|
301 |
-
<h4 class="font-semibold text-gray-800">Meherabad, India</h4>
|
302 |
-
<p class="text-gray-600">The main pilgrimage center housing Baba's tomb</p>
|
303 |
</div>
|
304 |
</div>
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
310 |
</div>
|
311 |
</div>
|
312 |
</div>
|
313 |
</div>
|
314 |
-
|
315 |
-
|
316 |
-
<
|
317 |
-
|
318 |
-
|
|
|
|
|
319 |
</div>
|
320 |
-
<div class="
|
321 |
-
<
|
|
|
322 |
</div>
|
323 |
-
<div class="
|
324 |
-
<
|
|
|
325 |
</div>
|
326 |
-
|
327 |
-
Send Message
|
328 |
-
</button>
|
329 |
-
</form>
|
330 |
</div>
|
331 |
</div>
|
332 |
</div>
|
333 |
</div>
|
334 |
</div>
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
349 |
</div>
|
350 |
-
<div
|
351 |
-
<
|
352 |
-
|
353 |
-
<
|
354 |
-
<li><a href="#home" class="text-gray-400 hover:text-amber-300 transition duration-300">Home</a></li>
|
355 |
-
<li><a href="#about" class="text-gray-400 hover:text-amber-300 transition duration-300">About</a></li>
|
356 |
-
<li><a href="#teachings" class="text-gray-400 hover:text-amber-300 transition duration-300">Teachings</a></li>
|
357 |
-
<li><a href="#timeline" class="text-gray-400 hover:text-amber-300 transition duration-300">Timeline</a></li>
|
358 |
-
</ul>
|
359 |
-
</div>
|
360 |
-
<div>
|
361 |
-
<h4 class="title-font text-lg mb-4">Resources</h4>
|
362 |
-
<ul class="space-y-2">
|
363 |
-
<li><a href="#" class="text-gray-400 hover:text-amber-300 transition duration-300">Books</a></li>
|
364 |
-
<li><a href="#" class="text-gray-400 hover:text-amber-300 transition duration-300">Quotes</a></li>
|
365 |
-
<li><a href="#" class="text-gray-400 hover:text-amber-300 transition duration-300">Discourses</a></li>
|
366 |
-
<li><a href="#" class="text-gray-400 hover:text-amber-300 transition duration-300">Messages</a></li>
|
367 |
-
</ul>
|
368 |
-
</div>
|
369 |
-
<div>
|
370 |
-
<h4 class="title-font text-lg mb-4">Connect</h4>
|
371 |
-
<div class="flex space-x-4 mb-4">
|
372 |
-
<a href="#" class="text-gray-400 hover:text-amber-300 transition duration-300">
|
373 |
-
<i class="fab fa-facebook-f text-xl"></i>
|
374 |
-
</a>
|
375 |
-
<a href="#" class="text-gray-400 hover:text-amber-300 transition duration-300">
|
376 |
-
<i class="fab fa-twitter text-xl"></i>
|
377 |
-
</a>
|
378 |
-
<a href="#" class="text-gray-400 hover:text-amber-300 transition duration-300">
|
379 |
-
<i class="fab fa-instagram text-xl"></i>
|
380 |
-
</a>
|
381 |
-
<a href="#" class="text-gray-400 hover:text-amber-300 transition duration-300">
|
382 |
-
<i class="fab fa-youtube text-xl"></i>
|
383 |
-
</a>
|
384 |
-
</div>
|
385 |
-
<p class="text-gray-400">
|
386 |
-
<i class="fas fa-envelope mr-2"></i> [email protected]
|
387 |
-
</p>
|
388 |
</div>
|
389 |
</div>
|
390 |
</div>
|
391 |
-
<div class="border-t border-gray-700 mt-8 pt-8 text-center text-gray-400">
|
392 |
-
<p>© 2023 Avatar Meher Baba Trust. All rights reserved.</p>
|
393 |
-
</div>
|
394 |
</div>
|
395 |
-
</
|
396 |
-
|
397 |
-
<!-- Back to Top Button -->
|
398 |
-
<button id="backToTop" class="fixed bottom-6 right-6 bg-amber-800 text-white w-12 h-12 rounded-full shadow-lg flex items-center justify-center transition duration-300 opacity-0 invisible">
|
399 |
-
<i class="fas fa-arrow-up"></i>
|
400 |
-
</button>
|
401 |
|
402 |
<script>
|
403 |
-
//
|
404 |
-
const
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
405 |
|
406 |
-
|
407 |
-
|
408 |
-
backToTopButton.classList.remove('opacity-0', 'invisible');
|
409 |
-
backToTopButton.classList.add('opacity-100', 'visible');
|
410 |
-
} else {
|
411 |
-
backToTopButton.classList.remove('opacity-100', 'visible');
|
412 |
-
backToTopButton.classList.add('opacity-0', 'invisible');
|
413 |
-
}
|
414 |
});
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
|
|
|
|
421 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
422 |
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
427 |
|
428 |
-
|
429 |
-
|
430 |
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
436 |
}
|
437 |
});
|
438 |
});
|
|
|
|
|
|
|
|
|
439 |
|
440 |
-
//
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
446 |
</script>
|
447 |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=vishnumeher/amb" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
|
448 |
</html>
|
|
|
3 |
<head>
|
4 |
<meta charset="UTF-8">
|
5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<title>Image Segmentation Demo</title>
|
7 |
<script src="https://cdn.tailwindcss.com"></script>
|
8 |
+
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
9 |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
10 |
<style>
|
11 |
+
.dropzone {
|
12 |
+
border: 2px dashed #9CA3AF;
|
13 |
+
border-radius: 0.5rem;
|
14 |
+
transition: all 0.3s ease;
|
|
|
|
|
15 |
}
|
16 |
+
.dropzone.active {
|
17 |
+
border-color: #3B82F6;
|
18 |
+
background-color: #EFF6FF;
|
19 |
}
|
20 |
+
.result-container {
|
21 |
+
transition: all 0.5s ease;
|
22 |
+
opacity: 0;
|
23 |
+
height: 0;
|
24 |
+
overflow: hidden;
|
|
|
25 |
}
|
26 |
+
.result-container.show {
|
27 |
+
opacity: 1;
|
28 |
+
height: auto;
|
|
|
29 |
}
|
30 |
+
.loading-spinner {
|
31 |
+
animation: spin 1s linear infinite;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
}
|
33 |
+
@keyframes spin {
|
34 |
+
0% { transform: rotate(0deg); }
|
35 |
+
100% { transform: rotate(360deg); }
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
}
|
37 |
+
.image-container {
|
38 |
+
position: relative;
|
39 |
+
width: 100%;
|
40 |
+
height: 300px;
|
41 |
}
|
42 |
+
.image-wrapper {
|
43 |
+
position: relative;
|
44 |
+
width: 100%;
|
45 |
+
height: 100%;
|
46 |
+
overflow: hidden;
|
|
|
|
|
|
|
47 |
}
|
48 |
+
.image-wrapper img {
|
49 |
+
object-fit: contain;
|
50 |
width: 100%;
|
51 |
+
height: 100%;
|
52 |
+
}
|
53 |
+
.slider-container {
|
54 |
+
position: absolute;
|
55 |
+
bottom: 10px;
|
56 |
+
left: 50%;
|
57 |
+
transform: translateX(-50%);
|
58 |
+
background: rgba(0,0,0,0.5);
|
59 |
+
padding: 5px 10px;
|
60 |
+
border-radius: 20px;
|
61 |
+
color: white;
|
62 |
+
display: flex;
|
63 |
+
align-items: center;
|
64 |
+
gap: 10px;
|
65 |
+
}
|
66 |
+
.slider {
|
67 |
+
width: 150px;
|
68 |
}
|
69 |
</style>
|
70 |
</head>
|
71 |
+
<body class="bg-gray-50 min-h-screen">
|
72 |
+
<div class="container mx-auto px-4 py-8">
|
73 |
+
<header class="mb-8 text-center">
|
74 |
+
<h1 class="text-3xl font-bold text-gray-800 mb-2">Image Segmentation Demo</h1>
|
75 |
+
<p class="text-gray-600">Upload an image to generate segmentation masks using our AI model</p>
|
76 |
+
</header>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
|
78 |
+
<div class="max-w-4xl mx-auto bg-white rounded-xl shadow-md overflow-hidden p-6 mb-8">
|
79 |
+
<div class="grid md:grid-cols-2 gap-8">
|
80 |
+
<!-- Upload Section -->
|
81 |
+
<div>
|
82 |
+
<div id="dropzone" class="dropzone p-8 text-center cursor-pointer">
|
83 |
+
<div class="flex flex-col items-center justify-center">
|
84 |
+
<i class="fas fa-cloud-upload-alt text-4xl text-blue-500 mb-4"></i>
|
85 |
+
<h3 class="text-lg font-medium text-gray-700 mb-2">Drag & Drop your image here</h3>
|
86 |
+
<p class="text-gray-500 text-sm mb-4">or</p>
|
87 |
+
<label for="file-upload" class="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition cursor-pointer">
|
88 |
+
Browse Files
|
89 |
+
</label>
|
90 |
+
<input id="file-upload" type="file" class="hidden" accept="image/*">
|
91 |
+
<p class="text-gray-400 text-xs mt-4">Supports: JPG, PNG, WEBP (Max 5MB)</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
</div>
|
93 |
</div>
|
94 |
|
95 |
+
<div id="preview-container" class="mt-4 hidden">
|
96 |
+
<h3 class="text-sm font-medium text-gray-700 mb-2">Selected Image</h3>
|
97 |
+
<div class="image-container">
|
98 |
+
<div class="image-wrapper bg-gray-100 rounded-lg">
|
99 |
+
<img id="preview-image" src="" alt="Preview" class="hidden">
|
100 |
+
</div>
|
|
|
|
|
101 |
</div>
|
102 |
+
<div class="flex justify-between mt-4">
|
103 |
+
<button id="process-btn" class="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition">
|
104 |
+
<i class="fas fa-magic mr-2"></i> Process Image
|
105 |
+
</button>
|
106 |
+
<button id="clear-btn" class="px-4 py-2 bg-gray-200 text-gray-700 rounded-md hover:bg-gray-300 transition">
|
107 |
+
<i class="fas fa-trash-alt mr-2"></i> Clear
|
108 |
+
</button>
|
|
|
|
|
|
|
109 |
</div>
|
110 |
</div>
|
111 |
+
</div>
|
112 |
+
|
113 |
+
<!-- Results Section -->
|
114 |
+
<div>
|
115 |
+
<div id="loading-indicator" class="hidden">
|
116 |
+
<div class="flex flex-col items-center justify-center h-full">
|
117 |
+
<div class="loading-spinner border-4 border-blue-500 border-t-transparent rounded-full w-12 h-12 mb-4"></div>
|
118 |
+
<p class="text-gray-600">Processing your image...</p>
|
119 |
+
<p class="text-gray-400 text-sm">This may take a few moments</p>
|
120 |
</div>
|
121 |
</div>
|
122 |
|
123 |
+
<div id="result-container" class="result-container">
|
124 |
+
<h3 class="text-lg font-medium text-gray-700 mb-4">Segmentation Results</h3>
|
125 |
+
|
126 |
+
<div class="mb-6">
|
127 |
+
<div class="flex items-center justify-between mb-2">
|
128 |
+
<h4 class="text-sm font-medium text-gray-700">Segmentation Mask</h4>
|
129 |
+
<div class="flex items-center">
|
130 |
+
<button id="download-mask" class="text-blue-500 hover:text-blue-700 text-sm">
|
131 |
+
<i class="fas fa-download mr-1"></i> Download
|
132 |
+
</button>
|
133 |
+
</div>
|
134 |
+
</div>
|
135 |
+
<div class="image-container">
|
136 |
+
<div class="image-wrapper bg-gray-100 rounded-lg relative">
|
137 |
+
<img id="mask-image" src="" alt="Segmentation Mask" class="hidden">
|
138 |
+
<div class="slider-container hidden" id="mask-slider">
|
139 |
+
<i class="fas fa-eye"></i>
|
140 |
+
<input type="range" min="0" max="100" value="50" class="slider" id="mask-opacity">
|
141 |
+
<span id="mask-value">50%</span>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
</div>
|
143 |
</div>
|
144 |
+
</div>
|
145 |
+
</div>
|
146 |
+
|
147 |
+
<div class="mb-6">
|
148 |
+
<div class="flex items-center justify-between mb-2">
|
149 |
+
<h4 class="text-sm font-medium text-gray-700">Overlay Comparison</h4>
|
150 |
+
<div class="flex items-center">
|
151 |
+
<button id="download-overlay" class="text-blue-500 hover:text-blue-700 text-sm">
|
152 |
+
<i class="fas fa-download mr-1"></i> Download
|
153 |
+
</button>
|
154 |
+
</div>
|
155 |
+
</div>
|
156 |
+
<div class="image-container">
|
157 |
+
<div class="image-wrapper bg-gray-100 rounded-lg relative">
|
158 |
+
<img id="overlay-image" src="" alt="Overlay" class="hidden">
|
159 |
+
<div class="slider-container">
|
160 |
+
<i class="fas fa-sliders-h"></i>
|
161 |
+
<input type="range" min="0" max="100" value="50" class="slider" id="overlay-opacity">
|
162 |
+
<span id="overlay-value">50%</span>
|
163 |
</div>
|
164 |
</div>
|
165 |
</div>
|
166 |
</div>
|
167 |
+
|
168 |
+
<div class="bg-gray-50 p-4 rounded-lg">
|
169 |
+
<h4 class="text-sm font-medium text-gray-700 mb-2">Segmentation Statistics</h4>
|
170 |
+
<div class="grid grid-cols-3 gap-4 text-center">
|
171 |
+
<div class="bg-white p-2 rounded shadow">
|
172 |
+
<p class="text-xs text-gray-500">Foreground Area</p>
|
173 |
+
<p id="foreground-area" class="font-bold">0 px²</p>
|
174 |
</div>
|
175 |
+
<div class="bg-white p-2 rounded shadow">
|
176 |
+
<p class="text-xs text-gray-500">Background Area</p>
|
177 |
+
<p id="background-area" class="font-bold">0 px²</p>
|
178 |
</div>
|
179 |
+
<div class="bg-white p-2 rounded shadow">
|
180 |
+
<p class="text-xs text-gray-500">Confidence</p>
|
181 |
+
<p id="confidence-score" class="font-bold">0%</p>
|
182 |
</div>
|
183 |
+
</div>
|
|
|
|
|
|
|
184 |
</div>
|
185 |
</div>
|
186 |
</div>
|
187 |
</div>
|
188 |
</div>
|
189 |
+
|
190 |
+
<div class="max-w-4xl mx-auto bg-white rounded-xl shadow-md overflow-hidden p-6">
|
191 |
+
<h2 class="text-xl font-bold text-gray-800 mb-4">About This Model</h2>
|
192 |
+
<div class="grid md:grid-cols-2 gap-6">
|
193 |
+
<div>
|
194 |
+
<h3 class="font-medium text-gray-700 mb-2">Model Details</h3>
|
195 |
+
<ul class="text-gray-600 space-y-2">
|
196 |
+
<li class="flex items-start">
|
197 |
+
<i class="fas fa-cog text-blue-500 mt-1 mr-2"></i>
|
198 |
+
<span>Architecture: Your Custom Segmentation Model</span>
|
199 |
+
</li>
|
200 |
+
<li class="flex items-start">
|
201 |
+
<i class="fas fa-weight-hanging text-blue-500 mt-1 mr-2"></i>
|
202 |
+
<span>Model File: .pth format</span>
|
203 |
+
</li>
|
204 |
+
<li class="flex items-start">
|
205 |
+
<i class="fas fa-tachometer-alt text-blue-500 mt-1 mr-2"></i>
|
206 |
+
<span>Inference Time: Varies by hardware</span>
|
207 |
+
</li>
|
208 |
+
<li class="flex items-start">
|
209 |
+
<i class="fas fa-chart-line text-blue-500 mt-1 mr-2"></i>
|
210 |
+
<span>Custom Trained Model</span>
|
211 |
+
</li>
|
212 |
+
</ul>
|
213 |
</div>
|
214 |
+
<div>
|
215 |
+
<h3 class="font-medium text-gray-700 mb-2">Performance Metrics</h3>
|
216 |
+
<div class="h-48">
|
217 |
+
<canvas id="metrics-chart"></canvas>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
218 |
</div>
|
219 |
</div>
|
220 |
</div>
|
|
|
|
|
|
|
221 |
</div>
|
222 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
223 |
|
224 |
<script>
|
225 |
+
// DOM Elements
|
226 |
+
const dropzone = document.getElementById('dropzone');
|
227 |
+
const fileUpload = document.getElementById('file-upload');
|
228 |
+
const previewContainer = document.getElementById('preview-container');
|
229 |
+
const previewImage = document.getElementById('preview-image');
|
230 |
+
const processBtn = document.getElementById('process-btn');
|
231 |
+
const clearBtn = document.getElementById('clear-btn');
|
232 |
+
const loadingIndicator = document.getElementById('loading-indicator');
|
233 |
+
const resultContainer = document.getElementById('result-container');
|
234 |
+
const maskImage = document.getElementById('mask-image');
|
235 |
+
const overlayImage = document.getElementById('overlay-image');
|
236 |
+
const maskSlider = document.getElementById('mask-slider');
|
237 |
+
const maskOpacity = document.getElementById('mask-opacity');
|
238 |
+
const maskValue = document.getElementById('mask-value');
|
239 |
+
const overlayOpacity = document.getElementById('overlay-opacity');
|
240 |
+
const overlayValue = document.getElementById('overlay-value');
|
241 |
+
const foregroundArea = document.getElementById('foreground-area');
|
242 |
+
const backgroundArea = document.getElementById('background-area');
|
243 |
+
const confidenceScore = document.getElementById('confidence-score');
|
244 |
+
const downloadMask = document.getElementById('download-mask');
|
245 |
+
const downloadOverlay = document.getElementById('download-overlay');
|
246 |
+
|
247 |
+
// Event Listeners
|
248 |
+
dropzone.addEventListener('click', () => fileUpload.click());
|
249 |
|
250 |
+
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
|
251 |
+
dropzone.addEventListener(eventName, preventDefaults, false);
|
|
|
|
|
|
|
|
|
|
|
|
|
252 |
});
|
253 |
+
|
254 |
+
function preventDefaults(e) {
|
255 |
+
e.preventDefault();
|
256 |
+
e.stopPropagation();
|
257 |
+
}
|
258 |
+
|
259 |
+
['dragenter', 'dragover'].forEach(eventName => {
|
260 |
+
dropzone.addEventListener(eventName, highlight, false);
|
261 |
});
|
262 |
+
|
263 |
+
['dragleave', 'drop'].forEach(eventName => {
|
264 |
+
dropzone.addEventListener(eventName, unhighlight, false);
|
265 |
+
});
|
266 |
+
|
267 |
+
function highlight() {
|
268 |
+
dropzone.classList.add('active');
|
269 |
+
}
|
270 |
+
|
271 |
+
function unhighlight() {
|
272 |
+
dropzone.classList.remove('active');
|
273 |
+
}
|
274 |
+
|
275 |
+
dropzone.addEventListener('drop', handleDrop, false);
|
276 |
+
fileUpload.addEventListener('change', handleFiles, false);
|
277 |
|
278 |
+
function handleDrop(e) {
|
279 |
+
const dt = e.dataTransfer;
|
280 |
+
const files = dt.files;
|
281 |
+
handleFiles({target: {files}});
|
282 |
+
}
|
283 |
+
|
284 |
+
function handleFiles(e) {
|
285 |
+
const file = e.target.files[0];
|
286 |
+
if (!file) return;
|
287 |
+
|
288 |
+
if (!file.type.match('image.*')) {
|
289 |
+
alert('Please select an image file (JPG, PNG, WEBP)');
|
290 |
+
return;
|
291 |
+
}
|
292 |
+
|
293 |
+
if (file.size > 5 * 1024 * 1024) {
|
294 |
+
alert('File size exceeds 5MB limit');
|
295 |
+
return;
|
296 |
+
}
|
297 |
+
|
298 |
+
const reader = new FileReader();
|
299 |
+
reader.onload = function(e) {
|
300 |
+
previewImage.src = e.target.result;
|
301 |
+
previewImage.classList.remove('hidden');
|
302 |
+
previewContainer.classList.remove('hidden');
|
303 |
+
resultContainer.classList.remove('show');
|
304 |
+
};
|
305 |
+
reader.readAsDataURL(file);
|
306 |
+
}
|
307 |
+
|
308 |
+
processBtn.addEventListener('click', processImage);
|
309 |
+
clearBtn.addEventListener('click', clearAll);
|
310 |
+
|
311 |
+
function clearAll() {
|
312 |
+
fileUpload.value = '';
|
313 |
+
previewImage.src = '';
|
314 |
+
previewImage.classList.add('hidden');
|
315 |
+
previewContainer.classList.add('hidden');
|
316 |
+
maskImage.classList.add('hidden');
|
317 |
+
overlayImage.classList.add('hidden');
|
318 |
+
resultContainer.classList.remove('show');
|
319 |
+
maskSlider.classList.add('hidden');
|
320 |
+
}
|
321 |
+
|
322 |
+
maskOpacity.addEventListener('input', () => {
|
323 |
+
const value = maskOpacity.value;
|
324 |
+
maskValue.textContent = `${value}%`;
|
325 |
+
maskImage.style.opacity = value / 100;
|
326 |
+
});
|
327 |
+
|
328 |
+
overlayOpacity.addEventListener('input', () => {
|
329 |
+
const value = overlayOpacity.value;
|
330 |
+
overlayValue.textContent = `${value}%`;
|
331 |
+
overlayImage.style.opacity = value / 100;
|
332 |
+
});
|
333 |
+
|
334 |
+
async function processImage() {
|
335 |
+
if (!previewImage.src) {
|
336 |
+
alert('Please select an image first');
|
337 |
+
return;
|
338 |
+
}
|
339 |
+
|
340 |
+
// Show loading indicator
|
341 |
+
loadingIndicator.classList.remove('hidden');
|
342 |
+
resultContainer.classList.remove('show');
|
343 |
+
|
344 |
+
try {
|
345 |
+
// Convert the image to a blob for upload
|
346 |
+
const blob = await fetch(previewImage.src).then(r => r.blob());
|
347 |
+
|
348 |
+
// Create FormData to send the image
|
349 |
+
const formData = new FormData();
|
350 |
+
formData.append('image', blob, 'uploaded_image.jpg');
|
351 |
+
|
352 |
+
// 1. FIRST APPROACH: Using a Flask backend
|
353 |
+
// -----------------------------------------
|
354 |
+
// You would need to create a Flask server that loads your model
|
355 |
+
// and processes the image. The endpoint would be something like:
|
356 |
+
// const response = await fetch('http://localhost:5000/process', {
|
357 |
+
// method: 'POST',
|
358 |
+
// body: formData
|
359 |
+
// });
|
360 |
+
|
361 |
+
// 2. SECOND APPROACH: Using Pyodide to run Python in browser
|
362 |
+
// ---------------------------------------------------------
|
363 |
+
// This approach runs your model directly in the browser using WebAssembly
|
364 |
+
// You would need to:
|
365 |
+
// 1. Load Pyodide
|
366 |
+
// 2. Install required Python packages
|
367 |
+
// 3. Load your model
|
368 |
+
// 4. Process the image
|
369 |
+
|
370 |
+
// Here's a basic structure for the Pyodide approach:
|
371 |
+
/*
|
372 |
+
// Load Pyodide
|
373 |
+
let pyodide = await loadPyodide();
|
374 |
+
|
375 |
+
// Install required packages
|
376 |
+
await pyodide.loadPackage(["numpy", "Pillow", "torch"]);
|
377 |
+
|
378 |
+
// Load your custom segmentation code
|
379 |
+
// You would need to convert your model to a format that can be loaded in Pyodide
|
380 |
+
// and include it in your project files
|
381 |
+
await pyodide.runPythonAsync(`
|
382 |
+
import your_segmentation_module
|
383 |
+
from your_segmentation_module import YourSegmentationModel
|
384 |
+
|
385 |
+
# Load your model (you would need to provide the path to your model file)
|
386 |
+
model = YourSegmentationModel()
|
387 |
+
model.load_state_dict(torch.load('path/to/your/model.pth'))
|
388 |
+
model.eval()
|
389 |
+
|
390 |
+
# Process image function
|
391 |
+
def process_image(image_data):
|
392 |
+
# Your image processing and segmentation logic here
|
393 |
+
# Return the mask and statistics
|
394 |
+
return mask, foreground_area, background_area, confidence
|
395 |
+
`);
|
396 |
+
|
397 |
+
// Process the image
|
398 |
+
const response = await pyodide.runPythonAsync(`
|
399 |
+
image_data = get_image_data() # You would need to implement this
|
400 |
+
mask, fg_area, bg_area, conf = process_image(image_data)
|
401 |
+
# Convert results to format that can be returned to JS
|
402 |
+
# ...
|
403 |
+
`);
|
404 |
+
*/
|
405 |
+
|
406 |
+
// For this demo, we'll simulate a response
|
407 |
+
// In a real implementation, you would use one of the approaches above
|
408 |
+
const simulatedResponse = {
|
409 |
+
mask: "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z/C/HgAGgwJ/lK3Q6wAAAABJRU5ErkJggg==", // Base64 encoded placeholder
|
410 |
+
foreground_area: 12345,
|
411 |
+
background_area: 45678,
|
412 |
+
confidence: 0.92
|
413 |
+
};
|
414 |
+
|
415 |
+
// Display the results
|
416 |
+
maskImage.src = `data:image/png;base64,${simulatedResponse.mask}`;
|
417 |
+
maskImage.classList.remove('hidden');
|
418 |
+
maskSlider.classList.remove('hidden');
|
419 |
+
|
420 |
+
overlayImage.src = previewImage.src;
|
421 |
+
overlayImage.classList.remove('hidden');
|
422 |
+
|
423 |
+
// Update statistics
|
424 |
+
foregroundArea.textContent = `${simulatedResponse.foreground_area} px²`;
|
425 |
+
backgroundArea.textContent = `${simulatedResponse.background_area} px²`;
|
426 |
+
confidenceScore.textContent = `${Math.round(simulatedResponse.confidence * 100)}%`;
|
427 |
+
|
428 |
+
// Setup download buttons
|
429 |
+
downloadMask.onclick = () => downloadImage(maskImage.src, 'segmentation-mask.png');
|
430 |
+
downloadOverlay.onclick = () => downloadImage(overlayImage.src, 'segmentation-overlay.png');
|
431 |
|
432 |
+
// Show results
|
433 |
+
resultContainer.classList.add('show');
|
434 |
|
435 |
+
} catch (error) {
|
436 |
+
console.error('Error:', error);
|
437 |
+
alert('Error processing image. Please try again.');
|
438 |
+
} finally {
|
439 |
+
loadingIndicator.classList.add('hidden');
|
440 |
+
}
|
441 |
+
}
|
442 |
+
|
443 |
+
function downloadImage(url, filename) {
|
444 |
+
const a = document.createElement('a');
|
445 |
+
a.href = url;
|
446 |
+
a.download = filename;
|
447 |
+
document.body.appendChild(a);
|
448 |
+
a.click();
|
449 |
+
document.body.removeChild(a);
|
450 |
+
}
|
451 |
+
|
452 |
+
// Initialize chart
|
453 |
+
document.addEventListener('DOMContentLoaded', function() {
|
454 |
+
const ctx = document.getElementById('metrics-chart').getContext('2d');
|
455 |
+
const chart = new Chart(ctx, {
|
456 |
+
type: 'bar',
|
457 |
+
data: {
|
458 |
+
labels: ['IoU', 'Precision', 'Recall', 'Dice'],
|
459 |
+
datasets: [{
|
460 |
+
label: 'Model Metrics',
|
461 |
+
data: [0.85, 0.88, 0.82, 0.87], // Replace with your model's actual metrics
|
462 |
+
backgroundColor: [
|
463 |
+
'rgba(59, 130, 246, 0.7)',
|
464 |
+
'rgba(16, 185, 129, 0.7)',
|
465 |
+
'rgba(245, 158, 11, 0.7)',
|
466 |
+
'rgba(139, 92, 246, 0.7)'
|
467 |
+
],
|
468 |
+
borderColor: [
|
469 |
+
'rgba(59, 130, 246, 1)',
|
470 |
+
'rgba(16, 185, 129, 1)',
|
471 |
+
'rgba(245, 158, 11, 1)',
|
472 |
+
'rgba(139, 92, 246, 1)'
|
473 |
+
],
|
474 |
+
borderWidth: 1
|
475 |
+
}]
|
476 |
+
},
|
477 |
+
options: {
|
478 |
+
responsive: true,
|
479 |
+
maintainAspectRatio: false,
|
480 |
+
scales: {
|
481 |
+
y: {
|
482 |
+
beginAtZero: true,
|
483 |
+
max: 1.0
|
484 |
+
}
|
485 |
+
},
|
486 |
+
plugins: {
|
487 |
+
legend: {
|
488 |
+
display: false
|
489 |
+
}
|
490 |
+
}
|
491 |
}
|
492 |
});
|
493 |
});
|
494 |
+
|
495 |
+
// MODEL INTEGRATION GUIDE
|
496 |
+
// -----------------------
|
497 |
+
// To integrate your custom segmentation model, you have two main options:
|
498 |
|
499 |
+
// 1. Flask Backend Approach (Recommended for production)
|
500 |
+
// ------------------------------------------------------
|
501 |
+
// - Create a Flask server that loads your model
|
502 |
+
// - The server should have an endpoint (e.g., /process) that:
|
503 |
+
// - Receives the image file
|
504 |
+
// - Processes it using your model
|
505 |
+
// - Returns the segmentation mask and statistics
|
506 |
+
// - In this HTML file, modify the processImage() function to call your Flask endpoint
|
507 |
+
|
508 |
+
// Example Flask server structure:
|
509 |
+
/*
|
510 |
+
from flask import Flask, request, jsonify
|
511 |
+
import your_segmentation_module
|
512 |
+
import base64
|
513 |
+
import io
|
514 |
+
from PIL import Image
|
515 |
+
|
516 |
+
app = Flask(__name__)
|
517 |
+
|
518 |
+
# Load your model (replace with your actual model path)
|
519 |
+
model = your_segmentation_module.YourSegmentationModel()
|
520 |
+
model.load_state_dict(torch.load('path/to/your/model.pth'))
|
521 |
+
model.eval()
|
522 |
+
|
523 |
+
@app.route('/process', methods=['POST'])
|
524 |
+
def process_image():
|
525 |
+
if 'image' not in request.files:
|
526 |
+
return jsonify({'error': 'No image provided'}), 400
|
527 |
+
|
528 |
+
image_file = request.files['image']
|
529 |
+
image = Image.open(image_file.stream)
|
530 |
+
|
531 |
+
# Process image with your model
|
532 |
+
mask, fg_area, bg_area, confidence = model.process(image)
|
533 |
+
|
534 |
+
# Convert mask to base64
|
535 |
+
buffered = io.BytesIO()
|
536 |
+
mask.save(buffered, format="PNG")
|
537 |
+
mask_base64 = base64.b64encode(buffered.getvalue()).decode('utf-8')
|
538 |
+
|
539 |
+
return jsonify({
|
540 |
+
'mask': mask_base64,
|
541 |
+
'foreground_area': fg_area,
|
542 |
+
'background_area': bg_area,
|
543 |
+
'confidence': confidence
|
544 |
+
})
|
545 |
+
|
546 |
+
if __name__ == '__main__':
|
547 |
+
app.run(debug=True)
|
548 |
+
*/
|
549 |
+
|
550 |
+
// 2. Pyodide Approach (For browser-only implementation)
|
551 |
+
// ----------------------------------------------------
|
552 |
+
// - This runs Python directly in the browser using WebAssembly
|
553 |
+
// - Limitations: Larger initial load time, limited package support
|
554 |
+
// - Steps:
|
555 |
+
// a. Include Pyodide in your project
|
556 |
+
// b. Convert your model to a format that can be loaded in Pyodide
|
557 |
+
// c. Modify the processImage() function to use Pyodide
|
558 |
+
|
559 |
+
// Model Path Configuration:
|
560 |
+
// -------------------------
|
561 |
+
// Wherever you see 'path/to/your/model.pth' in the code comments,
|
562 |
+
// replace it with the actual path to your trained model file.
|
563 |
+
// This could be:
|
564 |
+
// - A relative path from your Flask server's root directory
|
565 |
+
// - An absolute path on your server
|
566 |
+
// - A URL if hosting the model file online
|
567 |
</script>
|
568 |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=vishnumeher/amb" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
|
569 |
</html>
|