DrAbbas commited on
Commit
a67e140
ยท
verified ยท
1 Parent(s): 62ad3c0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +237 -0
app.py CHANGED
@@ -908,6 +908,192 @@ def apply_brightness(img):
908
  return Image.fromarray(arr)
909
 
910
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
911
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
912
  # ๐Ÿ“ก ุฑุจุท ู‚ุงุนุฏุฉ ุงู„ุจูŠุงู†ุงุช ุนุจุฑ API
913
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•๏ฟฝ๏ฟฝโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
@@ -2071,6 +2257,57 @@ with gr.Blocks(title=f"SONAR-AI v{VERSION}") as app:
2071
  p_btn.click(physics_analyze, inputs=[p_img], outputs=[p_res, p_tbl])
2072
 
2073
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2074
  with gr.Tab("๐Ÿท๏ธ ู‚ุงุนุฏุฉ ุงู„ุฃุตู†ุงู"):
2075
  gr.HTML(f"<div style='background:#E8F5E9;padding:10px 14px;border-radius:10px;margin-bottom:8px;border-right:4px solid #2E7D32;'><b style='color:#2E7D32;'>๐Ÿ“ฆ {len(CARGO_DATABASE)} ุตู†ู</b></div>")
2076
  cats = gr.Dataframe(value=get_categories())
 
908
  return Image.fromarray(arr)
909
 
910
 
911
+
912
+
913
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
914
+ # ๐Ÿง  AI Image Enhancement Engine
915
+ # Real-ESRGAN + GPU Neural + OpenCV Advanced
916
+ # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
917
+
918
+ ESRGAN_MODEL = None
919
+ AI_ENHANCE_READY = False
920
+
921
+ def load_ai_enhance_models():
922
+ global ESRGAN_MODEL, AI_ENHANCE_READY
923
+ if AI_ENHANCE_READY:
924
+ return True
925
+ try:
926
+ from basicsr.archs.rrdbnet_arch import RRDBNet
927
+ from realesrgan import RealESRGANer
928
+ model_path = None
929
+ for p in ["RealESRGAN_x2plus.pth", "weights/RealESRGAN_x2plus.pth", "/app/RealESRGAN_x2plus.pth"]:
930
+ if os.path.exists(p):
931
+ model_path = p; break
932
+ if model_path is None:
933
+ try:
934
+ from huggingface_hub import hf_hub_download
935
+ model_path = hf_hub_download(repo_id="ai-forever/Real-ESRGAN", filename="RealESRGAN_x2.pth")
936
+ print("๐Ÿ“ฅ Downloaded Real-ESRGAN from HF Hub")
937
+ except:
938
+ try:
939
+ model_path = hf_hub_download(repo_id="sberbank-ai/Real-ESRGAN", filename="RealESRGAN_x2.pth")
940
+ except Exception as e:
941
+ print(f"โš ๏ธ Real-ESRGAN download failed: {e}")
942
+ if model_path:
943
+ esrgan_net = RRDBNet(num_in_ch=3, num_out_ch=3, num_feat=64, num_block=23, num_grow_ch=32, scale=2)
944
+ ESRGAN_MODEL = RealESRGANer(scale=2, model_path=model_path, model=esrgan_net,
945
+ tile=384, tile_pad=10, pre_pad=0, half=True if USE_GPU else False,
946
+ device=DEVICE if torch is not None else 'cpu')
947
+ print("โœ… Real-ESRGAN loaded (x2, tile=384)")
948
+ except ImportError:
949
+ print("โš ๏ธ Real-ESRGAN not installed (pip install realesrgan basicsr)")
950
+ except Exception as e:
951
+ print(f"โš ๏ธ Real-ESRGAN error: {e}")
952
+ AI_ENHANCE_READY = True
953
+ return ESRGAN_MODEL is not None
954
+
955
+ def ai_enhance_esrgan(img, scale=2):
956
+ if img is None: return None
957
+ load_ai_enhance_models()
958
+ if ESRGAN_MODEL is None: return None
959
+ try:
960
+ import cv2
961
+ img_bgr = cv2.cvtColor(np.array(img.convert('RGB')), cv2.COLOR_RGB2BGR)
962
+ output, _ = ESRGAN_MODEL.enhance(img_bgr, outscale=scale)
963
+ return Image.fromarray(cv2.cvtColor(output, cv2.COLOR_BGR2RGB))
964
+ except Exception as e:
965
+ print(f"โš ๏ธ ESRGAN: {e}"); return None
966
+
967
+ def ai_enhance_clahe_adv(img):
968
+ if img is None: return None
969
+ try:
970
+ import cv2
971
+ arr = np.array(img.convert('RGB'))
972
+ lab = cv2.cvtColor(arr, cv2.COLOR_RGB2LAB)
973
+ l, a, b = cv2.split(lab)
974
+ l = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8)).apply(l)
975
+ return Image.fromarray(cv2.cvtColor(cv2.merge([l,a,b]), cv2.COLOR_LAB2RGB))
976
+ except Exception as e:
977
+ print(f"โš ๏ธ CLAHE: {e}"); return None
978
+
979
+ def ai_enhance_histeq(img):
980
+ if img is None: return None
981
+ try:
982
+ import cv2
983
+ arr = np.array(img.convert('RGB'))
984
+ ycrcb = cv2.cvtColor(arr, cv2.COLOR_RGB2YCrCb)
985
+ ycrcb[:,:,0] = cv2.equalizeHist(ycrcb[:,:,0])
986
+ return Image.fromarray(cv2.cvtColor(ycrcb, cv2.COLOR_YCrCb2RGB))
987
+ except Exception as e:
988
+ print(f"โš ๏ธ HistEQ: {e}"); return None
989
+
990
+ def ai_enhance_sharpen(img):
991
+ if img is None: return None
992
+ try:
993
+ import cv2
994
+ arr = np.array(img.convert('RGB'))
995
+ denoised = cv2.fastNlMeansDenoisingColored(arr, None, 8, 8, 7, 21)
996
+ kernel = np.array([[-1,-1,-1],[-1,9.5,-1],[-1,-1,-1]])
997
+ return Image.fromarray(cv2.filter2D(denoised, -1, kernel))
998
+ except Exception as e:
999
+ print(f"โš ๏ธ Sharpen: {e}"); return None
1000
+
1001
+ def ai_enhance_combined(img):
1002
+ if img is None: return None
1003
+ try:
1004
+ import cv2
1005
+ arr = np.array(img.convert('RGB'))
1006
+ denoised = cv2.fastNlMeansDenoisingColored(arr, None, 6, 6, 7, 21)
1007
+ lab = cv2.cvtColor(denoised, cv2.COLOR_RGB2LAB)
1008
+ l, a, b = cv2.split(lab)
1009
+ l = cv2.createCLAHE(clipLimit=2.5, tileGridSize=(8,8)).apply(l)
1010
+ enhanced = cv2.cvtColor(cv2.merge([l,a,b]), cv2.COLOR_LAB2RGB)
1011
+ kernel = np.array([[0,-0.5,0],[-0.5,3,-0.5],[0,-0.5,0]])
1012
+ return Image.fromarray(np.clip(cv2.filter2D(enhanced, -1, kernel), 0, 255).astype(np.uint8))
1013
+ except Exception as e:
1014
+ print(f"โš ๏ธ Combined: {e}"); return None
1015
+
1016
+ def ai_enhance_gpu_neural(img):
1017
+ if img is None or torch is None: return None
1018
+ try:
1019
+ arr = np.array(img.convert('RGB')).astype(np.float32) / 255.0
1020
+ t = torch.from_numpy(arr.transpose(2,0,1)).unsqueeze(0).to(DEVICE)
1021
+ enhanced = t.clone()
1022
+ for ks in [3, 5, 9]:
1023
+ pad = ks // 2
1024
+ blurred = torch.nn.functional.avg_pool2d(
1025
+ torch.nn.functional.pad(t, (pad,pad,pad,pad), mode='reflect'), ks, 1)
1026
+ enhanced = enhanced + 0.3 * (t - blurred)
1027
+ enhanced = torch.clamp(enhanced, 0, 1)
1028
+ result = enhanced.squeeze(0).cpu().numpy().transpose(1,2,0)
1029
+ return Image.fromarray((result * 255).clip(0,255).astype(np.uint8))
1030
+ except Exception as e:
1031
+ print(f"โš ๏ธ GPU Neural: {e}"); return None
1032
+
1033
+ def ai_enhance_all(img):
1034
+ if img is None:
1035
+ empty = "<div style='text-align:center;padding:60px;color:#999;direction:rtl;'>"
1036
+ empty += "<div style='font-size:48px;'>๐Ÿง </div>"
1037
+ empty += "<div>ุงุฑูุน ุตูˆุฑุฉ ุณูˆู†ุงุฑ ู„ู„ุชุญุณูŠู† ุจุงู„ุฐูƒุงุก ุงู„ุงุตุทู†ุงุนูŠ</div></div>"
1038
+ return empty, None, None, None, None, None, None
1039
+ start = time_module.time()
1040
+ w_orig, h_orig = img.size
1041
+ results = {}; timings = {}
1042
+ techniques = [
1043
+ ("clahe", "๐Ÿ”† CLAHE Advanced", ai_enhance_clahe_adv),
1044
+ ("histeq", "๐Ÿ“Š Histogram EQ", ai_enhance_histeq),
1045
+ ("sharpen", "โšก Sharpen + Denoise", ai_enhance_sharpen),
1046
+ ("combined", "๐Ÿ† Combined Best", ai_enhance_combined),
1047
+ ("esrgan", "๐Ÿ”ฌ Real-ESRGAN x2", ai_enhance_esrgan),
1048
+ ("neural", "๐ŸŒŠ GPU Neural", ai_enhance_gpu_neural),
1049
+ ]
1050
+ for key, name, func in techniques:
1051
+ t0 = time_module.time()
1052
+ try:
1053
+ result = func(img)
1054
+ if result is not None:
1055
+ results[key] = result; timings[key] = time_module.time() - t0
1056
+ else: timings[key] = -1
1057
+ except Exception as e:
1058
+ print(f"โš ๏ธ {key}: {e}"); timings[key] = -1
1059
+ elapsed = time_module.time() - start
1060
+ n_ok = sum(1 for v in timings.values() if v >= 0)
1061
+ html = "<div style='font-family:Tajawal,sans-serif;direction:rtl;'>"
1062
+ html += "<div style='background:linear-gradient(135deg,#1a237e,#4A148C);padding:14px;border-radius:12px;text-align:center;color:white;margin-bottom:10px;'>"
1063
+ html += f"<div style='font-size:16px;font-weight:bold;'>๐Ÿง  ุชุญุณูŠู† ุจุงู„ุฐูƒุงุก ุงู„ุงุตุทู†ุงุนูŠ โ€” {n_ok}/{len(techniques)} ุชู‚ู†ูŠุงุช ู†ุฌุญุช</div>"
1064
+ html += f"<div style='font-size:12px;opacity:0.8;'>ุงู„ุตูˆุฑุฉ: {w_orig}ร—{h_orig} | ุงู„ูˆู‚ุช: {elapsed:.1f}s | {'โœ… ESRGAN' if 'esrgan' in results else 'โŒ ESRGAN'} | {'โœ… GPU' if 'neural' in results else 'โŒ GPU'}</div>"
1065
+ html += "</div>"
1066
+ html += "<div style='display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin:10px 0;'>"
1067
+ labels = {"clahe":("๐Ÿ”† CLAHE","#00897B"), "histeq":("๐Ÿ“Š HistEQ","#1565C0"), "sharpen":("โšก Sharpen","#E65100"),
1068
+ "combined":("๐Ÿ† Combined","#2E7D32"), "esrgan":("๐Ÿ”ฌ ESRGAN","#6A1B9A"), "neural":("๐ŸŒŠ Neural","#C62828")}
1069
+ for key, (name, color) in labels.items():
1070
+ t = timings.get(key, -1)
1071
+ if t >= 0:
1072
+ rw, rh = results[key].size
1073
+ html += f"<div style='background:{color}15;border:2px solid {color}40;border-radius:10px;padding:10px;text-align:center;'>"
1074
+ html += f"<div style='font-weight:bold;color:{color};'>{name}</div>"
1075
+ html += f"<div style='font-size:11px;color:#666;'>{rw}ร—{rh} | โฑ{t:.1f}s</div></div>"
1076
+ else:
1077
+ html += f"<div style='background:#f5f5f5;border:2px solid #ddd;border-radius:10px;padding:10px;text-align:center;'>"
1078
+ html += f"<div style='color:#999;'>{name} โŒ</div></div>"
1079
+ html += "</div>"
1080
+ html += "<div style='background:#E3F2FD;padding:10px;border-radius:8px;font-size:12px;margin-top:8px;border:1px solid #90CAF9;'>"
1081
+ html += "<b>๐Ÿ’ก</b> CLAHE+Combined ุณุฑูŠุนุฉ ูˆูุนุงู„ุฉ | Real-ESRGAN ุฃูุถู„ ุชูƒุจูŠุฑ | GPU Neural ุชุญุณูŠู† ุนุตุจูŠ</div></div>"
1082
+ return (html, results.get("clahe"), results.get("histeq"), results.get("sharpen"),
1083
+ results.get("combined"), results.get("esrgan"), results.get("neural"))
1084
+
1085
+ def ai_enhance_single(img, technique):
1086
+ if img is None: return None, "โŒ ู„ุง ุชูˆุฌุฏ ุตูˆุฑุฉ"
1087
+ funcs = {"๐Ÿ”† CLAHE Advanced": ai_enhance_clahe_adv, "๐Ÿ“Š Histogram EQ": ai_enhance_histeq,
1088
+ "โšก Sharpen + Denoise": ai_enhance_sharpen, "๐Ÿ† Combined Best": ai_enhance_combined,
1089
+ "๐Ÿ”ฌ Real-ESRGAN x2": ai_enhance_esrgan, "๐ŸŒŠ GPU Neural": ai_enhance_gpu_neural}
1090
+ func = funcs.get(technique)
1091
+ if func is None: return None, "โŒ ุชู‚ู†ูŠุฉ ุบูŠุฑ ู…ุนุฑูˆูุฉ"
1092
+ t0 = time_module.time(); result = func(img); elapsed = time_module.time() - t0
1093
+ if result is None: return None, f"โŒ {technique} ุบูŠุฑ ู…ุชูˆูุฑุฉ"
1094
+ rw, rh = result.size
1095
+ return result, f"โœ… {technique} | {rw}ร—{rh} | โฑ {elapsed:.1f}s"
1096
+
1097
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
1098
  # ๐Ÿ“ก ุฑุจุท ู‚ุงุนุฏุฉ ุงู„ุจูŠุงู†ุงุช ุนุจุฑ API
