FaizanShaikh1 commited on
Commit
8e9064a
·
verified ·
1 Parent(s): 997c1fe

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +168 -136
app.py CHANGED
@@ -5,13 +5,15 @@ import time
5
  import sys
6
  import os
7
  from pathlib import Path
8
- import streamlit as st
9
- from PIL import Image, ImageTk
10
  import tempfile
11
  import io
12
  import threading
13
  import tkinter as tk
14
  from tkinter import filedialog, Label, Button, Frame
 
 
 
15
 
16
  # Constants
17
  MODEL_DIR = "models"
@@ -22,7 +24,7 @@ def parse_args():
22
  parser.add_argument('--garment', type=str, help='Path to garment image')
23
  parser.add_argument('--webcam', type=int, default=0, help='Webcam index to use')
24
  parser.add_argument('--resolution', type=str, default='640x480', help='Camera resolution')
25
- parser.add_argument('--streamlit', action='store_true', help='Run in Streamlit mode')
26
  parser.add_argument('--tkinter', action='store_true', help='Run with Tkinter UI')
27
  return parser.parse_args()
28
 
@@ -498,12 +500,12 @@ class GarmentProcessor:
498
  class AdvancedVirtualTryOn:
499
  """Main class for the virtual try-on system"""
500
 
501
- def __init__(self, garment_path, camera_index=0, resolution="640x480", streamlit_mode=False):
502
  # Parse resolution
503
  width, height = map(int, resolution.split('x'))
504
 
505
- # Set Streamlit mode
506
- self.streamlit_mode = streamlit_mode
507
 
508
  # Initialize components
509
  self.pose_estimator = HumanPoseEstimator()
@@ -512,8 +514,8 @@ class AdvancedVirtualTryOn:
512
  # Load garment
513
  self.garment = self.garment_processor.load_garment(garment_path)
514
 
515
- # Initialize camera if not in Streamlit mode
516
- if not streamlit_mode:
517
  self.camera = cv2.VideoCapture(camera_index)
518
  self.camera.set(cv2.CAP_PROP_FRAME_WIDTH, width)
519
  self.camera.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
@@ -544,7 +546,7 @@ class AdvancedVirtualTryOn:
544
  self.last_keypoints = None
545
 
546
  print("Advanced Virtual Try-On initialized.")
547
- if not streamlit_mode:
548
  print("Starting camera feed...")
549
 
550
  def update_fps(self):
@@ -709,7 +711,7 @@ class AdvancedVirtualTryOn:
709
  1, (0, 255, 0), 2, cv2.LINE_AA)
710
 
711
  # Display current garment fit parameters
712
- if self.show_controls and not self.streamlit_mode:
713
  # Display fitting instructions
