awacke1 commited on
Commit
963c867
Β·
verified Β·
1 Parent(s): 9a6f4b3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +91 -110
app.py CHANGED
@@ -2,94 +2,26 @@ import streamlit as st
2
  import pandas as pd
3
  from datetime import datetime
4
  import os
5
- import threading
6
- import time
7
- from PIL import Image
8
- from io import BytesIO
9
  import base64
10
- import cv2
11
- import numpy as np
12
- import queue
13
 
14
  # 🌟πŸ”₯ Initialize session state like a galactic DJ spinning tracks!
15
  if 'file_history' not in st.session_state:
16
  st.session_state['file_history'] = []
17
- if 'auto_capture_running' not in st.session_state:
18
- st.session_state['auto_capture_running'] = False
19
-
20
- # πŸ“ΈπŸ“· Camera thread class for OpenCV capture
21
- class CamThread(threading.Thread):
22
- def __init__(self, preview_name, cam_id, frame_queue):
23
- threading.Thread.__init__(self)
24
- self.preview_name = preview_name
25
- self.cam_id = cam_id
26
- self.frame_queue = frame_queue
27
- self.running = True
28
-
29
- def run(self):
30
- print(f"Starting {self.preview_name}")
31
- self.cam_preview()
32
-
33
- def cam_preview(self):
34
- cam = cv2.VideoCapture(self.cam_id)
35
- cam.set(cv2.CAP_PROP_FRAME_WIDTH, 640) # Set reasonable resolution
36
- cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
37
- cam.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')) # Use MJPG for better USB compatibility
38
- if not cam.isOpened():
39
- st.error(f"🚨 Failed to open {self.preview_name}. Check connection or index.")
40
- return
41
-
42
- while self.running:
43
- ret, frame = cam.read()
44
- if ret:
45
- # Convert BGR to RGB for display
46
- frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
47
- try:
48
- self.frame_queue.put_nowait(frame_rgb)
49
- except queue.Full:
50
- pass # Skip if queue is full
51
- time.sleep(0.03) # ~30 FPS
52
-
53
- cam.release()
54
-
55
- def stop(self):
56
- self.running = False
57
 
58
  # πŸ“œπŸ’Ύ Save to history like a time-traveling scribe! | πŸ“…βœ¨ save_to_history("πŸ–ΌοΈ Image", "pic.jpg", img_data) - Stamps a pic in the history books like a boss!
59
  def save_to_history(file_type, file_path, img_data):
60
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
61
- # Convert RGB to BGR for OpenCV saving
62
- img_bgr = cv2.cvtColor(img_data, cv2.COLOR_RGB2BGR)
63
- cv2.imwrite(file_path, img_bgr)
64
  st.session_state['file_history'].append({
65
  "Timestamp": timestamp,
66
  "Type": file_type,
67
  "Path": file_path
68
  })
69
 
70
- # πŸ“Έβ° Auto-capture every 10 secs like a sneaky shutterbug!
71
- def auto_capture(frame_queues):
72
- while st.session_state['auto_capture_running']:
73
- for i, q in enumerate(frame_queues):
74
- try:
75
- frame = q.get_nowait()
76
- filename = f"cam{i}_auto_{datetime.now().strftime('%Y%m%d_%H%M%S')}.jpg"
77
- save_to_history("πŸ–ΌοΈ Image", filename, frame)
78
- except queue.Empty:
79
- pass # Skip if no frame available
80
- time.sleep(10)
81
-
82
  # πŸŽ›οΈ Sidebar config like a spaceship control panel!
83
  with st.sidebar:
84
  st.header("πŸŽšοΈπŸ“Έ Snap Shack")
85
- frame_queues = [queue.Queue(maxsize=1), queue.Queue(maxsize=1)] # Define frame_queues here
86
- if st.button("⏰ Start Auto-Snap"):
87
- st.session_state['auto_capture_running'] = True
88
- threading.Thread(target=auto_capture, args=(frame_queues,), daemon=True).start()
89
- if st.button("⏹️ Stop Auto-Snap"):
90
- st.session_state['auto_capture_running'] = False
91
-
92
- # πŸ“‚ Sidebar file outline with emoji flair!
93
  st.subheader("πŸ“œ Snap Stash")
94
  if st.session_state['file_history']:
95
  images = [f for f in st.session_state['file_history'] if f['Type'] == "πŸ–ΌοΈ Image"]
@@ -101,33 +33,94 @@ with st.sidebar:
101
  st.write("πŸ•³οΈ Empty Stash!")
102
 
103
  # 🌍🎨 Main UI kicks off like a cosmic art show!
