nonamelife commited on
Commit
da622da
·
verified ·
1 Parent(s): 6b9715a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +73 -45
app.py CHANGED
@@ -5,80 +5,100 @@ from flask import Flask, request, render_template, jsonify
5
  from tensorflow.keras.utils import load_img, img_to_array
6
  from werkzeug.utils import secure_filename
7
  from datetime import datetime
8
- from huggingface_hub import hf_hub_download # New import!
9
- import time
10
 
11
  app = Flask(__name__)
12
 
13
  # --- Model Loading Configuration ---
14
  MODEL_FILE_NAME = "model.keras"
15
- # REPLACE THIS WITH YOUR HUGGING FACE MODEL REPO ID
16
- # Format: "your-username/your-model-repo-name"
17
- HF_MODEL_REPO_ID = "nonamelife/garbage-detection-model" # Example!
18
-
19
- # Check if model exists, if not, try to download it from Hugging Face Hub
20
- if not os.path.exists(MODEL_FILE_NAME):
21
- print(f"'{MODEL_FILE_NAME}' not found locally. Attempting to download from Hugging Face Hub...")
22
- try:
23
- # Download the model from Hugging Face Hub
24
- # The downloaded file will be in a cache directory by default,
25
- # so we'll move it to the current directory for easier loading.
26
- model_path = hf_hub_download(repo_id=HF_MODEL_REPO_ID, filename=MODEL_FILE_NAME)
27
- # Move the downloaded file to the root directory for app.py to find it easily
28
- os.rename(model_path, MODEL_FILE_NAME)
29
- print(f"'{MODEL_FILE_NAME}' downloaded successfully from Hugging Face Hub.")
30
- except Exception as e:
31
- print(f"FATAL: Could not download model from Hugging Face Hub: {e}")
32
- # If download fails, the model will remain None, and prediction attempts will fail.
33
- model = None
34
-
35
- # Load the trained model
36
- model = None # Initialize model to None
37
  try:
38
- if os.path.exists(MODEL_FILE_NAME):
39
- model = tf.keras.models.load_model(MODEL_FILE_NAME)
40
- print(f"Model loaded successfully from {MODEL_FILE_NAME}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  else:
42
- print(f"Model file '{MODEL_FILE_NAME}' still not found after download attempt.")
 
 
43
  except Exception as e:
44
- print(f"Error loading model from {MODEL_FILE_NAME}: {e}")
45
- model = None # Ensure model is None if loading fails
 
 
 
 
46
 
47
- # Configurations
48
  UPLOAD_FOLDER = os.path.join('static', 'uploads')
49
  ALLOWED_EXTENSIONS = {'jpg', 'jpeg', 'png'}
50
  app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
51
- os.makedirs(UPLOAD_FOLDER, exist_ok=True) # Ensure uploads directory exists
 
52
 
53
  def allowed_file(filename):
54
- return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
 
 
55
 
56
  def preprocess_image(image_path):
57
- img = load_img(image_path, target_size=(224, 224))
58
- img_array = img_to_array(img) / 255.0
59
- return np.expand_dims(img_array, axis=0)
 
60
 
 
61
  @app.route('/')
62
  def index():
 
63
  return render_template('home.html')
64
 
65
  @app.route('/tool')
66
  def tool():
 
67
  return render_template('tool.html')
68
 
69
  @app.route('/about')
70
  def about():
 
71
  return render_template('about.html')
72
 
73
  @app.route('/contact')
74
  def contact():
 
75
  return render_template('contact.html')
76
 
77
  @app.route('/predict', methods=['POST'])
78
  def predict():
 
 
79
  if model is None:
80
  return jsonify({'error': 'Model not loaded. Please check server logs.'}), 500
81
 
 
82
  if 'file' not in request.files:
83
  return jsonify({'error': 'No files uploaded'}), 400
84
 
@@ -90,24 +110,28 @@ def predict():
90
  for file in files:
91
  file_path = None
92
  if file and allowed_file(file.filename):
 
93
  filename = secure_filename(file.filename)
94
  timestamp = datetime.now().strftime("%Y%m%d%H%M%S%f")
95
  unique_filename = f"{timestamp}_{filename}"
96
  file_path = os.path.join(app.config['UPLOAD_FOLDER'], unique_filename)
97
- file.save(file_path)
98
 
99
  try:
100
- img_array = preprocess_image(file_path)
101
- prediction = model.predict(img_array)[0][0]
 
 
102
  label = "Dirty" if prediction > 0.5 else "Clean"
103
  confidence = prediction if label == "Dirty" else 1 - prediction
104
 
105
  results.append({
106
  'label': label,
107
- 'confidence': f"{confidence:.2%}",
108
- 'image_url': f"/static/uploads/{unique_filename}"
109
  })
110
  except Exception as e:
 
111
  results.append({
112
  'label': 'Error',
113
  'confidence': 'N/A',
@@ -115,7 +139,7 @@ def predict():
115
  'error': str(e)
116
  })
117
  finally:
118
- # Clean up the uploaded file after processing
119
  if file_path and os.path.exists(file_path):
120
  try:
121
  os.remove(file_path)
@@ -123,6 +147,7 @@ def predict():
123
  except Exception as e:
124
  print(f"Error deleting file {file_path}: {e}")
125
  else:
 
126
  results.append({
127
  'label': 'Error',
128
  'confidence': 'N/A',
@@ -130,10 +155,13 @@ def predict():
130
  'error': f"Invalid file type: {file.filename}"
131
  })
132
 
 
133
  return render_template('results.html', results=results)
134
 
 
135
  if __name__ == '__main__':
136
- # Hugging Face Spaces sets the PORT environment variable
137
- # Default to 7860 as it's common for HF Spaces apps
 
138
  port = int(os.environ.get('PORT', 7860))
139
- app.run(host='0.0.0.0', port=port, debug=True)
 
5
  from tensorflow.keras.utils import load_img, img_to_array
6
  from werkzeug.utils import secure_filename
7
  from datetime import datetime
8
+ from huggingface_hub import hf_hub_download # Crucial for downloading model from HF Hub
9
+ import time # Used for potential retry logic, though not explicitly in hf_hub_download here
10
 
11
  app = Flask(__name__)
12
 
13
  # --- Model Loading Configuration ---
14
  MODEL_FILE_NAME = "model.keras"
15
+ # IMPORTANT: Replace "YOUR_USERNAME/garbage-detection-model" with the actual REPO ID of YOUR MODEL on Hugging Face Hub.
16
+ # This is the repository where your 'model.keras' file is stored.
17
+ # Example: "your_huggingface_username/your_model_repo_name"
18
+ MODEL_REPO_ID = "nonamelife/garbage-detection-model" # <--- MAKE SURE THIS IS YOUR CORRECT MODEL REPO ID!
19
+
20
+ model = None # Initialize model as None
21
+
22
+ # --- Model Loading Logic ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
  try:
24
+ print(f"Attempting to download '{MODEL_FILE_NAME}' from Hugging Face Hub ({MODEL_REPO_ID})...")
25
+
26
+ # hf_hub_download returns the FULL PATH to the downloaded file in the cache.
27
+ # We specify local_dir within /app to ensure write permissions and consistency.
28
+ # local_dir_use_symlinks=False is important for Docker environments to avoid symlink issues.
29
+ downloaded_model_path = hf_hub_download(
30
+ repo_id=MODEL_REPO_ID,
31
+ filename=MODEL_FILE_NAME,
32
+ local_dir="/app/.cache/huggingface/models", # This directory will be created if it doesn't exist
33
+ local_dir_use_symlinks=False
34
+ )
35
+
36
+ print(f"'{MODEL_FILE_NAME}' downloaded successfully to: {downloaded_model_path}")
37
+
38
+ # Now, load the model directly from the downloaded path.
39
+ # This check is a safeguard, as hf_hub_download should ensure existence.
40
+ if os.path.exists(downloaded_model_path):
41
+ model = tf.keras.models.load_model(downloaded_model_path)
42
+ print("Model loaded successfully!")
43
  else:
44
+ # This message indicates a very unusual state if download was reported successful.
45
+ print(f"ERROR: Download reported success, but file not found at expected path: {downloaded_model_path}")
46
+
47
  except Exception as e:
48
+ # Catch any exceptions during download or loading and log them.
49
+ print(f"FATAL: Could not download or load model from Hugging Face Hub: {e}")
50
+ model = None # Ensure model remains None if there's an error
51
+
52
+ # --- End Model Loading Logic ---
53
+
54
 
55
+ # Configurations for Flask app
56
  UPLOAD_FOLDER = os.path.join('static', 'uploads')
57
  ALLOWED_EXTENSIONS = {'jpg', 'jpeg', 'png'}
58
  app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
59
+ # Ensure the uploads directory exists within the container
60
+ os.makedirs(UPLOAD_FOLDER, exist_ok=True)
61
 
62
  def allowed_file(filename):
63
+ """Checks if the uploaded file has an allowed extension."""
64
+ return '.' in filename and \
65
+ filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
66
 
67
  def preprocess_image(image_path):
68
+ """Loads and preprocesses an image for model prediction."""
69
+ img = load_img(image_path, target_size=(224, 224)) # Load image, resize to 224x224
70
+ img_array = img_to_array(img) / 255.0 # Convert to array and normalize pixel values
71
+ return np.expand_dims(img_array, axis=0) # Add batch dimension for model input
72
 
73
+ # --- Flask Routes ---
74
  @app.route('/')
75
  def index():
76
+ """Renders the home page."""
77
  return render_template('home.html')
78
 
79
  @app.route('/tool')
80
  def tool():
81
+ """Renders the image upload tool page."""
82
  return render_template('tool.html')
83
 
84
  @app.route('/about')
85
  def about():
86
+ """Renders the about page."""
87
  return render_template('about.html')
88
 
89
  @app.route('/contact')
90
  def contact():
91
+ """Renders the contact page."""
92
  return render_template('contact.html')
93
 
94
  @app.route('/predict', methods=['POST'])
95
  def predict():
96
+ """Handles image uploads and returns predictions."""
97
+ # Check if the model was loaded successfully at startup
98
  if model is None:
99
  return jsonify({'error': 'Model not loaded. Please check server logs.'}), 500
100
 
101
+ # Check if a file was part of the request
102
  if 'file' not in request.files:
103
  return jsonify({'error': 'No files uploaded'}), 400
104
 
 
110
  for file in files:
111
  file_path = None
112
  if file and allowed_file(file.filename):
113
+ # Secure filename and create a unique name to prevent collisions
114
  filename = secure_filename(file.filename)
115
  timestamp = datetime.now().strftime("%Y%m%d%H%M%S%f")
116
  unique_filename = f"{timestamp}_{filename}"
117
  file_path = os.path.join(app.config['UPLOAD_FOLDER'], unique_filename)
118
+ file.save(file_path) # Save the uploaded file temporarily
119
 
120
  try:
121
+ img_array = preprocess_image(file_path) # Preprocess the image
122
+ prediction = model.predict(img_array)[0][0] # Get prediction from the model
123
+
124
+ # Determine label and confidence based on sigmoid output
125
  label = "Dirty" if prediction > 0.5 else "Clean"
126
  confidence = prediction if label == "Dirty" else 1 - prediction
127
 
128
  results.append({
129
  'label': label,
130
+ 'confidence': f"{confidence:.2%}", # Format confidence as percentage
131
+ 'image_url': f"/static/uploads/{unique_filename}" # URL for displaying the image
132
  })
133
  except Exception as e:
134
+ # Catch any errors during prediction or processing
135
  results.append({
136
  'label': 'Error',
137
  'confidence': 'N/A',
 
139
  'error': str(e)
140
  })
141
  finally:
142
+ # Clean up: delete the temporary uploaded file
143
  if file_path and os.path.exists(file_path):
144
  try:
145
  os.remove(file_path)
 
147
  except Exception as e:
148
  print(f"Error deleting file {file_path}: {e}")
149
  else:
150
+ # Handle invalid file types
151
  results.append({
152
  'label': 'Error',
153
  'confidence': 'N/A',
 
155
  'error': f"Invalid file type: {file.filename}"
156
  })
157
 
158
+ # Render the results page with predictions
159
  return render_template('results.html', results=results)
160
 
161
+ # --- Main execution block ---
162
  if __name__ == '__main__':
163
+ # Hugging Face Spaces sets the PORT environment variable for the app to listen on.
164
+ # We default to 7860 as it's common for HF Spaces apps.
165
+ # Debug mode should be OFF for production deployments (like Hugging Face Spaces) for security.
166
  port = int(os.environ.get('PORT', 7860))
167
+ app.run(host='0.0.0.0', port=port, debug=False)