MahmoudNabilMohamed's picture
Update app.py
c005998 verified
import os
import numpy as np
import requests
from flask import Flask, request, jsonify, send_file
from werkzeug.utils import secure_filename
import onnxruntime
from PIL import Image
import io
import base64
import logging
# ุฅุนุฏุงุฏ ุงู„ุชุณุฌูŠู„
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB max file size
# ุชุญุฏูŠุซ ุงู„ู…ุณุงุฑุงุช ู„ู„ุนู…ู„ ููŠ Codespaces
# MODEL_URL = "https://huggingface.co/skytnt/anime-seg/resolve/main/isnetis.onnx"
MODEL_URL = "https://huggingface.co/briaai/RMBG-1.4/resolve/main/onnx/model_fp16.onnx?download=true"
MODEL_PATH = "isnetis.onnx"
UPLOAD_FOLDER = "uploads"
RESULT_FOLDER = "results"
# ุฅู†ุดุงุก ุงู„ู…ุฌู„ุฏุงุช
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
os.makedirs(RESULT_FOLDER, exist_ok=True)
class BackgroundRemover:
def __init__(self):
self.session = None
self.input_name = None
self.output_name = None
def download_model(self):
if os.path.exists(MODEL_PATH):
logger.info("โœ… Model already exists, skipping download")
return True
try:
logger.info("๐Ÿ“ฅ Downloading model from HuggingFace...")
response = requests.get(MODEL_URL, stream=True)
response.raise_for_status()
total_size = int(response.headers.get('content-length', 0))
downloaded = 0
with open(MODEL_PATH, 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
if chunk:
f.write(chunk)
downloaded += len(chunk)
if total_size > 0:
progress = (downloaded / total_size) * 100
print(f"\r๐Ÿ“ฅ Downloading: {progress:.1f}%", end="", flush=True)
print() # ุณุทุฑ ุฌุฏูŠุฏ
logger.info("โœ… Model downloaded successfully")
return True
except Exception as e:
logger.error(f"โŒ Failed to download model: {e}")
return False
def load_model(self):
try:
logger.info("๐Ÿ”„ Loading ONNX model...")
providers = ['CPUExecutionProvider']
# ุงู„ุชุญู‚ู‚ ู…ู† ุฏุนู… GPU (ุงุฎุชูŠุงุฑูŠ)
try:
available_providers = onnxruntime.get_available_providers()
if 'CUDAExecutionProvider' in available_providers:
providers.insert(0, 'CUDAExecutionProvider')
logger.info("๐Ÿš€ CUDA provider available")
else:
logger.info("๐Ÿ’ป Using CPU provider")
except:
logger.info("๐Ÿ’ป Using CPU provider")
self.session = onnxruntime.InferenceSession(MODEL_PATH, providers=providers)
self.input_name = self.session.get_inputs()[0].name
self.output_name = self.session.get_outputs()[0].name
logger.info(f"โœ… Model loaded successfully")
logger.info(f"๐Ÿ“Š Input: {self.input_name}, Output: {self.output_name}")
return True
except Exception as e:
logger.error(f"โŒ Failed to load model: {e}")
return False
def preprocess_image(self, image):
original_size = image.size
image = image.convert('RGB')
image = image.resize((1024, 1024), Image.LANCZOS)
image_array = np.array(image).astype(np.float32)
image_array = image_array / 255.0
image_array = np.transpose(image_array, (2, 0, 1))
image_array = np.expand_dims(image_array, axis=0)
return image_array, original_size
def postprocess_mask(self, mask, original_size):
mask = mask.squeeze()
mask = (mask * 255).astype(np.uint8)
mask = Image.fromarray(mask, mode='L')
mask = mask.resize(original_size, Image.LANCZOS)
return mask
def remove_background(self, image_path):
try:
logger.info(f"๐Ÿ–ผ๏ธ Processing image: {image_path}")
image = Image.open(image_path)
preprocessed, original_size = self.preprocess_image(image)
logger.info("๐Ÿค– Running AI inference...")
mask = self.session.run([self.output_name], {self.input_name: preprocessed})[0]
mask = self.postprocess_mask(mask, original_size)
logger.info("โœ‚๏ธ Applying mask to remove background...")
image = image.convert('RGBA')
image.putalpha(mask)
logger.info("โœ… Background removed successfully")
return image
except Exception as e:
logger.error(f"โŒ Failed to remove background: {e}")
return None
# ุฅู†ุดุงุก ูƒุงุฆู† ุฅุฒุงู„ุฉ ุงู„ุฎู„ููŠุฉ
background_remover = BackgroundRemover()
@app.route('/', methods=['GET'])
def health_check():
"""ูุญุต ุตุญุฉ ุงู„ุณูŠุฑูุฑ"""
return jsonify({
'status': 'โœ… Server is running',
'model_loaded': background_remover.session is not None,
'endpoints': {
'health_check': '/ (GET)',
'remove_background': '/remove-background (POST)'
},
'info': 'Background Remover API - Ready to use!'
})
@app.route('/remove-background', methods=['POST'])
def remove_background_endpoint():
"""ุฅุฒุงู„ุฉ ุฎู„ููŠุฉ ุงู„ุตูˆุฑุฉ"""
try:
# ุงู„ุชุญู‚ู‚ ู…ู† ูˆุฌูˆุฏ ุงู„ู…ู„ู
if 'file' not in request.files:
return jsonify({'error': 'No file uploaded'}), 400
file = request.files['file']
if file.filename == '':
return jsonify({'error': 'No file selected'}), 400
# ุงู„ุชุญู‚ู‚ ู…ู† ู†ูˆุน ุงู„ู…ู„ู
if not file.content_type.startswith('image/'):
return jsonify({'error': 'File must be an image'}), 400
# ุญูุธ ุงู„ู…ู„ู
filename = secure_filename(file.filename)
filepath = os.path.join(UPLOAD_FOLDER, filename)
file.save(filepath)
logger.info(f"๐Ÿ“‚ File saved: {filepath}")
# ู…ุนุงู„ุฌุฉ ุงู„ุตูˆุฑุฉ
result = background_remover.remove_background(filepath)
if result is None:
os.remove(filepath) # ุญุฐู ุงู„ู…ู„ู ููŠ ุญุงู„ุฉ ุงู„ูุดู„
return jsonify({'error': 'Failed to process image'}), 500
# ุญูุธ ุงู„ู†ุชูŠุฌุฉ
result_filename = f"result_{filename.rsplit('.', 1)[0]}.png"
result_path = os.path.join(RESULT_FOLDER, result_filename)
result.save(result_path, 'PNG')
# ุญุฐู ุงู„ู…ู„ู ุงู„ุฃุตู„ูŠ
os.remove(filepath)
logger.info(f"โœ… Result saved: {result_path}")
return send_file(result_path, mimetype='image/png', as_attachment=False)
except Exception as e:
logger.error(f"โŒ Error in remove_background_endpoint: {e}")
return jsonify({'error': 'Internal server error'}), 500
if __name__ == '__main__':
print("=" * 60)
print("๐ŸŽฏ Background Remover API Server")
print("=" * 60)
logger.info("๐Ÿš€ Starting Background Remover Server...")
# ุชุญู…ูŠู„ ูˆุชุดุบูŠู„ ุงู„ู†ู…ูˆุฐุฌ
if not background_remover.download_model():
logger.error("โŒ Failed to download model. Exiting...")
exit(1)
if not background_remover.load_model():
logger.error("โŒ Failed to load model. Exiting...")
exit(1)
# ุฅุนุฏุงุฏ ุงู„ู…ู†ูุฐ
if __name__ == '__main__':
if not background_remover.download_model():
exit(1)
if not background_remover.load_model():
exit(1)
# Hugging Face Spaces ูŠุณุชุฎุฏู… ุงู„ู…ู†ูุฐ 7860
port = int(os.environ.get('PORT', 7860))
print(f'๐Ÿ“ก Running on port: {port}')
print(f'๐ŸŒ Local URL: http://localhost:{port}')
print(f'๐Ÿ” Health check: http://localhost:{port}/')
print(f'๐Ÿ“ฑ API endpoint: http://localhost:{port}/remove-background')
print('=' * 60)
app.run(host='0.0.0.0', port=port, debug=False)