714
  instructions = [
715
  "Controls:",
@@ -726,7 +728,7 @@ class AdvancedVirtualTryOn:
726
  cv2.putText(frame, line, (10, y_pos), cv2.FONT_HERSHEY_SIMPLEX,
727
  0.5, (0, 255, 0), 1, cv2.LINE_AA)
728
  y_pos += 25
729
- elif not self.streamlit_mode:
730
  cv2.putText(frame, "Press 'c' for controls", (10, 70),
731
  cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 1, cv2.LINE_AA)
732
 
@@ -734,8 +736,8 @@ class AdvancedVirtualTryOn:
734
 
735
  def run(self):
736
  """Main application loop"""
737
- if self.streamlit_mode:
738
- print("Streamlit mode is active. The main loop will be controlled by the Streamlit app.")
739
  return
740
 
741
  print("Advanced Virtual Try-On started. Press 'q' to quit, 'd' to toggle debug mode.")
@@ -822,7 +824,7 @@ class AdvancedVirtualTryOn:
822
 
823
  def clean_up(self):
824
  """Clean up resources"""
825
- if hasattr(self, 'camera') and not self.streamlit_mode and self.camera.isOpened():
826
  self.camera.release()
827
  cv2.destroyAllWindows()
828
  print("Application closed.")
@@ -1078,137 +1080,167 @@ def run_tkinter_app(webcam_index=0, resolution="640x480"):
1078
  ui = TkinterUI(webcam_index, resolution)
1079
  ui.start()
1080
 
1081
- def run_streamlit_app():
1082
- """Run the application in Streamlit mode"""
1083
- st.set_page_config(page_title="Virtual Try-On", page_icon="👕", layout="wide")
1084
-
1085
- st.title("Advanced Virtual Try-On")
1086
- st.subheader("Try on clothing virtually using your webcam")
1087
-
1088
- # Sidebar for uploading garment and adjustments
1089
- with st.sidebar:
1090
- st.header("Settings")
1091
- uploaded_garment = st.file_uploader("Upload a garment image (with transparent background)", type=["png", "jpg", "jpeg"])
1092
-
1093
- st.subheader("Fitting Adjustments")
1094
- width_scale = st.slider("Width Scale", 0.8, 3.0, 1.2, 0.1)
1095
- height_scale = st.slider("Height Scale", 0.6, 2.0, 1.1, 0.1)
1096
- collar_position = st.slider("Collar Position", 0.05, 0.3, 0.2, 0.01)
1097
-
1098
- debug_mode = st.checkbox("Show Skeleton", value=False)
1099
-
1100
- st.info("For best results, use a garment image with a transparent background.")
1101
-
1102
- # Main content
1103
- col1, col2 = st.columns(2)
1104
-
1105
- # If no garment uploaded, show sample garments
1106
- if uploaded_garment is None:
1107
- with col1:
1108
- st.warning("Please upload a garment image to begin")
1109
- st.write("No garment image uploaded. Here's how it works:")
1110
- st.write("1. Upload a garment image with transparent background")
1111
- st.write("2. Position yourself in front of the camera")
1112
- st.write("3. Adjust the fit using the controls in the sidebar")
1113
-
1114
- # Example garment placeholder
1115
- st.image("https://i.imgur.com/JFP0rja.png", caption="Example garment (upload your own)")
1116
-
1117
- with col2:
1118
- # Camera placeholder
1119
- st.write("Camera feed will appear here")
1120
- placeholder = st.empty()
1121
- placeholder.image(np.zeros((480, 640, 3), dtype=np.uint8), channels="BGR", caption="Webcam feed will appear here")
1122
-
1123
- return
1124
-
1125
- # Save uploaded garment to temp file
1126
- temp_garment_file = None
1127
- if uploaded_garment is not None:
1128
- temp_garment_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png")
1129
- temp_garment_file.write(uploaded_garment.getvalue())
1130
- temp_garment_file.close()
1131
-
1132
- # Initialize the application with the uploaded garment
1133
- try:
1134
- app = AdvancedVirtualTryOn(temp_garment_file.name, 0, "640x480", streamlit_mode=True)
1135
-
1136
- # Set parameters from sliders
1137
- app.width_scale = width_scale
1138
- app.height_scale = height_scale
1139
- app.collar_position = collar_position
1140
- app.debug_mode = debug_mode
1141
-
1142
- # Show the garment
1143
- with col1:
1144
- st.subheader("Garment:")
1145
- garment_display = cv2.cvtColor(app.garment, cv2.COLOR_BGRA2RGBA)
1146
- st.image(garment_display, caption="Your uploaded garment")
1147
-
1148
- # Start webcam
1149
- with col2:
1150
- st.subheader("Virtual Try-On:")
1151
- webcam_placeholder = st.empty()
1152
-
1153
- cap = cv2.VideoCapture(0)
1154
- cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
1155
- cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
1156
 
1157
- # Check if webcam opened successfully
1158
- if not cap.isOpened():
1159
- st.error("Could not open webcam. Please check your camera connection.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1160
  return
1161
 
1162
- stop_button = st.button("Stop")
1163
-
1164
- while not stop_button:
1165
- success, frame = cap.read()
1166
- if not success:
1167
- st.error("Failed to capture frame from webcam")
1168
- break
1169
-
1170
- # Process the frame
1171
- processed_frame = app.process_frame(frame)
1172
-
1173
- # Convert BGR to RGB for Streamlit
1174
- processed_frame_rgb = cv2.cvtColor(processed_frame, cv2.COLOR_BGR2RGB)
1175
-
1176
- # Display the processed frame
1177
- webcam_placeholder.image(processed_frame_rgb, channels="RGB", caption="Live Try-On")
1178
-
1179
- # Check if stop button was pressed
1180
- if stop_button:
1181
- break
1182
-
1183
- # Small sleep to reduce CPU usage
1184
- time.sleep(0.01)
1185
-
1186
- # Recheck the stop button status
1187
- stop_button = st.button("Stop")
1188
-
1189
- # Clean up
1190
- cap.release()
1191
-
1192
- except Exception as e:
1193
- st.error(f"Error: {e}")
1194
- if 'app' in locals():
1195
- app.clean_up()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1196
 
1197
- finally:
1198
- # Remove temporary file
1199
- if temp_garment_file:
1200
- try:
1201
- os.unlink(temp_garment_file.name)
1202
- except:
1203
- pass
1204
 
1205
  def main():
1206
  args = parse_args()
1207
  try:
1208
  # Check which mode to run in
1209
- if args.streamlit:
1210
- run_streamlit_app()
1211
- elif args.tkinter or (not args.garment and not args.streamlit):
 
1212
  # Use tkinter by default if no garment is specified
1213
  run_tkinter_app(args.webcam, args.resolution)
1214
  else:
 
5
  import sys
6
  import os
7
  from pathlib import Path
8
+ from PIL import Image
 
9
  import tempfile
10
  import io
11
  import threading
12
  import tkinter as tk
13
  from tkinter import filedialog, Label, Button, Frame
14
+ from shiny import App, render, ui, reactive
15
+ from shiny.types import ImgData
16
+ import base64
17
 
18
  # Constants
19
  MODEL_DIR = "models"
 
24
  parser.add_argument('--garment', type=str, help='Path to garment image')
25
  parser.add_argument('--webcam', type=int, default=0, help='Webcam index to use')
26
  parser.add_argument('--resolution', type=str, default='640x480', help='Camera resolution')
27
+ parser.add_argument('--shiny', action='store_true', help='Run in Shiny mode')
28
  parser.add_argument('--tkinter', action='store_true', help='Run with Tkinter UI')
29
  return parser.parse_args()
30
 
 
500
  class AdvancedVirtualTryOn:
501
  """Main class for the virtual try-on system"""
502
 
503
+ def __init__(self, garment_path, camera_index=0, resolution="640x480", shiny_mode=False):
504
  # Parse resolution
505
  width, height = map(int, resolution.split('x'))
506
 
507
+ # Set Shiny mode
508
+ self.shiny_mode = shiny_mode
509
 
510
  # Initialize components
511
  self.pose_estimator = HumanPoseEstimator()
 
514
  # Load garment
515
  self.garment = self.garment_processor.load_garment(garment_path)
516
 
517
+ # Initialize camera if not in Shiny mode
518
+ if not shiny_mode:
519
  self.camera = cv2.VideoCapture(camera_index)
520
  self.camera.set(cv2.CAP_PROP_FRAME_WIDTH, width)
521
  self.camera.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
 
546
  self.last_keypoints = None
547
 
548
  print("Advanced Virtual Try-On initialized.")
549
+ if not shiny_mode:
550
  print("Starting camera feed...")
551
 
552
  def update_fps(self):
 
711
  1, (0, 255, 0), 2, cv2.LINE_AA)
712
 
713
  # Display current garment fit parameters
714
+ if self.show_controls and not self.shiny_mode:
715
  # Display fitting instructions
716
  instructions = [
717
  "Controls:",
 
728
  cv2.putText(frame, line, (10, y_pos), cv2.FONT_HERSHEY_SIMPLEX,
729
  0.5, (0, 255, 0), 1, cv2.LINE_AA)
730
  y_pos += 25
731
+ elif not self.shiny_mode:
732
  cv2.putText(frame, "Press 'c' for controls", (10, 70),
733
  cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 1, cv2.LINE_AA)
734
 
 
736
 
737
  def run(self):
738
  """Main application loop"""
739
+ if self.shiny_mode:
740
+ print("Shiny mode is active. The main loop will be controlled by the Shiny app.")
741
  return
742
 
743
  print("Advanced Virtual Try-On started. Press 'q' to quit, 'd' to toggle debug mode.")
 
824
 
825
  def clean_up(self):
826
  """Clean up resources"""
827
+ if hasattr(self, 'camera') and not self.shiny_mode and self.camera.isOpened():
828
  self.camera.release()
829
  cv2.destroyAllWindows()
830
  print("Application closed.")
 
1080
  ui = TkinterUI(webcam_index, resolution)
1081
  ui.start()
1082
 
1083
+ def run_shiny_app():
1084
+ """Run the application in Shiny mode"""
1085
+ app_ui = ui.page_fluid(
1086
+ ui.tags.head(
1087
+ ui.tags.title("Advanced Virtual Try-On"),
1088
+ ui.tags.style("""
1089
+ .container { max-width: 1200px; }
1090
+ .row { margin-bottom: 20px; }
1091
+ .col-md-6 { padding: 10px; }
1092
+ .well { background-color: #f8f9fa; padding: 15px; border-radius: 5px; }
1093
+ .form-group { margin-bottom: 15px; }
1094
+ .control-label { font-weight: bold; }
1095
+ .img-preview { max-width: 100%; height: auto; }
1096
+ """)
1097
+ ),
1098
+ ui.div(
1099
+ {"class": "container"},
1100
+ ui.h1("Advanced Virtual Try-On"),
1101
+ ui.p("Try on clothing virtually using your webcam"),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1102
 
1103
+ ui.div(
1104
+ {"class": "row"},
1105
+ ui.div(
1106
+ {"class": "col-md-6"},
1107
+ ui.div(
1108
+ {"class": "well"},
1109
+ ui.h3("Settings"),
1110
+ ui.input_file("garment_upload", "Upload Garment Image",
1111
+ accept=[".png", ".jpg", ".jpeg"]),
1112
+ ui.div(
1113
+ {"class": "form-group"},
1114
+ ui.input_slider("width_scale", "Width Scale",
1115
+ min=0.8, max=3.0, value=1.2, step=0.1),
1116
+ ui.input_slider("height_scale", "Height Scale",
1117
+ min=0.6, max=2.0, value=1.1, step=0.1),
1118
+ ui.input_slider("collar_position", "Collar Position",
1119
+ min=0.05, max=0.3, value=0.2, step=0.01),
1120
+ ui.input_checkbox("debug_mode", "Show Skeleton", value=False)
1121
+ ),
1122
+ ui.div(
1123
+ {"class": "form-group"},
1124
+ ui.input_action_button("start_button", "Start Try-On",
1125
+ class_="btn-primary"),
1126
+ ui.input_action_button("stop_button", "Stop",
1127
+ class_="btn-danger")
1128
+ )
1129
+ )
1130
+ ),
1131
+ ui.div(
1132
+ {"class": "col-md-6"},
1133
+ ui.div(
1134
+ {"class": "well"},
1135
+ ui.h3("Preview"),
1136
+ ui.output_image("garment_preview"),
1137
+ ui.h3("Live Try-On"),
1138
+ ui.output_image("webcam_feed")
1139
+ )
1140
+ )
1141
+ )
1142
+ )
1143
+ )
1144
+
1145
+ def server(input, output, session):
1146
+ # Initialize reactive values
1147
+ app = reactive.Value(None)
1148
+ is_running = reactive.Value(False)
1149
+ temp_garment_file = reactive.Value(None)
1150
+
1151
+ @reactive.Effect
1152
+ @reactive.event(input.garment_upload)
1153
+ def handle_garment_upload():
1154
+ if input.garment_upload() is not None:
1155
+ # Save uploaded file to temp
1156
+ temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png")
1157
+ temp_file.write(input.garment_upload()["datapath"])
1158
+ temp_file.close()
1159
+ temp_garment_file.set(temp_file.name)
1160
+
1161
+ @reactive.Effect
1162
+ @reactive.event(input.start_button)
1163
+ def start_tryon():
1164
+ if not temp_garment_file.get():
1165
+ ui.notification_show("Please upload a garment first", type="warning")
1166
  return
1167
 
1168
+ if not is_running.get():
1169
+ try:
1170
+ app.set(AdvancedVirtualTryOn(
1171
+ temp_garment_file.get(),
1172
+ 0,
1173
+ "640x480",
1174
+ shiny_mode=True
1175
+ ))
1176
+ is_running.set(True)
1177
+ ui.notification_show("Try-on started", type="success")
1178
+ except Exception as e:
1179
+ ui.notification_show(f"Error starting try-on: {e}", type="error")
1180
+
1181
+ @reactive.Effect
1182
+ @reactive.event(input.stop_button)
1183
+ def stop_tryon():
1184
+ if is_running.get():
1185
+ if app.get():
1186
+ app.get().clean_up()
1187
+ is_running.set(False)
1188
+ ui.notification_show("Try-on stopped", type="info")
1189
+
1190
+ @output
1191
+ @render.image
1192
+ def garment_preview():
1193
+ if temp_garment_file.get():
1194
+ img = Image.open(temp_garment_file.get())
1195
+ # Convert to base64
1196
+ buffered = io.BytesIO()
1197
+ img.save(buffered, format="PNG")
1198
+ img_str = base64.b64encode(buffered.getvalue()).decode()
1199
+ return ImgData(src=f"data:image/png;base64,{img_str}")
1200
+ return None
1201
+
1202
+ @output
1203
+ @render.image
1204
+ def webcam_feed():
1205
+ if is_running.get() and app.get():
1206
+ try:
1207
+ # Get frame from camera
1208
+ ret, frame = app.get().camera.read()
1209
+ if ret:
1210
+ # Process the frame
1211
+ processed = app.get().process_frame(frame)
1212
+
1213
+ # Convert to PIL Image
1214
+ img = Image.fromarray(cv2.cvtColor(processed, cv2.COLOR_BGR2RGB))
1215
+
1216
+ # Convert to base64
1217
+ buffered = io.BytesIO()
1218
+ img.save(buffered, format="JPEG")
1219
+ img_str = base64.b64encode(buffered.getvalue()).decode()
1220
+ return ImgData(src=f"data:image/jpeg;base64,{img_str}")
1221
+ except Exception as e:
1222
+ ui.notification_show(f"Error processing frame: {e}", type="error")
1223
+ return None
1224
+
1225
+ # Update app parameters when sliders change
1226
+ @reactive.Effect
1227
+ def update_params():
1228
+ if app.get():
1229
+ app.get().width_scale = input.width_scale()
1230
+ app.get().height_scale = input.height_scale()
1231
+ app.get().collar_position = input.collar_position()
1232
+ app.get().debug_mode = input.debug_mode()
1233
 
1234
+ return App(app_ui, server)
 
 
 
 
 
 
1235
 
1236
  def main():
1237
  args = parse_args()
1238
  try:
1239
  # Check which mode to run in
1240
+ if args.shiny:
1241
+ app = run_shiny_app()
1242
+ app.run(host="0.0.0.0", port=8000)
1243
+ elif args.tkinter or (not args.garment and not args.shiny):
1244
  # Use tkinter by default if no garment is specified
1245
  run_tkinter_app(args.webcam, args.resolution)
1246
  else: