import gradio as gr import numpy as np import cv2 import os import time import requests import sys from PIL import Image # ─── FIX FOR BASICSR & TORCHVISION ──────────────────────────────────────────── import torchvision.transforms.functional sys.modules['torchvision.transforms.functional_tensor'] = torchvision.transforms.functional # ────────────────────────────────────────────────────────────────────────────── # ─── Model Download ─────────────────────────────────────────────────────────── MODEL_DIR = "weights" MODEL_PATH = os.path.join(MODEL_DIR, "RealESRGAN_x4plus.pth") MODEL_URL = "https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth" def download_model(): os.makedirs(MODEL_DIR, exist_ok=True) if not os.path.exists(MODEL_PATH): print("📥 মডেল ডাউনলোড হচ্ছে...") r = requests.get(MODEL_URL, stream=True) with open(MODEL_PATH, "wb") as f: for chunk in r.iter_content(chunk_size=8192): f.write(chunk) print("✅ মডেল ডাউনলোড সম্পন্ন!") download_model() # ─── Real-ESRGAN Setup ──────────────────────────────────────────────────────── from basicsr.archs.rrdbnet_arch import RRDBNet from realesrgan import RealESRGANer def load_upsampler(): model = RRDBNet( num_in_ch=3, num_out_ch=3, num_feat=64, num_block=23, num_grow_ch=32, scale=4 ) upsampler = RealESRGANer( scale=4, model_path=MODEL_PATH, model=model, tile=128, tile_pad=10, pre_pad=0, half=False ) return upsampler print("🔄 মডেল লোড হচ্ছে...") upsampler = load_upsampler() print("✅ মডেল রেডি!") # ─── Image Analysis ─────────────────────────────────────────────────────────── def analyze_image(img: Image.Image) -> dict: w, h = img.size mp = (w * h) / 1_000_000 if w >= 3840 or h >= 2160: quality_label = "4K বা তার বেশি (Ultra HD)" quality_icon = "🟣" elif w >= 1920 or h >= 1080: quality_label = "1080p Full HD" quality_icon = "🟢" elif w >= 1280 or h >= 720: quality_label = "720p HD" quality_icon = "🟡" elif w >= 854 or h >= 480: quality_label = "480p SD" quality_icon = "🟠" else: quality_label = "লো রেজোলিউশন" quality_icon = "🔴" mode_label = {"RGB": "রঙিন (RGB)", "RGBA": "রঙিন + Transparency", "L": "কালো-সাদা"}.get(img.mode, img.mode) return { "width": w, "height": h, "megapixels": round(mp, 2), "quality_label": quality_label, "quality_icon": quality_icon, "mode": mode_label, "target_w": 3840, "target_h": 2160 } # ─── Main Processing ────────────────────────────────────────────────────────── def upscale_to_4k(pil_img): if pil_img is None: yield None, "❌ কোনো ছবি আপলোড করা হয়নি।", None, "" return t_start = time.time() yield None, "🔍 **ছবি বিশ্লেষণ হচ্ছে...**", None, "⏳ প্রসেসিং শুরু হয়েছে" time.sleep(0.3) pil_img = pil_img.convert("RGB") info = analyze_image(pil_img) analysis_text = f""" ## 📊 ছবি বিশ্লেষণ ফলাফল | তথ্য | মান | | :--- | :--- | | {info['quality_icon']} বর্তমান কোয়ালিটি | **{info['quality_label']}** | | 📐 বর্তমান রেজোলিউশন | **{info['width']} × {info['height']} px** | | 📷 মেগাপিক্সেল | **{info['megapixels']} MP** | | 🎯 টার্গেট রেজোলিউশন | **3840 × 2160 (4K)** | --- ⚡ **AI Upscaling শুরু হচ্ছে (১-২ মিনিট সময় দিন)...** """ yield None, analysis_text, None, "🔄 AI প্রসেসিং চলছে..." img_np = np.array(pil_img) img_bgr = cv2.cvtColor(img_np, cv2.COLOR_RGB2BGR) try: output_bgr, _ = upsampler.enhance(img_bgr, outscale=4) except Exception as e: yield None, f"❌ **এরর:** সার্ভার ওভারলোড হয়েছে, আবার চেষ্টা করুন।", None, "❌ ব্যর্থ হয়েছে" return output_rgb = cv2.cvtColor(output_bgr, cv2.COLOR_BGR2RGB) output_pil = Image.fromarray(output_rgb) out_w, out_h = output_pil.size if out_w != 3840 or out_h != 2160: output_pil = output_pil.resize((3840, 2160), Image.LANCZOS) t_end = time.time() elapsed = t_end - t_start mins = int(elapsed // 60) secs = int(elapsed % 60) time_str = f"{mins} মিনিট {secs} সেকেন্ড" if mins > 0 else f"{secs} সেকেন্ড" out_path = "/tmp/4k_output.png" output_pil.save(out_path, "PNG", optimize=False) file_size_mb = os.path.getsize(out_path) / (1024 * 1024) result_text = f""" ## ✅ 4K Upscaling সম্পন্ন! | ফলাফল | মান | | :--- | :--- | | 🎯 আউটপুট রেজোলিউশন | **3840 × 2160 (4K Ultra HD)** | | 📁 ফাইল সাইজ | **{file_size_mb:.1f} MB** | | ⏱️ সময় লেগেছে | **{time_str}** | | ✨ আপস্কেল রেশিও | **অটোম্যাটিক 4K এনালাইসিস** | | 🧠 মডেল | **Real-ESRGAN x4plus** | --- 💾 নিচের ছবিতে রাইট ক্লিক করে **"Save Image"** দিয়ে ডাউনলোড করুন অথবা ডাউনলোড বাটনে চাপুন। """ time_display = f"✅ {time_str} এ সম্পন্ন | 3840×2160 (4K)" yield output_pil, result_text, out_path, time_display # ─── Custom CSS ─────────────────────────────────────────────────────────────── CSS = """ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&display=swap'); * { font-family: 'Inter', sans-serif; box-sizing: border-box; } body, .gradio-container { background: #0a0a0f !important; color: #e8e8f0 !important; } .gradio-container { max-width: 1100px !important; margin: 0 auto !important; padding: 20px !important; } #header { text-align: center; padding: 40px 20px 30px; background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%); border-radius: 20px; margin-bottom: 24px; border: 1px solid #2a2a4a; } #header h1 { font-size: 2.8rem; font-weight: 700; background: linear-gradient(90deg, #00d4ff, #7b2ff7, #ff6b6b); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin: 0 0 10px; } #header p { color: #8888aa; font-size: 1.05rem; margin: 0; } .badge-row { display: flex; justify-content: center; gap: 12px; flex-wrap: wrap; margin-top: 16px; } .badge { background: rgba(0,212,255,0.1); border: 1px solid rgba(0,212,255,0.3); color: #00d4ff; padding: 5px 14px; border-radius: 20px; font-size: 0.82rem; font-weight: 600; } #timer-box { background: linear-gradient(135deg, #1a1a2e, #0f1923); border: 1px solid #2a3a5a; border-radius: 14px; padding: 16px 24px; text-align: center; font-size: 1.1rem; font-weight: 600; color: #00d4ff; margin-bottom: 16px; min-height: 54px; display: flex; align-items: center; justify-content: center; } .upload-zone label { font-size: 1rem !important; font-weight: 600 !important; color: #aaaacc !important; } #upscale-btn { background: linear-gradient(135deg, #7b2ff7, #00d4ff) !important; border: none !important; color: white !important; font-size: 1.1rem !important; font-weight: 700 !important; padding: 14px 32px !important; border-radius: 12px !important; cursor: pointer !important; transition: all 0.3s !important; width: 100% !important; letter-spacing: 0.5px !important; } #upscale-btn:hover { transform: translateY(-2px) !important; box-shadow: 0 8px 30px rgba(123,47,247,0.5) !important; } .panel { background: #111122 !important; border: 1px solid #2a2a4a !important; border-radius: 16px !important; padding: 20px !important; } .result-markdown { background: #0d0d1f !important; border-radius: 12px; padding: 16px; } footer { display: none !important; } """ # ─── UI Layout ──────────────────────────────────────────────────────────────── with gr.Blocks(css=CSS, title="4K AI Upscaler") as demo: gr.HTML("""
যেকোনো ছবি আপলোড করুন — AI স্বয়ংক্রিয়ভাবে বিশ্লেষণ করে ৪K Ultra HD তে রূপান্তর করবে