awacke1 commited on
Commit
adeee4c
·
verified ·
1 Parent(s): 27fb02e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +175 -100
app.py CHANGED
@@ -7,8 +7,8 @@ import time
7
  from dataclasses import dataclass
8
  import zipfile
9
  import logging
10
- import av
11
- from streamlit_webrtc import webrtc_streamer, VideoProcessorBase, WebRtcMode
12
 
13
  # Logging setup
14
  logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
@@ -133,7 +133,6 @@ class DiffusionBuilder:
133
  def fine_tune(self, images, texts):
134
  try:
135
  import torch
136
- from PIL import Image
137
  import numpy as np
138
  logger.info("Starting diffusion fine-tuning")
139
  optimizer = torch.optim.AdamW(self.pipeline.unet.parameters(), lr=1e-5)
@@ -189,32 +188,162 @@ def zip_files(files, zip_name):
189
  zipf.write(file, os.path.basename(file))
190
  return zip_name
191
 
192
- # Video Processor for WebRTC
193
- class CameraProcessor(VideoProcessorBase):
194
- def __init__(self):
195
- self.frame = None
196
-
197
- def recv(self, frame):
198
- from PIL import Image
199
- img = frame.to_image()
200
- self.frame = img
201
- return av.VideoFrame.from_image(img)
202
-
203
- def capture_frame(self):
204
- from PIL import Image
205
- return self.frame
206
-
207
- def capture_video(self):
208
- from PIL import Image
209
- frames = []
210
- start_time = time.time()
211
- while time.time() - start_time < 10 and self.frame:
212
- frames.append(np.array(self.frame))
213
- time.sleep(0.033) # ~30 FPS
214
- return frames
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
215
 
216
  # Main App
217
- st.title("SFT Tiny Titans 🚀 (Dual Cam Action!)")
218
 
219
  # Sidebar Galleries
220
  st.sidebar.header("Captured Media 🎨")
@@ -227,7 +356,6 @@ def update_gallery():
227
  for idx, file in enumerate(media_files[:4]):
228
  with cols[idx % 2]:
229
  if file.endswith(".png"):
230
- from PIL import Image
231
  st.image(Image.open(file), caption=file.split('/')[-1], use_container_width=True)
232
  elif file.endswith(".mp4"):
233
  st.video(file)
@@ -273,77 +401,26 @@ with tab1:
273
 
274
  with tab2:
275
  st.header("Camera Snap 📷 (Dual Live Feed!)")
 
 
276
  cols = st.columns(2)
277
- processors = {}
278
  for i in range(2):
279
  with cols[i]:
280
- st.subheader(f"Camera {i}")
281
- key = f"camera_{i}"
282
- processors[key] = webrtc_streamer(
283
- key=key,
284
- mode=WebRtcMode.SENDRECV,
285
- video_processor_factory=CameraProcessor,
286
- frontend_rtc_configuration={"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]}
287
- )
288
- if st.button(f"Capture Frame 📸 Cam {i}", key=f"snap_{i}"):
289
- logger.info(f"Capturing frame from Camera {i}")
290
- try:
291
- if processors[key].video_processor and processors[key].video_processor.frame:
292
- snapshot = processors[key].video_processor.capture_frame()
293
- filename = generate_filename(i)
294
- snapshot.save(filename)
295
- st.image(snapshot, caption=filename, use_container_width=True)
296
- logger.info(f"Saved snapshot: {filename}")
297
- if 'captured_images' not in st.session_state:
298
- st.session_state['captured_images'] = []
299
- st.session_state['captured_images'].append(filename)
300
- update_gallery()
301
- else:
302
- st.error("No frame available!")
303
- logger.error(f"No frame captured from Camera {i}")
304
- except Exception as e:
305
- st.error(f"Frame capture failed: {str(e)}")
306
- logger.error(f"Error capturing frame: {str(e)}")
307
- if st.button(f"Capture Video 🎥 Cam {i}", key=f"rec_{i}"):
308
- logger.info(f"Capturing 10s video from Camera {i}")
309
- try:
310
- if processors[key].video_processor:
311
- frames = processors[key].video_processor.capture_video()
312
- if frames:
313
- mp4_filename = generate_filename(i, "mp4")
314
- with av.open(mp4_filename, "w") as container:
315
- stream = container.add_stream("h264", rate=30)
316
- stream.width = frames[0].shape[1]
317
- stream.height = frames[0].shape[0]
318
- for frame in frames:
319
- av_frame = av.VideoFrame.from_ndarray(frame, format="rgb24")
320
- for packet in stream.encode(av_frame):
321
- container.mux(packet)
322
- for packet in stream.encode():
323
- container.mux(packet)
324
- st.video(mp4_filename)
325
- logger.info(f"Saved video: {mp4_filename}")
326
- sliced_images = []
327
- step = max(1, len(frames) // 10)
328
- for j in range(0, len(frames), step):
329
- if len(sliced_images) < 10:
330
- img = Image.fromarray(frames[j])
331
- img_filename = generate_filename(f"{i}_{len(sliced_images)}")
332
- img.save(img_filename)
333
- sliced_images.append(img_filename)
334
- st.image(img, caption=img_filename, use_container_width=True)
335
- st.session_state['captured_images'] = st.session_state.get('captured_images', []) + sliced_images
336
- logger.info(f"Sliced video into {len(sliced_images)} images")
337
- update_gallery()
338
- else:
339
- st.error("No frames recorded!")
340
- logger.error("No frames captured during video recording")
341
- else:
342
- st.error("Camera processor not initialized!")
343
- logger.error(f"Processor not ready for Camera {i}")
344
- except Exception as e:
345
- st.error(f"Video capture failed: {str(e)}")
346
- logger.error(f"Error capturing video: {str(e)}")
347
 
348
  with tab3:
349
  st.header("Fine-Tune Titans 🔧 (Tune Fast!)")
@@ -370,14 +447,13 @@ with tab3:
370
  if st.button("Tune CV 🔄"):
371
  logger.info("Initiating CV fine-tune")
372
  try:
373
- from PIL import Image
374
  images = [Image.open(img) for img in captured_images]
375
  st.session_state['builder'].fine_tune(images, texts)
376
  st.success("CV polished! 🎉")
377
  except Exception as e:
378
  st.error(f"CV fine-tune failed: {str(e)}")
379
  else:
380
- st.warning("Capture at least 2 images first! ⚠️")
381
 
382
  with tab4:
383
  st.header("Test Titans 🧪 (Image Agent Demo!)")
@@ -401,7 +477,6 @@ with tab4:
401
  if st.button("Run CV Demo ▶️"):
402
  logger.info("Running CV image set demo")
403
  try:
404
- from PIL import Image
405
  images = [Image.open(img) for img in captured_images[:10]]
406
  prompts = ["Neon " + os.path.basename(img).split('.')[0] for img in captured_images[:10]]
407
  generated_images = []
@@ -425,7 +500,7 @@ with tab4:
425
  st.error(f"CV demo failed: {str(e)}")
426
  logger.error(f"Error in CV demo: {str(e)}")
427
  else:
428
- st.warning("Capture at least 2 images first! ⚠️")
429
 
430
  # Display Logs
431
  st.sidebar.subheader("Action Logs 📜")
 
7
  from dataclasses import dataclass
8
  import zipfile
9
  import logging
10
+ from streamlit.components.v1 import html
11
+ from PIL import Image
12
 
13
  # Logging setup
14
  logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
 
133
  def fine_tune(self, images, texts):
134
  try:
135
  import torch
 
136
  import numpy as np
137
  logger.info("Starting diffusion fine-tuning")
138
  optimizer = torch.optim.AdamW(self.pipeline.unet.parameters(), lr=1e-5)
 
188
  zipf.write(file, os.path.basename(file))
189
  return zip_name
190
 
191
+ # JavaScript/HTML Components
192
+ camera_selector_html = """
193
+ <div>
194
+ <h3>Camera & Audio Source Selector</h3>
195
+ <select id="videoSource"></select>
196
+ <select id="audioSource"></select>
197
+ <button onclick="startStream()">Start Stream</button>
198
+ <video id="video" autoplay playsinline style="width: 100%;"></video>
199
+ </div>
200
+ <script>
201
+ const videoSource = document.getElementById('videoSource');
202
+ const audioSource = document.getElementById('audioSource');
203
+ const video = document.getElementById('video');
204
+ let stream;
205
+
206
+ navigator.mediaDevices.enumerateDevices().then(devices => {
207
+ devices.forEach(device => {
208
+ const option = document.createElement('option');
209
+ option.value = device.deviceId;
210
+ option.text = device.label || `${device.kind} ${device.deviceId}`;
211
+ if (device.kind === 'videoinput') {
212
+ videoSource.appendChild(option);
213
+ } else if (device.kind === 'audioinput') {
214
+ audioSource.appendChild(option);
215
+ }
216
+ });
217
+ }).catch(err => console.error('Error enumerating devices:', err));
218
+
219
+ function startStream() {
220
+ if (stream) {
221
+ stream.getTracks().forEach(track => track.stop());
222
+ }
223
+ const constraints = {
224
+ video: { deviceId: videoSource.value ? { exact: videoSource.value } : undefined },
225
+ audio: { deviceId: audioSource.value ? { exact: audioSource.value } : undefined }
226
+ };
227
+ navigator.mediaDevices.getUserMedia(constraints)
228
+ .then(mediaStream => {
229
+ stream = mediaStream;
230
+ video.srcObject = stream;
231
+ console.log('Stream started');
232
+ })
233
+ .catch(err => console.error('Error starting stream:', err));
234
+ }
235
+ </script>
236
+ """
237
+
238
+ image_capture_html = """
239
+ <div>
240
+ <h3>Image Capture - Camera {id}</h3>
241
+ <video id="video{id}" autoplay playsinline style="width: 100%;"></video>
242
+ <button onclick="captureFrame{id}()">Capture Frame 📸</button>
243
+ <canvas id="canvas{id}" style="display: none;"></canvas>
244
+ </div>
245
+ <script>
246
+ const video{id} = document.getElementById('video{id}');
247
+ const canvas{id} = document.getElementById('canvas{id}');
248
+ let stream{id};
249
+
250
+ navigator.mediaDevices.getUserMedia({ video: true })
251
+ .then(mediaStream => {
252
+ stream{id} = mediaStream;
253
+ video{id}.srcObject = stream{id};
254
+ console.log('Camera {id} stream started');
255
+ })
256
+ .catch(err => console.error('Error starting Camera {id}:', err));
257
+
258
+ function captureFrame{id}() {
259
+ canvas{id}.width = video{id}.videoWidth;
260
+ canvas{id}.height = video{id}.videoHeight;
261
+ const ctx = canvas{id}.getContext('2d');
262
+ ctx.drawImage(video{id}, 0, 0, canvas{id}.width, canvas{id}.height);
263
+ const dataUrl = canvas{id}.toDataURL('image/png');
264
+ const filename = `{id}${new Date().toISOString().replace(/[^0-9]/g, '')}.png`;
265
+ const link = document.createElement('a');
266
+ link.href = dataUrl;
267
+ link.download = filename;
268
+ link.click();
269
+ console.log('Captured frame:', filename);
270
+ }
271
+ </script>
272
+ """
273
+
274
+ video_capture_html = """
275
+ <div>
276
+ <h3>Video Capture - Camera {id}</h3>
277
+ <video id="video{id}" autoplay playsinline style="width: 100%;"></video>
278
+ <button onclick="captureVideo{id}()">Capture Video 🎥</button>
279
+ <canvas id="canvas{id}" style="display: none;"></canvas>
280
+ </div>
281
+ <script>
282
+ const video{id} = document.getElementById('video{id}');
283
+ const canvas{id} = document.getElementById('canvas{id}');
284
+ let stream{id}, recorder{id};
285
+
286
+ navigator.mediaDevices.getUserMedia({ video: true, audio: true })
287
+ .then(mediaStream => {
288
+ stream{id} = mediaStream;
289
+ video{id}.srcObject = stream{id};
290
+ recorder{id} = new MediaRecorder(stream{id});
291
+ const chunks = [];
292
+ recorder{id}.ondataavailable = e => chunks.push(e.data);
293
+ recorder{id}.onstop = () => {
294
+ const blob = new Blob(chunks, { type: 'video/mp4' });
295
+ const filename = `{id}${new Date().toISOString().replace(/[^0-9]/g, '')}.mp4`;
296
+ const url = URL.createObjectURL(blob);
297
+ const link = document.createElement('a');
298
+ link.href = url;
299
+ link.download = filename;
300
+ link.click();
301
+ console.log('Captured video:', filename);
302
+ sliceVideo{id}(blob);
303
+ };
304
+ console.log('Camera {id} stream started');
305
+ })
306
+ .catch(err => console.error('Error starting Camera {id}:', err));
307
+
308
+ function captureVideo{id}() {
309
+ recorder{id}.start();
310
+ setTimeout(() => recorder{id}.stop(), 10000); // 10 seconds
311
+ console.log('Recording started for Camera {id}');
312
+ }
313
+
314
+ function sliceVideo{id}(blob) {
315
+ const video = document.createElement('video');
316
+ video.src = URL.createObjectURL(blob);
317
+ video.onloadedmetadata = () => {
318
+ const ctx = canvas{id}.getContext('2d');
319
+ canvas{id}.width = video.videoWidth;
320
+ canvas{id}.height = video.videoHeight;
321
+ let frameCount = 0;
322
+ const interval = video.duration / 10;
323
+ video.currentTime = 0;
324
+ const captureFrame = () => {
325
+ if (frameCount < 10) {
326
+ ctx.drawImage(video, 0, 0, canvas{id}.width, canvas{id}.height);
327
+ const dataUrl = canvas{id}.toDataURL('image/png');
328
+ const filename = `{id}${new Date().toISOString().replace(/[^0-9]/g, '')}_${frameCount}.png`;
329
+ const link = document.createElement('a');
330
+ link.href = dataUrl;
331
+ link.download = filename;
332
+ link.click();
333
+ console.log('Captured frame:', filename);
334
+ frameCount++;
335
+ video.currentTime += interval;
336
+ setTimeout(captureFrame, 100);
337
+ }
338
+ };
339
+ video.play().then(captureFrame);
340
+ };
341
+ }
342
+ </script>
343
+ """
344
 
345
  # Main App
346
+ st.title("SFT Tiny Titans 🚀 (Web Cam Action!)")
347
 
348
  # Sidebar Galleries
349
  st.sidebar.header("Captured Media 🎨")
 
356
  for idx, file in enumerate(media_files[:4]):
357
  with cols[idx % 2]:
358
  if file.endswith(".png"):
 
359
  st.image(Image.open(file), caption=file.split('/')[-1], use_container_width=True)
360
  elif file.endswith(".mp4"):
361
  st.video(file)
 
401
 
402
  with tab2:
403
  st.header("Camera Snap 📷 (Dual Live Feed!)")
404
+ st.subheader("Source Configuration")
405
+ html(camera_selector_html, height=400)
406
  cols = st.columns(2)
 
407
  for i in range(2):
408
  with cols[i]:
409
+ html(image_capture_html.format(id=i), height=300)
410
+ html(video_capture_html.format(id=i), height=300)
411
+ st.subheader("Upload Captured Files")
412
+ uploaded_files = st.file_uploader("Upload PNGs/MP4s from Downloads", type=["png", "mp4"], accept_multiple_files=True)
413
+ if uploaded_files:
414
+ for file in uploaded_files:
415
+ filename = file.name
416
+ with open(filename, "wb") as f:
417
+ f.write(file.read())
418
+ logger.info(f"Saved uploaded file: {filename}")
419
+ if filename.endswith(".png"):
420
+ st.image(Image.open(filename), caption=filename, use_container_width=True)
421
+ elif filename.endswith(".mp4"):
422
+ st.video(filename)
423
+ update_gallery()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
424
 
425
  with tab3:
426
  st.header("Fine-Tune Titans 🔧 (Tune Fast!)")
 
447
  if st.button("Tune CV 🔄"):
448
  logger.info("Initiating CV fine-tune")
449
  try:
 
450
  images = [Image.open(img) for img in captured_images]
451
  st.session_state['builder'].fine_tune(images, texts)
452
  st.success("CV polished! 🎉")
453
  except Exception as e:
454
  st.error(f"CV fine-tune failed: {str(e)}")
455
  else:
456
+ st.warning("Upload at least 2 PNGs in Camera Snap first! ⚠️")
457
 
458
  with tab4:
459
  st.header("Test Titans 🧪 (Image Agent Demo!)")
 
477
  if st.button("Run CV Demo ▶️"):
478
  logger.info("Running CV image set demo")
479
  try:
 
480
  images = [Image.open(img) for img in captured_images[:10]]
481
  prompts = ["Neon " + os.path.basename(img).split('.')[0] for img in captured_images[:10]]
482
  generated_images = []
 
500
  st.error(f"CV demo failed: {str(e)}")
501
  logger.error(f"Error in CV demo: {str(e)}")
502
  else:
503
+ st.warning("Upload at least 2 PNGs in Camera Snap first! ⚠️")
504
 
505
  # Display Logs
506
  st.sidebar.subheader("Action Logs 📜")