Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,47 +1,111 @@
|
|
| 1 |
# app.py
|
| 2 |
import os
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
from flask import Flask, render_template, request, jsonify
|
| 4 |
import base64
|
| 5 |
-
from rembg import remove # Import the remove function from rembg
|
| 6 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
app = Flask(__name__)
|
|
|
|
|
|
|
| 8 |
|
| 9 |
@app.route('/')
|
| 10 |
def index():
|
| 11 |
# Render the main HTML page
|
|
|
|
|
|
|
| 12 |
return render_template('index.html')
|
| 13 |
|
| 14 |
@app.route('/upload', methods=['POST'])
|
| 15 |
def upload_file():
|
|
|
|
|
|
|
| 16 |
# Check if an image file is uploaded in the request
|
| 17 |
if 'image' not in request.files:
|
|
|
|
|
|
|
| 18 |
return jsonify({'error': 'No image part in the request'}), 400
|
| 19 |
|
| 20 |
uploaded_file = request.files['image']
|
| 21 |
|
| 22 |
# Check if the filename is empty (no file selected)
|
| 23 |
if uploaded_file.filename == '':
|
|
|
|
|
|
|
| 24 |
return jsonify({'error': 'No image selected'}), 400
|
| 25 |
|
| 26 |
# Check if the file object itself exists
|
| 27 |
if not uploaded_file:
|
| 28 |
-
|
|
|
|
|
|
|
| 29 |
|
|
|
|
|
|
|
| 30 |
try:
|
| 31 |
# Read the uploaded image file bytes
|
| 32 |
input_image_bytes = uploaded_file.read()
|
|
|
|
|
|
|
| 33 |
|
| 34 |
# Use rembg to remove the background
|
| 35 |
-
|
|
|
|
| 36 |
output_image_bytes = remove(input_image_bytes)
|
|
|
|
|
|
|
| 37 |
|
| 38 |
# Convert the original image and background-removed image to base64
|
|
|
|
|
|
|
| 39 |
original_image_base64 = base64.b64encode(input_image_bytes).decode('utf-8')
|
| 40 |
modified_image_base64 = base64.b64encode(output_image_bytes).decode('utf-8')
|
|
|
|
|
|
|
| 41 |
|
| 42 |
# Return the images as JSON to the frontend
|
| 43 |
# Ensure the data URI format is correct (it needs image type, e.g., image/png)
|
| 44 |
# rembg typically outputs PNG
|
|
|
|
|
|
|
| 45 |
return jsonify({
|
| 46 |
'original_image': f'data:image/png;base64,{original_image_base64}',
|
| 47 |
'background_removed_image': f'data:image/png;base64,{modified_image_base64}'
|
|
@@ -49,12 +113,17 @@ def upload_file():
|
|
| 49 |
|
| 50 |
except Exception as e:
|
| 51 |
# Log the exception for debugging
|
| 52 |
-
print(f"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
# Return a generic error message to the user
|
| 54 |
return jsonify({'error': f'Failed to process image: {str(e)}'}), 500
|
| 55 |
|
| 56 |
-
# Keep the __main__ block for running locally
|
| 57 |
if __name__ == '__main__':
|
| 58 |
-
|
| 59 |
-
# debug=True
|
| 60 |
-
|
|
|
|
|
|
| 1 |
# app.py
|
| 2 |
import os
|
| 3 |
+
import sys # Import sys to print to stderr for logging
|
| 4 |
+
import traceback # Import traceback for detailed error printing
|
| 5 |
+
|
| 6 |
+
# <<< Force disable Numba cache BEFORE any imports that might use it >>>
|
| 7 |
+
# Printing to stderr ensures it shows up in container logs easily
|
| 8 |
+
print("----------------------------------------------------------", file=sys.stderr)
|
| 9 |
+
print("Attempting to set NUMBA_DISABLE_CACHE=1", file=sys.stderr)
|
| 10 |
+
os.environ['NUMBA_DISABLE_CACHE'] = '1'
|
| 11 |
+
# <<< Verify it was set (check logs for this output) >>>
|
| 12 |
+
numba_cache_status = os.getenv('NUMBA_DISABLE_CACHE')
|
| 13 |
+
print(f"NUMBA_DISABLE_CACHE is now set to: {numba_cache_status}", file=sys.stderr)
|
| 14 |
+
if numba_cache_status != '1':
|
| 15 |
+
print("WARNING: NUMBA_DISABLE_CACHE was not set correctly!", file=sys.stderr)
|
| 16 |
+
print("----------------------------------------------------------", file=sys.stderr)
|
| 17 |
+
|
| 18 |
+
# Now proceed with other imports
|
| 19 |
+
print("Importing Flask, base64...", file=sys.stderr)
|
| 20 |
from flask import Flask, render_template, request, jsonify
|
| 21 |
import base64
|
|
|
|
| 22 |
|
| 23 |
+
# Try importing rembg with detailed logging
|
| 24 |
+
try:
|
| 25 |
+
print("Attempting to import rembg...", file=sys.stderr)
|
| 26 |
+
# Flush output buffer to ensure messages appear in order
|
| 27 |
+
sys.stderr.flush()
|
| 28 |
+
from rembg import remove # Import the remove function from rembg
|
| 29 |
+
print("Imported rembg successfully.", file=sys.stderr)
|
| 30 |
+
sys.stderr.flush()
|
| 31 |
+
except ImportError as e:
|
| 32 |
+
# Catch ImportError specifically if rembg isn't found
|
| 33 |
+
print(f"FATAL: Could not import rembg: {e}", file=sys.stderr)
|
| 34 |
+
print("Please check installation and dependencies in requirements.txt.", file=sys.stderr)
|
| 35 |
+
sys.stderr.flush()
|
| 36 |
+
raise # Re-raise to stop execution clearly
|
| 37 |
+
except Exception as e:
|
| 38 |
+
# Catch other potential exceptions during import (like the Numba error)
|
| 39 |
+
print(f"ERROR during import process (likely rembg or its dependency): {e}", file=sys.stderr)
|
| 40 |
+
# Print the full traceback for detailed debugging
|
| 41 |
+
traceback.print_exc(file=sys.stderr)
|
| 42 |
+
sys.stderr.flush()
|
| 43 |
+
raise # Re-raise the exception to see the full traceback in logs
|
| 44 |
+
|
| 45 |
+
print("Flask app initialization starting...", file=sys.stderr)
|
| 46 |
app = Flask(__name__)
|
| 47 |
+
print("Flask app initialized.", file=sys.stderr)
|
| 48 |
+
sys.stderr.flush()
|
| 49 |
|
| 50 |
@app.route('/')
|
| 51 |
def index():
|
| 52 |
# Render the main HTML page
|
| 53 |
+
print("Serving index page.", file=sys.stderr)
|
| 54 |
+
sys.stderr.flush()
|
| 55 |
return render_template('index.html')
|
| 56 |
|
| 57 |
@app.route('/upload', methods=['POST'])
|
| 58 |
def upload_file():
|
| 59 |
+
print("Received request to /upload", file=sys.stderr)
|
| 60 |
+
sys.stderr.flush()
|
| 61 |
# Check if an image file is uploaded in the request
|
| 62 |
if 'image' not in request.files:
|
| 63 |
+
print("Error: No image part in the request.", file=sys.stderr)
|
| 64 |
+
sys.stderr.flush()
|
| 65 |
return jsonify({'error': 'No image part in the request'}), 400
|
| 66 |
|
| 67 |
uploaded_file = request.files['image']
|
| 68 |
|
| 69 |
# Check if the filename is empty (no file selected)
|
| 70 |
if uploaded_file.filename == '':
|
| 71 |
+
print("Error: No image selected (filename empty).", file=sys.stderr)
|
| 72 |
+
sys.stderr.flush()
|
| 73 |
return jsonify({'error': 'No image selected'}), 400
|
| 74 |
|
| 75 |
# Check if the file object itself exists
|
| 76 |
if not uploaded_file:
|
| 77 |
+
print("Error: Uploaded file object is invalid.", file=sys.stderr)
|
| 78 |
+
sys.stderr.flush()
|
| 79 |
+
return jsonify({'error': 'Image file is invalid'}), 400
|
| 80 |
|
| 81 |
+
print(f"Processing uploaded file: {uploaded_file.filename}", file=sys.stderr)
|
| 82 |
+
sys.stderr.flush()
|
| 83 |
try:
|
| 84 |
# Read the uploaded image file bytes
|
| 85 |
input_image_bytes = uploaded_file.read()
|
| 86 |
+
print(f"Read {len(input_image_bytes)} bytes from image.", file=sys.stderr)
|
| 87 |
+
sys.stderr.flush()
|
| 88 |
|
| 89 |
# Use rembg to remove the background
|
| 90 |
+
print("Calling rembg.remove...", file=sys.stderr)
|
| 91 |
+
sys.stderr.flush()
|
| 92 |
output_image_bytes = remove(input_image_bytes)
|
| 93 |
+
print(f"rembg.remove finished, output size: {len(output_image_bytes)} bytes.", file=sys.stderr)
|
| 94 |
+
sys.stderr.flush()
|
| 95 |
|
| 96 |
# Convert the original image and background-removed image to base64
|
| 97 |
+
print("Encoding images to base64...", file=sys.stderr)
|
| 98 |
+
sys.stderr.flush()
|
| 99 |
original_image_base64 = base64.b64encode(input_image_bytes).decode('utf-8')
|
| 100 |
modified_image_base64 = base64.b64encode(output_image_bytes).decode('utf-8')
|
| 101 |
+
print("Encoding complete.", file=sys.stderr)
|
| 102 |
+
sys.stderr.flush()
|
| 103 |
|
| 104 |
# Return the images as JSON to the frontend
|
| 105 |
# Ensure the data URI format is correct (it needs image type, e.g., image/png)
|
| 106 |
# rembg typically outputs PNG
|
| 107 |
+
print("Returning JSON response.", file=sys.stderr)
|
| 108 |
+
sys.stderr.flush()
|
| 109 |
return jsonify({
|
| 110 |
'original_image': f'data:image/png;base64,{original_image_base64}',
|
| 111 |
'background_removed_image': f'data:image/png;base64,{modified_image_base64}'
|
|
|
|
| 113 |
|
| 114 |
except Exception as e:
|
| 115 |
# Log the exception for debugging
|
| 116 |
+
print(f"ERROR processing image with rembg: {str(e)}", file=sys.stderr)
|
| 117 |
+
print("------------------- Traceback -------------------", file=sys.stderr)
|
| 118 |
+
traceback.print_exc(file=sys.stderr)
|
| 119 |
+
print("-------------------------------------------------", file=sys.stderr)
|
| 120 |
+
sys.stderr.flush()
|
| 121 |
# Return a generic error message to the user
|
| 122 |
return jsonify({'error': f'Failed to process image: {str(e)}'}), 500
|
| 123 |
|
| 124 |
+
# Keep the __main__ block for running locally, but it's not used by Gunicorn
|
| 125 |
if __name__ == '__main__':
|
| 126 |
+
print("Running Flask app directly (for local testing only)...", file=sys.stderr)
|
| 127 |
+
# When run directly, use debug=True for development ease
|
| 128 |
+
# When run with Gunicorn (like in Hugging Face), Gunicorn handles host/port/workers, debug should be False.
|
| 129 |
+
app.run(host='0.0.0.0', port=5000, debug=True)
|