vertalius commited on
Commit
b7c53bf
·
verified ·
1 Parent(s): 4155984

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +11 -93
app.py CHANGED
@@ -6,17 +6,6 @@ from typing import Optional, Tuple
6
  from datetime import datetime
7
  from PIL import Image
8
 
9
- # Попытка импортировать st_canvas; если не установлен, интерактивный режим будет отключён.
10
- try:
11
- from streamlit_drawable_canvas import st_canvas
12
- canvas_available = True
13
- except ImportError:
14
- canvas_available = False
15
- st.warning(
16
- "Интерактивное редактирование отключено, так как модуль streamlit-drawable-canvas не установлен. "
17
- "Для его использования добавьте 'streamlit-drawable-canvas' в зависимости."
18
- )
19
-
20
  from pose_detector import PoseDetector
21
  from skeleton_generator import SkeletonGenerator
22
  from animation_exporter import AnimationExporter
@@ -34,31 +23,22 @@ def init_page():
34
  padding: 2rem;
35
  transition: background-color 0.3s;
36
  }
37
-
38
- /* Dark theme */
39
  [data-theme="dark"] .stApp {
40
  background-color: #1E1E1E;
41
  color: #FFFFFF;
42
  }
43
-
44
- /* Widget styling */
45
  .stButton>button {
46
  background-color: #4CAF50;
47
  color: white;
48
  border-radius: 4px;
49
  padding: 0.5rem 1rem;
50
  }
51
-
52
  .stDownloadButton>button {
53
  background-color: #008CBA;
54
  }
55
-
56
- /* Progress bars */
57
  .stProgress > div > div > div {
58
  background-color: #4CAF50;
59
  }
60
-
61
- /* Columns spacing */
62
  .stColumn {
63
  padding: 0 1rem;
64
  }
@@ -86,7 +66,7 @@ def init_page():
86
  st.session_state.manual_correction = st.sidebar.checkbox("Enable Manual Corrections", value=st.session_state.manual_correction)
87
 
88
  if st.session_state.manual_correction:
89
- st.sidebar.info("Интерактивное редактирование доступно" + (" (с использованием canvas)" if canvas_available else " (canvas не доступен)"))
90
 
91
  st.title("Pose Detection & Animation Generator")
92
  return confidence_threshold
@@ -129,7 +109,7 @@ def main():
129
  with col1:
130
  st.subheader("Original")
131
  with col2:
132
- st.subheader("Processed (click to select joint)")
133
 
134
  try:
135
  if file_type == 'image' and not is_gif:
@@ -151,10 +131,9 @@ def main():
151
  db.close()
152
 
153
  def process_image_upload(uploaded_file, components, processed_file, db, col1, col2):
154
- """Обработка изображения с сохранением состояния и интерактивным выбором сустава (если canvas доступен)."""
155
  pose_detector, skeleton_generator, animation_exporter = components
156
 
157
- # Сохраняем исходное изображение в session_state
158
  if "uploaded_image" not in st.session_state:
159
  file_bytes = np.asarray(bytearray(uploaded_file.read()), dtype=np.uint8)
160
  image = cv2.imdecode(file_bytes, 1)
@@ -165,7 +144,6 @@ def process_image_upload(uploaded_file, components, processed_file, db, col1, co
165
  with col1:
166
  st.image(cv2.cvtColor(image, cv2.COLOR_BGR2RGB), use_column_width=True)
167
 
168
- # Обработка изображения для получения позы и скелета
169
  if "original_skeleton_data" not in st.session_state:
170
  processed_image, skeleton_data = process_image(image, pose_detector, skeleton_generator)
171
  st.session_state.original_skeleton_data = skeleton_data
@@ -174,75 +152,15 @@ def process_image_upload(uploaded_file, components, processed_file, db, col1, co
174
  skeleton_data = st.session_state.original_skeleton_data
175
  processed_image = st.session_state.processed_image
176
 
177
- # Сохраняем данные поз в БД
178
  save_pose_data(db, processed_file.id, skeleton_data)
179
  animation_data_binary = animation_exporter.export_pose(skeleton_data)
180
  save_animation_data(db, processed_file.id, skeleton_data)
181
 
182
  with col2:
183
- height, width = processed_image.shape[:2]
184
  processed_rgb = cv2.cvtColor(processed_image, cv2.COLOR_BGR2RGB)
185
- pil_image = Image.fromarray(processed_rgb)
186
-
187
- if canvas_available and st.session_state.get('manual_correction', False):
188
- # Используем st_canvas для интерактивного редактирования
189
- canvas_result = st_canvas(
190
- fill_color="rgba(0, 0, 0, 0)", # прозрачный фон для рисования
191
- stroke_width=5,
192
- stroke_color="#FF0000",
193
- background_image=pil_image,
194
- update_streamlit=True,
195
- height=height,
196
- width=width,
197
- drawing_mode="point", # режим для регистрации кликов
198
- key="canvas"
199
- )
200
-
201
- if canvas_result.json_data is not None:
202
- objects = canvas_result.json_data.get("objects", [])
203
- if objects:
204
- last_obj = objects[-1]
205
- click_x = last_obj.get("left")
206
- click_y = last_obj.get("top")
207
-
208
- # Находим ближайший joint (координаты нормализованы)
209
- min_dist = float("inf")
210
- selected_joint = None
211
- for joint_name, data in skeleton_data.items():
212
- joint_px = data['position'][0] * width
213
- joint_py = data['position'][1] * height
214
- dist = ((joint_px - click_x)**2 + (joint_py - click_y)**2)**0.5
215
- if dist < min_dist:
216
- min_dist = dist
217
- selected_joint = joint_name
218
- threshold = 20 # порог в пикселях для выбора сустава
219
- if min_dist < threshold:
220
- st.session_state.active_joint = selected_joint
221
- st.write(f"Selected joint: **{selected_joint}**")
222
- else:
223
- st.write("Click closer to a joint to select it.")
224
-
225
- if st.session_state.get("active_joint"):
226
- active_joint = st.session_state.active_joint
227
- joints = st.session_state.get("current_landmarks", skeleton_data.copy())
228
- st.write(f"Active joint for adjustment: **{active_joint}**")
229
- x_pos = st.slider("Adjust X", 0.0, 1.0, float(joints[active_joint]['position'][0]), 0.01, key=f"adj_x_{active_joint}")
230
- y_pos = st.slider("Adjust Y", 0.0, 1.0, float(joints[active_joint]['position'][1]), 0.01, key=f"adj_y_{active_joint}")
231
- if st.button("Apply Adjustment", key=f"apply_adj_{active_joint}"):
232
- joints[active_joint]['position'] = [x_pos, y_pos]
233
- st.session_state.current_landmarks = joints
234
- corrected_image = pose_detector.draw_corrected_pose(image, joints)
235
- st.session_state.processed_image = corrected_image
236
- corrected_rgb = cv2.cvtColor(corrected_image, cv2.COLOR_BGR2RGB)
237
- st.image(corrected_rgb, use_column_width=True)
238
- st.write(f"Updated {active_joint}: {joints[active_joint]['position']}")
239
- if st.button("Save Corrections", key=f"save_adj_{active_joint}"):
240
- save_corrected_pose(db, processed_file.id, joints)
241
- st.success("Corrections saved successfully!")
242
- else:
243
- # Если canvas недоступен, выводим просто изображение и сообщение
244
- st.image(processed_rgb, use_column_width=True)
245
- st.info("Интерактивное редактирование недоступно, так как streamlit-drawable-canvas не установлен.")
246
 
247
  def process_video_upload(uploaded_file, components, processed_file, db, is_gif, col1, col2):
248
  """Обработка видео/GIF файлов."""
@@ -307,12 +225,12 @@ def save_corrected_pose(db, file_id: int, joints: dict):
307
  def show_instructions():
308
  with st.expander("Instructions"):
309
  st.markdown("""
310
- 1. Upload an image/video using the file uploader.
311
  2. Wait for processing to complete.
312
- 3. In the **Processed** panel, click on the preview canvas near a joint to select it.
313
- 4. Adjust the selected joint using the sliders and click **Apply Adjustment**.
314
- 5. Click **Save Corrections** to store the changes.
315
- 6. Download animation data.
316
 
317
  Supported formats:
318
  - Images: JPG, PNG
 
6
  from datetime import datetime
7
  from PIL import Image
8
 
 
 
 
 
 
 
 
 
 
 
 
9
  from pose_detector import PoseDetector
10
  from skeleton_generator import SkeletonGenerator
11
  from animation_exporter import AnimationExporter
 
23
  padding: 2rem;
24
  transition: background-color 0.3s;
25
  }
 
 
26
  [data-theme="dark"] .stApp {
27
  background-color: #1E1E1E;
28
  color: #FFFFFF;
29
  }
 
 
30
  .stButton>button {
31
  background-color: #4CAF50;
32
  color: white;
33
  border-radius: 4px;
34
  padding: 0.5rem 1rem;
35
  }
 
36
  .stDownloadButton>button {
37
  background-color: #008CBA;
38
  }
 
 
39
  .stProgress > div > div > div {
40
  background-color: #4CAF50;
41
  }
 
 
42
  .stColumn {
43
  padding: 0 1rem;
44
  }
 
66
  st.session_state.manual_correction = st.sidebar.checkbox("Enable Manual Corrections", value=st.session_state.manual_correction)
67
 
68
  if st.session_state.manual_correction:
69
+ st.sidebar.info("Интерактивная корректировка временно отключена.")
70
 
71
  st.title("Pose Detection & Animation Generator")
72
  return confidence_threshold
 
109
  with col1:
110
  st.subheader("Original")
111
  with col2:
112
+ st.subheader("Processed")
113
 
114
  try:
115
  if file_type == 'image' and not is_gif:
 
131
  db.close()
132
 
133
  def process_image_upload(uploaded_file, components, processed_file, db, col1, col2):
134
+ """Обработка изображения с сохранением состояния. Интерактивная коррекция отключена."""
135
  pose_detector, skeleton_generator, animation_exporter = components
136
 
 
137
  if "uploaded_image" not in st.session_state:
138
  file_bytes = np.asarray(bytearray(uploaded_file.read()), dtype=np.uint8)
139
  image = cv2.imdecode(file_bytes, 1)
 
144
  with col1:
145
  st.image(cv2.cvtColor(image, cv2.COLOR_BGR2RGB), use_column_width=True)
146
 
 
147
  if "original_skeleton_data" not in st.session_state:
148
  processed_image, skeleton_data = process_image(image, pose_detector, skeleton_generator)
149
  st.session_state.original_skeleton_data = skeleton_data
 
152
  skeleton_data = st.session_state.original_skeleton_data
153
  processed_image = st.session_state.processed_image
154
 
 
155
  save_pose_data(db, processed_file.id, skeleton_data)
156
  animation_data_binary = animation_exporter.export_pose(skeleton_data)
157
  save_animation_data(db, processed_file.id, skeleton_data)
158
 
159
  with col2:
 
160
  processed_rgb = cv2.cvtColor(processed_image, cv2.COLOR_BGR2RGB)
161
+ st.image(processed_rgb, use_column_width=True)
162
+ if st.session_state.get('manual_correction', False):
163
+ st.info("Интерактивная корректировка временно отключена.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
 
165
  def process_video_upload(uploaded_file, components, processed_file, db, is_gif, col1, col2):
166
  """Обработка видео/GIF файлов."""
 
225
  def show_instructions():
226
  with st.expander("Instructions"):
227
  st.markdown("""
228
+ 1. Upload an image or video using the file uploader.
229
  2. Wait for processing to complete.
230
+ 3. The **Detection Confidence** slider in the sidebar sets the minimum confidence threshold for detecting a pose.
231
+ A higher value (e.g., 0.7) means that only detections with high certainty are considered, which may improve accuracy.
232
+ 4. The processed image/video will be displayed in the "Processed" panel.
233
+ 5. Download animation data.
234
 
235
  Supported formats:
236
  - Images: JPG, PNG