Sean Carnahan commited on
Commit
fef15d6
·
1 Parent(s): 5dd4f2e

Fix HF Spaces deployment: Add proper path handling and model loading

Browse files
Files changed (2) hide show
  1. Dockerfile +6 -1
  2. app.py +25 -63
Dockerfile CHANGED
@@ -15,8 +15,13 @@ RUN pip install --no-cache-dir -r requirements.txt
15
  # Create necessary directories with proper permissions
16
  RUN mkdir -p /code/static/uploads \
17
  && mkdir -p /code/logs \
 
18
  && chmod -R 777 /code/static/uploads \
19
- && chmod -R 777 /code/logs
 
 
 
 
20
 
21
  # Copy the rest of the application
22
  COPY . .
 
15
  # Create necessary directories with proper permissions
16
  RUN mkdir -p /code/static/uploads \
17
  && mkdir -p /code/logs \
18
+ && mkdir -p /code/external/BodybuildingPoseClassifier \
19
  && chmod -R 777 /code/static/uploads \
20
+ && chmod -R 777 /code/logs \
21
+ && chmod -R 777 /code/external
22
+
23
+ # Copy the model file first
24
+ COPY external/BodybuildingPoseClassifier/bodybuilding_pose_classifier.h5 /code/external/BodybuildingPoseClassifier/
25
 
26
  # Copy the rest of the application
27
  COPY . .
app.py CHANGED
@@ -49,90 +49,52 @@ file_handler = logging.FileHandler(os.path.join(log_dir, 'app.log'))
49
  file_handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
50
  logger.addHandler(file_handler)
51
 
52
- def log_memory_usage():
53
- """Log current memory usage."""
54
- try:
55
- process = psutil.Process()
56
- memory_info = process.memory_info()
57
- logger.info(f"Memory usage: {memory_info.rss / 1024 / 1024:.2f} MB")
58
- except Exception as e:
59
- logger.error(f"Error logging memory usage: {e}")
60
-
61
- def cleanup_memory():
62
- """Force garbage collection and log memory usage."""
63
- try:
64
- gc.collect()
65
- log_memory_usage()
66
- except Exception as e:
67
- logger.error(f"Error in cleanup_memory: {e}")
68
-
69
- def wrap_text(text: str, font_face: int, font_scale: float, thickness: int, max_width: int) -> list[str]:
70
- """Wrap text to fit within max_width."""
71
- if not text:
72
- return []
73
-
74
- lines = []
75
- words = text.split(' ')
76
- current_line = ''
77
-
78
- for word in words:
79
- # Check width if current_line + word fits
80
- test_line = current_line + word + ' '
81
- (text_width, _), _ = cv2.getTextSize(test_line.strip(), font_face, font_scale, thickness)
82
-
83
- if text_width <= max_width:
84
- current_line = test_line
85
- else:
86
- # Word doesn't fit, so current_line (without the new word) is a complete line
87
- lines.append(current_line.strip())
88
- # Start new line with the current word
89
- current_line = word + ' '
90
- # If a single word is too long, it will still overflow. Handle by breaking word if necessary (future enhancement)
91
- (single_word_width, _), _ = cv2.getTextSize(word.strip(), font_face, font_scale, thickness)
92
- if single_word_width > max_width:
93
- # For now, just add the long word and let it overflow, or truncate it.
94
- # A more complex solution would break the word.
95
- lines.append(word.strip()) # Add the long word as its own line
96
- current_line = '' # Reset current_line as the long word is handled
97
-
98
- if current_line.strip(): # Add the last line
99
- lines.append(current_line.strip())
100
-
101
- return lines if lines else [text] # Ensure at least the original text is returned if no wrapping happens
102
-
103
- app = Flask(__name__, static_url_path='/static', static_folder='static')
104
  CORS(app, resources={r"/*": {"origins": "*"}})
105
 
106
- app.config['UPLOAD_FOLDER'] = 'static/uploads'
107
  app.config['MAX_CONTENT_LENGTH'] = 100 * 1024 * 1024 # 100MB max file size
108
 
109
- # Ensure upload directory exists
110
- os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
111
-
112
  # Load CNN model for bodybuilding pose classification
113
  try:
114
  logger.info("Loading CNN model...")
115
- cnn_model_path = 'external/BodybuildingPoseClassifier/bodybuilding_pose_classifier.h5'
 
 
116
  if not os.path.exists(cnn_model_path):
117
  raise FileNotFoundError(f"CNN model not found at {cnn_model_path}")
118
- cnn_model = load_model(cnn_model_path)
 
 
119
  logger.info("CNN model loaded successfully")
120
  except Exception as e:
121
  logger.error(f"Error loading CNN model: {e}")
 
122
  raise
123
 
124
  cnn_class_labels = ['side_chest', 'front_double_biceps', 'back_double_biceps', 'front_lat_spread', 'back_lat_spread']
125
 
126
  def predict_pose_cnn(img_path):
127
  try:
128
- cleanup_memory() # Clean up before prediction
129
  if gpus:
130
  logger.info("[CNN_DEBUG] Using GPU for CNN prediction")
131
  with tf.device('/GPU:0'):
132
  img = image.load_img(img_path, target_size=(150, 150))
133
  img_array = image.img_to_array(img)
134
  img_array = np.expand_dims(img_array, axis=0) / 255.0
135
- predictions = cnn_model.predict(img_array, verbose=0) # Disable progress bar
136
  predicted_class = np.argmax(predictions, axis=1)
137
  confidence = float(np.max(predictions))
138
  else:
@@ -141,7 +103,7 @@ def predict_pose_cnn(img_path):
141
  img = image.load_img(img_path, target_size=(150, 150))
142
  img_array = image.img_to_array(img)
143
  img_array = np.expand_dims(img_array, axis=0) / 255.0
144
- predictions = cnn_model.predict(img_array, verbose=0) # Disable progress bar
145
  predicted_class = np.argmax(predictions, axis=1)
146
  confidence = float(np.max(predictions))
147
 
@@ -149,10 +111,10 @@ def predict_pose_cnn(img_path):
149
  return cnn_class_labels[predicted_class[0]], confidence
150
  except Exception as e:
151
  logger.error(f"[CNN_ERROR] Exception during CNN prediction: {e}")
152
- traceback.print_exc()
153
  raise
154
  finally:
155
- cleanup_memory() # Clean up after prediction
156
 
157
  @app.route('/static/uploads/<path:filename>')
158
  def serve_video(filename):
 
49
  file_handler.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
50
  logger.addHandler(file_handler)
51
 
52
+ # Define base paths
53
+ BASE_DIR = os.path.dirname(os.path.abspath(__file__))
54
+ STATIC_DIR = os.path.join(BASE_DIR, 'static')
55
+ UPLOAD_DIR = os.path.join(STATIC_DIR, 'uploads')
56
+ MODEL_DIR = os.path.join(BASE_DIR, 'external', 'BodybuildingPoseClassifier')
57
+
58
+ # Ensure all required directories exist
59
+ for directory in [STATIC_DIR, UPLOAD_DIR, MODEL_DIR, log_dir]:
60
+ os.makedirs(directory, exist_ok=True)
61
+ logger.info(f"Ensured directory exists: {directory}")
62
+
63
+ app = Flask(__name__, static_url_path='/static', static_folder=STATIC_DIR)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  CORS(app, resources={r"/*": {"origins": "*"}})
65
 
66
+ app.config['UPLOAD_FOLDER'] = UPLOAD_DIR
67
  app.config['MAX_CONTENT_LENGTH'] = 100 * 1024 * 1024 # 100MB max file size
68
 
 
 
 
69
  # Load CNN model for bodybuilding pose classification
70
  try:
71
  logger.info("Loading CNN model...")
72
+ cnn_model_path = os.path.join(MODEL_DIR, 'bodybuilding_pose_classifier.h5')
73
+ logger.info(f"Looking for model at: {cnn_model_path}")
74
+
75
  if not os.path.exists(cnn_model_path):
76
  raise FileNotFoundError(f"CNN model not found at {cnn_model_path}")
77
+
78
+ # Load model with custom_objects to handle any custom layers
79
+ cnn_model = load_model(cnn_model_path, compile=False)
80
  logger.info("CNN model loaded successfully")
81
  except Exception as e:
82
  logger.error(f"Error loading CNN model: {e}")
83
+ logger.error(traceback.format_exc())
84
  raise
85
 
86
  cnn_class_labels = ['side_chest', 'front_double_biceps', 'back_double_biceps', 'front_lat_spread', 'back_lat_spread']
87
 
88
  def predict_pose_cnn(img_path):
89
  try:
90
+ cleanup_memory()
91
  if gpus:
92
  logger.info("[CNN_DEBUG] Using GPU for CNN prediction")
93
  with tf.device('/GPU:0'):
94
  img = image.load_img(img_path, target_size=(150, 150))
95
  img_array = image.img_to_array(img)
96
  img_array = np.expand_dims(img_array, axis=0) / 255.0
97
+ predictions = cnn_model.predict(img_array, verbose=0)
98
  predicted_class = np.argmax(predictions, axis=1)
99
  confidence = float(np.max(predictions))
100
  else:
 
103
  img = image.load_img(img_path, target_size=(150, 150))
104
  img_array = image.img_to_array(img)
105
  img_array = np.expand_dims(img_array, axis=0) / 255.0
106
+ predictions = cnn_model.predict(img_array, verbose=0)
107
  predicted_class = np.argmax(predictions, axis=1)
108
  confidence = float(np.max(predictions))
109
 
 
111
  return cnn_class_labels[predicted_class[0]], confidence
112
  except Exception as e:
113
  logger.error(f"[CNN_ERROR] Exception during CNN prediction: {e}")
114
+ logger.error(traceback.format_exc())
115
  raise
116
  finally:
117
+ cleanup_memory()
118
 
119
  @app.route('/static/uploads/<path:filename>')
120
  def serve_video(filename):