104
- st.title("πŸ“Έ OpenCV Snap Craze")
105
-
106
- # πŸ“ΈπŸ“· Start camera threads
107
- threads = [
108
- CamThread("Camera 0", 0, frame_queues[0]),
109
- CamThread("Camera 1", 1, frame_queues[1])
110
- ]
111
- for thread in threads:
112
- thread.start()
113
 
114
- # πŸ“ΈπŸ“· Camera snap zone!
115
  st.header("πŸ“ΈπŸŽ₯ Snap Zone")
116
- cols = st.columns(2)
117
- placeholders = [cols[0].empty(), cols[1].empty()]
118
- for i, (placeholder, q, thread) in enumerate(zip(placeholders, frame_queues, threads)):
119
- if st.button(f"πŸ“Έ Snap Cam {i}", key=f"snap{i}"):
120
- try:
121
- frame = q.get_nowait()
122
- filename = f"cam{i}_snap_{datetime.now().strftime('%Y%m%d_%H%M%S')}.jpg"
123
- save_to_history("πŸ–ΌοΈ Image", filename, frame)
124
- except queue.Empty:
125
- st.error(f"🚨 No frame from Cam {i} yet!")
126
- try:
127
- frame = q.get_nowait()
128
- placeholder.image(frame, caption=f"Live Cam {i}", use_container_width=True)
129
- except queue.Empty:
130
- placeholder.write(f"πŸ“· Waiting for Cam {i}...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
 
132
  # πŸ“‚ Upload zone like a media drop party!
133
  st.header("πŸ“₯πŸŽ‰ Drop Zone")
@@ -135,10 +128,8 @@ uploaded_files = st.file_uploader("πŸ“Έ Toss Pics", accept_multiple_files=True,
135
  if uploaded_files:
136
  for uploaded_file in uploaded_files:
137
  file_path = f"uploaded_{uploaded_file.name}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.jpg"
138
- img = Image.open(uploaded_file)
139
- img_array = np.array(img)
140
- save_to_history("πŸ–ΌοΈ Image", file_path, img_array)
141
- st.image(img, caption=uploaded_file.name, use_container_width=True)
142
 
143
  # πŸ–ΌοΈ Gallery like a media circus!
144
  st.header("πŸŽͺ Snap Show")
@@ -165,14 +156,4 @@ if st.session_state['file_history']:
165
  df = pd.DataFrame(st.session_state['file_history'])
166
  st.dataframe(df)
167
  else:
168
- st.write("πŸ•³οΈ Nothing snapped yet!")
169
-
170
- # Cleanup on app exit
171
- def cleanup():
172
- for thread in threads:
173
- thread.stop()
174
- for thread in threads:
175
- thread.join()
176
-
177
- import atexit
178
- atexit.register(cleanup)
 
2
  import pandas as pd
3
  from datetime import datetime
4
  import os
 
 
 
 
5
  import base64
 
 
 
6
 
7
  # 🌟πŸ”₯ Initialize session state like a galactic DJ spinning tracks!
8
  if 'file_history' not in st.session_state:
9
  st.session_state['file_history'] = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  # πŸ“œπŸ’Ύ Save to history like a time-traveling scribe! | πŸ“…βœ¨ save_to_history("πŸ–ΌοΈ Image", "pic.jpg", img_data) - Stamps a pic in the history books like a boss!
12
  def save_to_history(file_type, file_path, img_data):
13
  timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
14
+ with open(file_path, "wb") as f:
15
+ f.write(base64.b64decode(img_data.split(',')[1]))
 
16
  st.session_state['file_history'].append({
17
  "Timestamp": timestamp,
18
  "Type": file_type,
19
  "Path": file_path
20
  })
21
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  # πŸŽ›οΈ Sidebar config like a spaceship control panel!
23
  with st.sidebar:
24
  st.header("πŸŽšοΈπŸ“Έ Snap Shack")
 
 
 
 
 
 
 
 
25
  st.subheader("πŸ“œ Snap Stash")
26
  if st.session_state['file_history']:
27
  images = [f for f in st.session_state['file_history'] if f['Type'] == "πŸ–ΌοΈ Image"]
 
33
  st.write("πŸ•³οΈ Empty Stash!")
34
 
35
  # 🌍🎨 Main UI kicks off like a cosmic art show!
36
+ st.title("πŸ“Έ Multi-Cam Snap Craze")
 
 
 
 
 
 
 
 
37
 
38
+ # πŸ“ΈπŸ“· JS camera zone with multiple streams!
39
  st.header("πŸ“ΈπŸŽ₯ Snap Zone")
40
+ multi_cam_html = """
41
+ <div id="videoContainer"></div>
42
+ <script>
43
+ let streams = [];
44
+ const container = document.getElementById('videoContainer');
45
+ let autoCaptureIntervals = [];
46
+
47
+ // πŸ“ΉπŸ” Enumerate cameras like a tech detective!
48
+ async function enumerateAndStartCameras() {
49
+ const devices = await navigator.mediaDevices.enumerateDevices();
50
+ const videoDevices = devices.filter(device => device.kind === 'videoinput');
51
+ videoDevices.forEach((device, index) => {
52
+ const div = document.createElement('div');
53
+ div.innerHTML = `
54
+ <p>${device.label || 'Camera ' + index}</p>
55
+ <video id="video${index}" autoplay playsinline style="width:100%;"></video>
56
+ <canvas id="canvas${index}" style="display:none;"></canvas>
57
+ <button onclick="takeSnapshot(${index})">πŸ“Έ Snap Cam ${index}</button>
58
+ `;
59
+ container.appendChild(div);
60
+ startStream(device.deviceId, index);
61
+ });
62
+ }
63
+
64
+ // πŸ“ΈπŸŽ₯ Start streaming like a live broadcast pro!
65
+ async function startStream(deviceId, index) {
66
+ const constraints = { video: { deviceId: { exact: deviceId } } };
67
+ const stream = await navigator.mediaDevices.getUserMedia(constraints);
68
+ const video = document.getElementById(`video${index}`);
69
+ video.srcObject = stream;
70
+ streams.push(stream);
71
+ // Auto-capture every 10 seconds
72
+ autoCaptureIntervals[index] = setInterval(() => takeSnapshot(index), 10000);
73
+ }
74
+
75
+ // πŸ“Έβœ‚οΈ Snap a pic like a stealthy paparazzi!
76
+ function takeSnapshot(index) {
77
+ const video = document.getElementById(`video${index}`);
78
+ const canvas = document.getElementById(`canvas${index}`);
79
+ canvas.width = video.videoWidth;
80
+ canvas.height = video.videoHeight;
81
+ canvas.getContext('2d').drawImage(video, 0, 0);
82
+ const dataUrl = canvas.toDataURL('image/jpeg');
83
+ window.parent.postMessage({ type: 'snapshot', data: dataUrl, camIndex: index }, '*');
84
+ }
85
+
86
+ // βΉοΈπŸ“΄ Stop all streams like a broadcast kill switch!
87
+ function stopStreams() {
88
+ streams.forEach(stream => stream.getTracks().forEach(track => track.stop()));
89
+ streams = [];
90
+ autoCaptureIntervals.forEach(interval => clearInterval(interval));
91
+ autoCaptureIntervals = [];
92
+ }
93
+
94
+ // 🎬 Kick off the camera party!
95
+ enumerateAndStartCameras();
96
+ window.onunload = stopStreams;
97
+ </script>
98
+ """
99
+ st.markdown(multi_cam_html, unsafe_allow_html=True)
100
+
101
+ # πŸ“ΈπŸ“₯ Handle snapshots from JS
102
+ def handle_snapshot():
103
+ if "snapshot" in st.session_state:
104
+ snapshot_data = st.session_state["snapshot"]
105
+ cam_index = st.session_state.get("camIndex", 0)
106
+ filename = f"cam{cam_index}_snap_{datetime.now().strftime('%Y%m%d_%H%M%S')}.jpg"
107
+ save_to_history("πŸ–ΌοΈ Image", filename, snapshot_data)
108
+ st.image(Image.open(BytesIO(base64.b64decode(snapshot_data.split(',')[1]))), caption=f"Cam {cam_index} Snap", use_container_width=True)
109
+ del st.session_state["snapshot"]
110
+
111
+ st.components.v1.html(
112
+ """
113
+ <script>
114
+ window.addEventListener('message', function(event) {
115
+ if (event.data.type === 'snapshot') {
116
+ window.streamlitAPI.setComponentValue({snapshot: event.data.data, camIndex: event.data.camIndex});
117
+ }
118
+ });
119
+ </script>
120
+ """,
121
+ height=0
122
+ )
123
+ handle_snapshot()
124
 
125
  # πŸ“‚ Upload zone like a media drop party!
126
  st.header("πŸ“₯πŸŽ‰ Drop Zone")
 
128
  if uploaded_files:
129
  for uploaded_file in uploaded_files:
130
  file_path = f"uploaded_{uploaded_file.name}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.jpg"
131
+ save_to_history("πŸ–ΌοΈ Image", file_path, base64.b64encode(uploaded_file.getvalue()).decode())
132
+ st.image(Image.open(uploaded_file), caption=uploaded_file.name, use_container_width=True)
 
 
133
 
134
  # πŸ–ΌοΈ Gallery like a media circus!
135
  st.header("πŸŽͺ Snap Show")
 
156
  df = pd.DataFrame(st.session_state['file_history'])
157
  st.dataframe(df)
158
  else:
159
+ st.write("πŸ•³οΈ Nothing snapped yet!")