1099
  # โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•๏ฟฝ๏ฟฝโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
 
2257
  p_btn.click(physics_analyze, inputs=[p_img], outputs=[p_res, p_tbl])
2258
 
2259
 
2260
+
2261
+ # โ•โ•โ• ๐Ÿง  ุชุญุณูŠู† ุงู„ุตูˆุฑ ุจุงู„ุฐูƒุงุก ุงู„ุงุตุทู†ุงุนูŠ โ•โ•โ•
2262
+ with gr.Tab("๐Ÿง  ุชุญุณูŠู† AI"):
2263
+ gr.HTML("""<div style='background:linear-gradient(135deg,#1a237e,#4A148C,#880E4F);padding:14px;border-radius:12px;margin-bottom:10px;color:white;text-align:center;'>
2264
+ <div style='font-size:18px;font-weight:bold;'>๐Ÿง  ุชุญุณูŠู† ุตูˆุฑ ุงู„ุณูˆู†ุงุฑ ุจุงู„ุฐูƒุงุก ุงู„ุงุตุทู†ุงุนูŠ</div>
2265
+ <div style='font-size:12px;opacity:0.8;margin-top:4px;'>Real-ESRGAN ยท GPU Neural ยท CLAHE ยท Histogram EQ ยท Sharpen+Denoise ยท Combined</div>
2266
+ </div>""")
2267
+ with gr.Row():
2268
+ with gr.Column(scale=1):
2269
+ enh_img = gr.Image(label="๐Ÿ“ท ุตูˆุฑุฉ ุงู„ุณูˆู†ุงุฑ ุงู„ุฃุตู„ูŠุฉ", type="pil", height=250)
2270
+ gr.HTML("""<div style='background:#F3E5F5;padding:10px;border-radius:8px;border:1px solid #CE93D8;font-size:11px;margin:6px 0;'>
2271
+ <b>6 ุชู‚ู†ูŠุงุช:</b><br>
2272
+ ๐Ÿ”† CLAHE โ€” ุชุญุณูŠู† ุชุจุงูŠู† ู…ุญู„ูŠ (ุณุฑูŠุน 0.1s)<br>
2273
+ ๐Ÿ“Š Histogram EQ โ€” ุชูˆุฒูŠุน ูƒุซุงูุงุช (ุณุฑูŠุน 0.05s)<br>
2274
+ โšก Sharpen+Denoise โ€” ุญุฏุฉ + ุฅุฒุงู„ุฉ ุถูˆุถุงุก (0.3s)<br>
2275
+ ๐Ÿ† Combined โ€” ุงู„ูƒู„ ู…ุฌุชู…ุน (ุฃูุถู„ ู†ุชูŠุฌุฉ ุณุฑูŠุนุฉ)<br>
2276
+ ๐Ÿ”ฌ Real-ESRGAN โ€” ุชูƒุจูŠุฑ x2 ุจุดุจูƒุฉ ุนุตุจูŠุฉ (GPU 5-15s)<br>
2277
+ ๐ŸŒŠ GPU Neural โ€” ุชุญุณูŠู† ุนุตุจูŠ ู…ุชุนุฏุฏ ุงู„ู…ู‚ุงูŠูŠุณ (GPU 1-3s)
2278
+ </div>""")
2279
+ enh_btn_all = gr.Button("๐Ÿง  ุชุญุณูŠู† ุจูƒู„ ุงู„ุชู‚ู†ูŠุงุช", variant="primary", size="lg")
2280
+ gr.HTML("<div style='text-align:center;color:#666;font-size:12px;margin:6px 0;'>โ€” ุฃูˆ ุงุฎุชุฑ ุชู‚ู†ูŠุฉ ูˆุงุญุฏุฉ โ€”</div>")
2281
+ enh_technique = gr.Radio(
2282
+ choices=["๐Ÿ”† CLAHE Advanced", "๐Ÿ“Š Histogram EQ", "โšก Sharpen + Denoise",
2283
+ "๐Ÿ† Combined Best", "๐Ÿ”ฌ Real-ESRGAN x2", "๐ŸŒŠ GPU Neural"],
2284
+ value="๐Ÿ† Combined Best", label="ุงุฎุชุฑ ุงู„ุชู‚ู†ูŠุฉ")
2285
+ enh_btn_single = gr.Button("โšก ุชุญุณูŠู† ุณุฑูŠุน", variant="secondary")
2286
+ enh_single_result = gr.Image(label="ุงู„ู†ุชูŠุฌุฉ", type="pil", height=200)
2287
+ enh_single_status = gr.HTML("")
2288
+ with gr.Column(scale=2):
2289
+ enh_html = gr.HTML("<div style='text-align:center;padding:60px;color:#999;direction:rtl;'><div style='font-size:48px;'>๐Ÿง </div><div>ุงุฑูุน ุตูˆุฑุฉ ุณูˆู†ุงุฑ ู„ู„ุชุญุณูŠู† ุจุงู„ุฐูƒุงุก ุงู„ุงุตุทู†ุงุนูŠ</div><div style='font-size:12px;margin-top:8px;'>6 ุชู‚ู†ูŠุงุช โ€” GPU accelerated</div></div>")
2290
+ gr.HTML("<div style='background:#1565C0;padding:8px;border-radius:8px;text-align:center;color:white;font-weight:bold;margin:8px 0;'>๐Ÿ“Š ู…ู‚ุงุฑู†ุฉ 6 ุชู‚ู†ูŠุงุช</div>")
2291
+ with gr.Row():
2292
+ enh_clahe = gr.Image(label="๐Ÿ”† CLAHE Advanced", type="pil", height=220)
2293
+ enh_histeq = gr.Image(label="๐Ÿ“Š Histogram EQ", type="pil", height=220)
2294
+ enh_sharpen = gr.Image(label="โšก Sharpen + Denoise", type="pil", height=220)
2295
+ with gr.Row():
2296
+ enh_combined = gr.Image(label="๐Ÿ† Combined Best", type="pil", height=220)
2297
+ enh_esrgan = gr.Image(label="๐Ÿ”ฌ Real-ESRGAN x2", type="pil", height=220)
2298
+ enh_neural = gr.Image(label="๐ŸŒŠ GPU Neural", type="pil", height=220)
2299
+ gr.HTML("<div style='background:#2E7D32;padding:8px;border-radius:8px;text-align:center;color:white;font-weight:bold;margin:8px 0;'>๐Ÿ”„ ู…ู‚ุงุฑู†ุฉ ู‚ุจู„ / ุจุนุฏ</div>")
2300
+ with gr.Row():
2301
+ enh_before = gr.Image(label="๐Ÿ“ท ู‚ุจู„ (ุงู„ุฃุตู„ูŠุฉ)", type="pil", height=300)
2302
+ enh_after = gr.Image(label="๐Ÿ† ุจุนุฏ (ุฃูุถู„ ู†ุชูŠุฌุฉ)", type="pil", height=300)
2303
+ def _run_all_slider(img):
2304
+ html, clahe, histeq, sharpen, combined, esrgan, neural = ai_enhance_all(img)
2305
+ best = esrgan if esrgan is not None else (combined if combined is not None else img)
2306
+ return html, clahe, histeq, sharpen, combined, esrgan, neural, img, best
2307
+ enh_btn_all.click(_run_all_slider, inputs=[enh_img],
2308
+ outputs=[enh_html, enh_clahe, enh_histeq, enh_sharpen, enh_combined, enh_esrgan, enh_neural, enh_before, enh_after])
2309
+ enh_btn_single.click(ai_enhance_single, inputs=[enh_img, enh_technique], outputs=[enh_single_result, enh_single_status])
2310
+
2311
  with gr.Tab("๐Ÿท๏ธ ู‚ุงุนุฏุฉ ุงู„ุฃุตู†ุงู"):
2312
  gr.HTML(f"<div style='background:#E8F5E9;padding:10px 14px;border-radius:10px;margin-bottom:8px;border-right:4px solid #2E7D32;'><b style='color:#2E7D32;'>๐Ÿ“ฆ {len(CARGO_DATABASE)} ุตู†ู</b></div>")
2313
  cats = gr.Dataframe(value=get_categories())