Update app.py
Browse files
app.py
CHANGED
|
@@ -908,63 +908,13 @@ def apply_brightness(img):
|
|
| 908 |
return Image.fromarray(arr)
|
| 909 |
|
| 910 |
|
| 911 |
-
|
| 912 |
-
|
| 913 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 914 |
-
# ๐ง AI Image Enhancement
|
| 915 |
-
#
|
| 916 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 917 |
|
| 918 |
-
|
| 919 |
-
|
| 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
|
|
@@ -976,7 +926,8 @@ def ai_enhance_clahe_adv(img):
|
|
| 976 |
except Exception as e:
|
| 977 |
print(f"โ ๏ธ CLAHE: {e}"); return None
|
| 978 |
|
| 979 |
-
def
|
|
|
|
| 980 |
if img is None: return None
|
| 981 |
try:
|
| 982 |
import cv2
|
|
@@ -987,7 +938,8 @@ def ai_enhance_histeq(img):
|
|
| 987 |
except Exception as e:
|
| 988 |
print(f"โ ๏ธ HistEQ: {e}"); return None
|
| 989 |
|
| 990 |
-
def
|
|
|
|
| 991 |
if img is None: return None
|
| 992 |
try:
|
| 993 |
import cv2
|
|
@@ -998,7 +950,8 @@ def ai_enhance_sharpen(img):
|
|
| 998 |
except Exception as e:
|
| 999 |
print(f"โ ๏ธ Sharpen: {e}"); return None
|
| 1000 |
|
| 1001 |
-
def
|
|
|
|
| 1002 |
if img is None: return None
|
| 1003 |
try:
|
| 1004 |
import cv2
|
|
@@ -1013,7 +966,8 @@ def ai_enhance_combined(img):
|
|
| 1013 |
except Exception as e:
|
| 1014 |
print(f"โ ๏ธ Combined: {e}"); return None
|
| 1015 |
|
| 1016 |
-
def
|
|
|
|
| 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
|
|
@@ -1030,69 +984,203 @@ def ai_enhance_gpu_neural(img):
|
|
| 1030 |
except Exception as e:
|
| 1031 |
print(f"โ ๏ธ GPU Neural: {e}"); return None
|
| 1032 |
|
| 1033 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
| 1044 |
-
("histeq", "๐
|
| 1045 |
-
("sharpen", "โก Sharpen
|
| 1046 |
-
("combined", "๐ Combined
|
| 1047 |
-
("
|
| 1048 |
-
("
|
| 1049 |
]
|
| 1050 |
for key, name, func in techniques:
|
| 1051 |
t0 = time_module.time()
|
| 1052 |
try:
|
| 1053 |
-
|
| 1054 |
-
if
|
| 1055 |
-
results[key] =
|
| 1056 |
else: timings[key] = -1
|
| 1057 |
-
except
|
| 1058 |
-
|
| 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;'>๐ง ุชุญุณูู
|
| 1064 |
-
html += f"<div style='font-size:12px;opacity:0.8;'>
|
| 1065 |
-
html += "</div>"
|
| 1066 |
html += "<div style='display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin:10px 0;'>"
|
| 1067 |
-
|
| 1068 |
-
|
| 1069 |
-
for key
|
| 1070 |
-
t = timings.get(key, -1)
|
| 1071 |
if t >= 0:
|
| 1072 |
rw, rh = results[key].size
|
| 1073 |
-
html += f"<div style='background:{
|
| 1074 |
-
html += f"<div style='font-weight:bold;color:{
|
| 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 |
-
|
| 1079 |
-
|
| 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("
|
|
|
|
| 1084 |
|
| 1085 |
-
def
|
|
|
|
| 1086 |
if img is None: return None, "โ ูุง ุชูุฌุฏ ุตูุฑุฉ"
|
| 1087 |
-
funcs = {"๐ CLAHE
|
| 1088 |
-
"โก Sharpen + Denoise":
|
| 1089 |
-
"
|
| 1090 |
func = funcs.get(technique)
|
| 1091 |
-
if func is None: return None, "โ
|
| 1092 |
-
t0 = time_module.time();
|
| 1093 |
-
if
|
| 1094 |
-
|
| 1095 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1096 |
|
| 1097 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1098 |
# ๐ก ุฑุจุท ูุงุนุฏุฉ ุงูุจูุงูุงุช ุนุจุฑ API
|
|
@@ -2258,55 +2346,75 @@ with gr.Blocks(title=f"SONAR-AI v{VERSION}") as app:
|
|
| 2258 |
|
| 2259 |
|
| 2260 |
|
| 2261 |
-
# โโโ
|
| 2262 |
-
|
| 2263 |
-
|
| 2264 |
-
|
| 2265 |
-
|
|
|
|
|
|
|
| 2266 |
</div>""")
|
| 2267 |
-
|
| 2268 |
-
|
| 2269 |
-
|
| 2270 |
-
|
| 2271 |
-
|
| 2272 |
-
|
| 2273 |
-
|
| 2274 |
-
|
| 2275 |
-
|
| 2276 |
-
|
| 2277 |
-
|
| 2278 |
-
|
| 2279 |
-
|
| 2280 |
-
gr.
|
| 2281 |
-
|
| 2282 |
-
|
| 2283 |
-
|
| 2284 |
-
|
| 2285 |
-
|
| 2286 |
-
|
| 2287 |
-
|
| 2288 |
-
|
| 2289 |
-
|
| 2290 |
-
|
| 2291 |
-
|
| 2292 |
-
|
| 2293 |
-
|
| 2294 |
-
|
| 2295 |
-
|
| 2296 |
-
|
| 2297 |
-
|
| 2298 |
-
|
| 2299 |
-
|
| 2300 |
-
|
| 2301 |
-
|
| 2302 |
-
|
| 2303 |
-
|
| 2304 |
-
|
| 2305 |
-
|
| 2306 |
-
|
| 2307 |
-
|
| 2308 |
-
|
| 2309 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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>")
|
|
|
|
| 908 |
return Image.fromarray(arr)
|
| 909 |
|
| 910 |
|
|
|
|
|
|
|
| 911 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 912 |
+
# ๐ง AI Image Enhancement โ ู
ุณุชูู ุชู
ุงู
ุงู
|
| 913 |
+
# ูุง ูุณุชุฎุฏู
ุฃู ุฏุงูุฉ ู
ู ุงูุชุจููุจุงุช ุงููุฏูู
ุฉ
|
| 914 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 915 |
|
| 916 |
+
def _enh_clahe(img):
|
| 917 |
+
"""๐ CLAHE โ ุชุญุณูู ุงูุชุจุงูู ุงูู
ุญูู"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 918 |
if img is None: return None
|
| 919 |
try:
|
| 920 |
import cv2
|
|
|
|
| 926 |
except Exception as e:
|
| 927 |
print(f"โ ๏ธ CLAHE: {e}"); return None
|
| 928 |
|
| 929 |
+
def _enh_histeq(img):
|
| 930 |
+
"""๐ Histogram EQ โ ุชูุฒูุน ูุซุงูุงุช"""
|
| 931 |
if img is None: return None
|
| 932 |
try:
|
| 933 |
import cv2
|
|
|
|
| 938 |
except Exception as e:
|
| 939 |
print(f"โ ๏ธ HistEQ: {e}"); return None
|
| 940 |
|
| 941 |
+
def _enh_sharpen(img):
|
| 942 |
+
"""โก Sharpen + Denoise"""
|
| 943 |
if img is None: return None
|
| 944 |
try:
|
| 945 |
import cv2
|
|
|
|
| 950 |
except Exception as e:
|
| 951 |
print(f"โ ๏ธ Sharpen: {e}"); return None
|
| 952 |
|
| 953 |
+
def _enh_combined(img):
|
| 954 |
+
"""๐ Combined โ CLAHE + Denoise + Sharpen"""
|
| 955 |
if img is None: return None
|
| 956 |
try:
|
| 957 |
import cv2
|
|
|
|
| 966 |
except Exception as e:
|
| 967 |
print(f"โ ๏ธ Combined: {e}"); return None
|
| 968 |
|
| 969 |
+
def _enh_gpu_neural(img):
|
| 970 |
+
"""๐ GPU Neural โ ุชุญุณูู ุนุตุจู"""
|
| 971 |
if img is None or torch is None: return None
|
| 972 |
try:
|
| 973 |
arr = np.array(img.convert('RGB')).astype(np.float32) / 255.0
|
|
|
|
| 984 |
except Exception as e:
|
| 985 |
print(f"โ ๏ธ GPU Neural: {e}"); return None
|
| 986 |
|
| 987 |
+
def _enh_super_resolve(img):
|
| 988 |
+
"""๐ฌ Super Resolution โ ุชูุจูุฑ x2 ุจุดุจูุฉ ุนุตุจูุฉ"""
|
| 989 |
+
if img is None or torch is None: return None
|
| 990 |
+
try:
|
| 991 |
+
import cv2
|
| 992 |
+
arr = np.array(img.convert('RGB'))
|
| 993 |
+
h, w = arr.shape[:2]
|
| 994 |
+
# Bicubic upscale + neural sharpen
|
| 995 |
+
upscaled = cv2.resize(arr, (w*2, h*2), interpolation=cv2.INTER_CUBIC)
|
| 996 |
+
# Neural sharpen on GPU
|
| 997 |
+
t = torch.from_numpy(upscaled.astype(np.float32) / 255.0).permute(2,0,1).unsqueeze(0).to(DEVICE)
|
| 998 |
+
for ks in [3, 5]:
|
| 999 |
+
pad = ks // 2
|
| 1000 |
+
blurred = torch.nn.functional.avg_pool2d(
|
| 1001 |
+
torch.nn.functional.pad(t, (pad,pad,pad,pad), mode='reflect'), ks, 1)
|
| 1002 |
+
t = t + 0.4 * (t - blurred)
|
| 1003 |
+
t = torch.clamp(t, 0, 1)
|
| 1004 |
+
result = t.squeeze(0).cpu().numpy().transpose(1,2,0)
|
| 1005 |
+
return Image.fromarray((result * 255).clip(0,255).astype(np.uint8))
|
| 1006 |
+
except Exception as e:
|
| 1007 |
+
print(f"โ ๏ธ SuperRes: {e}"); return None
|
| 1008 |
+
|
| 1009 |
+
|
| 1010 |
+
def enhance_all_independent(img):
|
| 1011 |
+
"""๐ง ุชุดุบูู 6 ุชูููุงุช ู
ุณุชููุฉ"""
|
| 1012 |
if img is None:
|
| 1013 |
empty = "<div style='text-align:center;padding:60px;color:#999;direction:rtl;'>"
|
| 1014 |
empty += "<div style='font-size:48px;'>๐ง </div>"
|
| 1015 |
empty += "<div>ุงุฑูุน ุตูุฑุฉ ุณููุงุฑ ููุชุญุณูู ุจุงูุฐูุงุก ุงูุงุตุทูุงุนู</div></div>"
|
| 1016 |
return empty, None, None, None, None, None, None
|
| 1017 |
+
|
| 1018 |
start = time_module.time()
|
| 1019 |
w_orig, h_orig = img.size
|
| 1020 |
results = {}; timings = {}
|
| 1021 |
+
|
| 1022 |
techniques = [
|
| 1023 |
+
("clahe", "๐ CLAHE", _enh_clahe),
|
| 1024 |
+
("histeq", "๐ HistEQ", _enh_histeq),
|
| 1025 |
+
("sharpen", "โก Sharpen", _enh_sharpen),
|
| 1026 |
+
("combined", "๐ Combined", _enh_combined),
|
| 1027 |
+
("neural", "๐ GPU Neural", _enh_gpu_neural),
|
| 1028 |
+
("superres", "๐ฌ Super Res x2", _enh_super_resolve),
|
| 1029 |
]
|
| 1030 |
for key, name, func in techniques:
|
| 1031 |
t0 = time_module.time()
|
| 1032 |
try:
|
| 1033 |
+
r = func(img)
|
| 1034 |
+
if r is not None:
|
| 1035 |
+
results[key] = r; timings[key] = time_module.time() - t0
|
| 1036 |
else: timings[key] = -1
|
| 1037 |
+
except: timings[key] = -1
|
| 1038 |
+
|
| 1039 |
elapsed = time_module.time() - start
|
| 1040 |
n_ok = sum(1 for v in timings.values() if v >= 0)
|
| 1041 |
+
|
| 1042 |
html = "<div style='font-family:Tajawal,sans-serif;direction:rtl;'>"
|
| 1043 |
html += "<div style='background:linear-gradient(135deg,#1a237e,#4A148C);padding:14px;border-radius:12px;text-align:center;color:white;margin-bottom:10px;'>"
|
| 1044 |
+
html += f"<div style='font-size:16px;font-weight:bold;'>๐ง ุชุญุณูู ู
ุณุชูู โ {n_ok}/{len(techniques)} ุชูููุงุช</div>"
|
| 1045 |
+
html += f"<div style='font-size:12px;opacity:0.8;'>{w_orig}ร{h_orig} | โฑ {elapsed:.1f}s</div></div>"
|
|
|
|
| 1046 |
html += "<div style='display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin:10px 0;'>"
|
| 1047 |
+
colors = {"clahe":"#00897B","histeq":"#1565C0","sharpen":"#E65100","combined":"#2E7D32","neural":"#C62828","superres":"#6A1B9A"}
|
| 1048 |
+
names = {"clahe":"๐ CLAHE","histeq":"๐ HistEQ","sharpen":"โก Sharpen","combined":"๐ Combined","neural":"๐ Neural","superres":"๐ฌ Super x2"}
|
| 1049 |
+
for key in ["clahe","histeq","sharpen","combined","neural","superres"]:
|
| 1050 |
+
t = timings.get(key, -1); c = colors[key]; n = names[key]
|
| 1051 |
if t >= 0:
|
| 1052 |
rw, rh = results[key].size
|
| 1053 |
+
html += f"<div style='background:{c}15;border:2px solid {c}40;border-radius:10px;padding:10px;text-align:center;'>"
|
| 1054 |
+
html += f"<div style='font-weight:bold;color:{c};'>{n}</div>"
|
| 1055 |
html += f"<div style='font-size:11px;color:#666;'>{rw}ร{rh} | โฑ{t:.1f}s</div></div>"
|
| 1056 |
else:
|
| 1057 |
+
html += f"<div style='background:#f5f5f5;border:2px solid #ddd;border-radius:10px;padding:10px;text-align:center;'><div style='color:#999;'>{n} โ</div></div>"
|
| 1058 |
+
html += "</div></div>"
|
| 1059 |
+
|
|
|
|
|
|
|
| 1060 |
return (html, results.get("clahe"), results.get("histeq"), results.get("sharpen"),
|
| 1061 |
+
results.get("combined"), results.get("neural"), results.get("superres"))
|
| 1062 |
+
|
| 1063 |
|
| 1064 |
+
def enhance_single_independent(img, technique):
|
| 1065 |
+
"""ุชุญุณูู ุจุชูููุฉ ูุงุญุฏุฉ"""
|
| 1066 |
if img is None: return None, "โ ูุง ุชูุฌุฏ ุตูุฑุฉ"
|
| 1067 |
+
funcs = {"๐ CLAHE": _enh_clahe, "๐ Histogram EQ": _enh_histeq,
|
| 1068 |
+
"โก Sharpen + Denoise": _enh_sharpen, "๐ Combined Best": _enh_combined,
|
| 1069 |
+
"๐ GPU Neural": _enh_gpu_neural, "๐ฌ Super Resolution x2": _enh_super_resolve}
|
| 1070 |
func = funcs.get(technique)
|
| 1071 |
+
if func is None: return None, "โ"
|
| 1072 |
+
t0 = time_module.time(); r = func(img); el = time_module.time() - t0
|
| 1073 |
+
if r is None: return None, f"โ {technique} ุบูุฑ ู
ุชููุฑุฉ"
|
| 1074 |
+
return r, f"โ
{technique} | {r.size[0]}ร{r.size[1]} | โฑ {el:.1f}s"
|
| 1075 |
+
|
| 1076 |
+
|
| 1077 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1078 |
+
# โก YOLO11x-cls ููุท โ ุชุญููู ุณุฑูุน ู
ุณุชูู
|
| 1079 |
+
# ูุง ูุณุชุฎุฏู
classify_image ููุง analyze_image
|
| 1080 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1081 |
+
|
| 1082 |
+
def yolo11_fast_classify(img, declared_text):
|
| 1083 |
+
"""โก ุชุตููู ุณุฑูุน ุจู YOLO11x-cls ููุท (3-8 ุซูุงูู)"""
|
| 1084 |
+
if img is None:
|
| 1085 |
+
return ("<div style='text-align:center;padding:60px;color:#999;'>"
|
| 1086 |
+
"<div style='font-size:48px;'>๐ท</div><div>ุงุฑูุน ุตูุฑุฉ ููุจุฏุก</div></div>",
|
| 1087 |
+
pd.DataFrame(), None)
|
| 1088 |
+
|
| 1089 |
+
start = time_module.time()
|
| 1090 |
+
if img.mode != 'RGB':
|
| 1091 |
+
img = img.convert('RGB')
|
| 1092 |
+
|
| 1093 |
+
# โโโ ุงูุจุญุซ ุนู YOLO11x ููุท โโโ
|
| 1094 |
+
yolo_model = None
|
| 1095 |
+
yolo_name = None
|
| 1096 |
+
for name in ['YOLO11x-cls', 'YOLOv10x-cls']:
|
| 1097 |
+
if name in CLASSIFICATION_MODELS:
|
| 1098 |
+
yolo_model = CLASSIFICATION_MODELS[name]
|
| 1099 |
+
yolo_name = name
|
| 1100 |
+
break
|
| 1101 |
+
|
| 1102 |
+
if yolo_model is None:
|
| 1103 |
+
return ("<div style='color:red;text-align:center;padding:30px;'>โ YOLO11x-cls ุบูุฑ ู
ุชููุฑ</div>",
|
| 1104 |
+
pd.DataFrame(), None)
|
| 1105 |
+
|
| 1106 |
+
# โโโ ุชุตููู โโโ
|
| 1107 |
+
items_list = []
|
| 1108 |
+
try:
|
| 1109 |
+
res = yolo_model(img, verbose=False)
|
| 1110 |
+
if res and res[0].probs is not None:
|
| 1111 |
+
probs = res[0].probs.data.cpu().numpy()
|
| 1112 |
+
top5_idx = probs.argsort()[-5:][::-1]
|
| 1113 |
+
for idx in top5_idx:
|
| 1114 |
+
if idx < len(CATEGORIES) and probs[idx] > 0.05:
|
| 1115 |
+
items_list.append((CATEGORIES[idx], float(probs[idx])))
|
| 1116 |
+
except Exception as e:
|
| 1117 |
+
return (f"<div style='color:red;'>โ ุฎุทุฃ: {e}</div>", pd.DataFrame(), None)
|
| 1118 |
+
|
| 1119 |
+
if not items_list:
|
| 1120 |
+
return ("<div style='color:orange;text-align:center;'>โ ๏ธ ูู
ูุชู
ุงูุชุดุงู ุฃุตูุงู</div>",
|
| 1121 |
+
pd.DataFrame(), None)
|
| 1122 |
+
|
| 1123 |
+
elapsed = time_module.time() - start
|
| 1124 |
+
|
| 1125 |
+
# โโโ ุงูุฌุฏูู โโโ
|
| 1126 |
+
rows = []
|
| 1127 |
+
total_duty = 0
|
| 1128 |
+
for i, (item, conf) in enumerate(items_list):
|
| 1129 |
+
info = get_hs_info(item)
|
| 1130 |
+
total_duty += info['duty']
|
| 1131 |
+
rows.append({'#': i+1, 'ุงูุตูู': info['ar'], 'EN': info['en'], 'ููุฏ_HS': info['hs'],
|
| 1132 |
+
'ุฑู
ุฒ_TSC': info['tsc_code'], 'ุงููุตู': f"Ch.{info['ch']} {info['ch_name']}",
|
| 1133 |
+
'ุงูุฑุณูู
%': info['duty'],
|
| 1134 |
+
'ุงูุณุนุฑ_ุงูู
ุฑุฌุนู': f"${info['avg_price']}" if info['avg_price'] > 0 else 'โ',
|
| 1135 |
+
'ุงูุซูุฉ': f"{conf:.1%}", 'ุงูู
ุตุฏุฑ': f'โก {yolo_name}'})
|
| 1136 |
+
df = pd.DataFrame(rows)
|
| 1137 |
+
|
| 1138 |
+
# โโโ ู
ุทุงุจูุฉ ุงูุชุตุฑูุญ โโโ
|
| 1139 |
+
declared = [d.strip().lower() for d in declared_text.split('+') if d.strip()] if declared_text else []
|
| 1140 |
+
det_names = [it.lower() for it, _ in items_list]
|
| 1141 |
+
is_match = True
|
| 1142 |
+
if declared:
|
| 1143 |
+
matched = sum(1 for d in declared if any(d in nm for nm in det_names))
|
| 1144 |
+
is_match = matched / max(len(declared), 1) > 0.5
|
| 1145 |
+
|
| 1146 |
+
top_name, top_conf = items_list[0]
|
| 1147 |
+
risk = 0 if is_match else 3
|
| 1148 |
+
if top_name == 'weapons': risk = 5
|
| 1149 |
+
risk_cfg = {0:('ุขู
ู','#2E7D32','๐ข'),1:('ู
ูุฎูุถ','#558B2F','๐ข'),2:('ู
ุชูุณุท','#F9A825','๐ก'),
|
| 1150 |
+
3:('ู
ุดุจูู','#EF6C00','๐ '),4:('ุนุงูู','#D84315','๐ด'),5:('ุญุฑุฌ','#B71C1C','โ')}
|
| 1151 |
+
r_name, r_color, r_icon = risk_cfg[risk]
|
| 1152 |
+
|
| 1153 |
+
n_items = len(items_list)
|
| 1154 |
+
en_desc = ' | '.join([f"{CARGO_DATABASE.get(it,{}).get('hs','')}-{it.upper()}" for it, _ in items_list])
|
| 1155 |
+
ar_desc = ' | '.join([CARGO_DATABASE.get(it,{}).get('ar', it) for it, _ in items_list])
|
| 1156 |
+
|
| 1157 |
+
html = f"""
|
| 1158 |
+
<div style='font-family:Tajawal,sans-serif;'>
|
| 1159 |
+
<div style='background:#FF6F00;padding:8px 14px;border-radius:10px;text-align:center;color:white;margin-bottom:8px;font-size:13px;'>โก {yolo_name} ููุท โ ูู
ูุฐุฌ ูุงุญุฏ | โฑ {elapsed:.1f}s</div>
|
| 1160 |
+
<div style='background:{"#2E7D32" if is_match else "#EF6C00"};padding:14px;border-radius:12px;text-align:center;color:white;margin-bottom:10px;'>
|
| 1161 |
+
<div style='font-size:22px;font-weight:bold;'>{"โ
ู
ุทุงุจู ููุชุตุฑูุญ" if is_match else "โ ๏ธ ูุชุทูุจ ู
ุฑุงุฌุนุฉ"}</div>
|
| 1162 |
+
</div>
|
| 1163 |
+
<div style='display:grid;grid-template-columns:repeat(4,1fr);gap:8px;margin-bottom:10px;'>
|
| 1164 |
+
<div style='background:#E3F2FD;padding:12px;border-radius:10px;text-align:center;border:1px solid #90CAF9;'>
|
| 1165 |
+
<div style='font-size:24px;font-weight:bold;color:#1565C0;'>{n_items}</div><div style='color:#666;font-size:12px;'>ุฃุตูุงู</div></div>
|
| 1166 |
+
<div style='background:#FFF3E0;padding:12px;border-radius:10px;text-align:center;border:1px solid #FFCC80;'>
|
| 1167 |
+
<div style='font-size:24px;font-weight:bold;color:#E65100;'>{total_duty}%</div><div style='color:#666;font-size:12px;'>ุงูุฑุณูู
</div></div>
|
| 1168 |
+
<div style='background:{r_color}15;padding:12px;border-radius:10px;text-align:center;border:1px solid {r_color}40;'>
|
| 1169 |
+
<div style='font-size:24px;font-weight:bold;color:{r_color};'>{r_icon} {r_name}</div><div style='color:#666;font-size:12px;'>ุงูุฎุทูุฑุฉ</div></div>
|
| 1170 |
+
<div style='background:#E8F5E9;padding:12px;border-radius:10px;text-align:center;border:1px solid #A5D6A7;'>
|
| 1171 |
+
<div style='font-size:24px;font-weight:bold;color:#2E7D32;'>โก</div><div style='color:#666;font-size:12px;'>{elapsed:.1f}s</div></div>
|
| 1172 |
+
</div>
|
| 1173 |
+
<div style='background:#fff;padding:14px;border-radius:10px;border:1px solid #e0e0e0;margin-top:8px;margin-bottom:8px;'>
|
| 1174 |
+
<div style='font-weight:bold;color:#1565C0;margin-bottom:6px;'>๐ HS Codes</div>
|
| 1175 |
+
<div style='background:#F5F5F5;padding:8px 12px;border-radius:8px;font-family:monospace;font-size:12px;direction:ltr;'>{en_desc}</div>
|
| 1176 |
+
</div>
|
| 1177 |
+
<div style='background:#fff;padding:14px;border-radius:10px;border:1px solid #e0e0e0;'>
|
| 1178 |
+
<div style='font-weight:bold;color:#E65100;margin-bottom:6px;'>๐ ุงููุตู</div>
|
| 1179 |
+
<div style='background:#FFF8E1;padding:8px 12px;border-radius:8px;font-size:13px;'>{ar_desc}</div>
|
| 1180 |
+
</div>
|
| 1181 |
+
</div>"""
|
| 1182 |
+
return html, df, None
|
| 1183 |
+
|
| 1184 |
|
| 1185 |
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 1186 |
# ๐ก ุฑุจุท ูุงุนุฏุฉ ุงูุจูุงูุงุช ุนุจุฑ API
|
|
|
|
| 2346 |
|
| 2347 |
|
| 2348 |
|
| 2349 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 2350 |
+
# ๐ง ุชุจููุจ ู
ุณุชูู โ YOLO11x + ุชุญุณูู ุตูุฑ
|
| 2351 |
+
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 2352 |
+
with gr.Tab("๐ง AI ู
ุณุชูู"):
|
| 2353 |
+
gr.HTML("""<div style='background:linear-gradient(135deg,#FF6F00,#E65100);padding:14px;border-radius:12px;margin-bottom:10px;color:white;text-align:center;'>
|
| 2354 |
+
<div style='font-size:18px;font-weight:bold;'>๐ง ุชุจููุจ ู
ุณุชูู โ YOLO11x + ุชุญุณูู ุตูุฑ</div>
|
| 2355 |
+
<div style='font-size:12px;opacity:0.8;margin-top:4px;'>โก ุณุฑูุน (5s) | ูู
ูุฐุฌ ูุงุญุฏ ููุท | 6 ุชูููุงุช ุชุญุณูู</div>
|
| 2356 |
</div>""")
|
| 2357 |
+
|
| 2358 |
+
with gr.Tabs():
|
| 2359 |
+
# โโโ ูุณู
1: ุชุตููู ุณุฑูุน YOLO11x โโโ
|
| 2360 |
+
with gr.Tab("โก ุชุตููู ุณุฑูุน"):
|
| 2361 |
+
gr.HTML("<div style='background:#FF6F00;padding:8px;border-radius:8px;text-align:center;color:white;font-weight:bold;margin-bottom:8px;'>โก YOLO11x-cls โ ุชุตููู ุจูู
ูุฐุฌ ูุงุญุฏ (3-8 ุซูุงูู)</div>")
|
| 2362 |
+
with gr.Row():
|
| 2363 |
+
with gr.Column(scale=1):
|
| 2364 |
+
y_img = gr.Image(label="๐ท ุตูุฑุฉ ุงูุณููุงุฑ", type="pil", height=300)
|
| 2365 |
+
y_dec = gr.Textbox(label="๐ ุงูุจุถุงุนุฉ ุงูู
ุตุฑูุญุฉ", placeholder="ู
ุซุงู: snacks ุฃู rice+sugar", lines=1)
|
| 2366 |
+
y_btn = gr.Button("โก ุชุตููู ุณุฑูุน YOLO11x", variant="primary", size="lg")
|
| 2367 |
+
with gr.Column(scale=2):
|
| 2368 |
+
y_res = gr.HTML("")
|
| 2369 |
+
y_tbl = gr.Dataframe(label="๐ ุงููุชุงุฆุฌ", value=pd.DataFrame(), wrap=True)
|
| 2370 |
+
y_det = gr.Image(label="๐ฏ Detection", type="pil", visible=False)
|
| 2371 |
+
y_btn.click(yolo11_fast_classify, inputs=[y_img, y_dec], outputs=[y_res, y_tbl, y_det], api_name="analyze_fast")
|
| 2372 |
+
|
| 2373 |
+
# โโโ ูุณู
2: ุชุญุณูู ุตูุฑ โโโ
|
| 2374 |
+
with gr.Tab("๐ฌ ุชุญุณูู ุตูุฑ"):
|
| 2375 |
+
gr.HTML("<div style='background:#1a237e;padding:8px;border-radius:8px;text-align:center;color:white;font-weight:bold;margin-bottom:8px;'>๐ฌ 6 ุชูููุงุช ุชุญุณูู โ CLAHE ยท HistEQ ยท Sharpen ยท Combined ยท Neural ยท Super Res</div>")
|
| 2376 |
+
with gr.Row():
|
| 2377 |
+
with gr.Column(scale=1):
|
| 2378 |
+
enh_img = gr.Image(label="๐ท ุงูุตูุฑุฉ ุงูุฃุตููุฉ", type="pil", height=250)
|
| 2379 |
+
gr.HTML("""<div style='background:#F3E5F5;padding:10px;border-radius:8px;border:1px solid #CE93D8;font-size:11px;margin:6px 0;'>
|
| 2380 |
+
๐ CLAHE โ ุชุจุงูู ู
ุญูู (0.1s)<br>๐ HistEQ โ ุชูุฒูุน ูุซุงูุงุช (0.05s)<br>
|
| 2381 |
+
โก Sharpen โ ุญุฏุฉ + ุฅุฒุงูุฉ ุถูุถุงุก (0.3s)<br>๐ Combined โ ุฃูุถู ูุชูุฌุฉ (0.4s)<br>
|
| 2382 |
+
๐ Neural โ ุชุญุณูู ุนุตุจู GPU (1-3s)<br>๐ฌ Super Res โ ุชูุจูุฑ x2 (2-5s)
|
| 2383 |
+
</div>""")
|
| 2384 |
+
enh_btn_all = gr.Button("๐ง ุชุญุณูู ุจูู ุงูุชูููุงุช", variant="primary", size="lg")
|
| 2385 |
+
gr.HTML("<div style='text-align:center;color:#666;font-size:12px;margin:6px 0;'>โ ุฃู ุงุฎุชุฑ ูุงุญุฏุฉ โ</div>")
|
| 2386 |
+
enh_tech = gr.Radio(choices=["๐ CLAHE", "๐ Histogram EQ", "โก Sharpen + Denoise",
|
| 2387 |
+
"๐ Combined Best", "๐ GPU Neural", "๐ฌ Super Resolution x2"],
|
| 2388 |
+
value="๐ Combined Best", label="ุงูุชูููุฉ")
|
| 2389 |
+
enh_btn_one = gr.Button("โก ุชุญุณูู ุณุฑูุน", variant="secondary")
|
| 2390 |
+
enh_one_res = gr.Image(label="ุงููุชูุฌุฉ", type="pil", height=200)
|
| 2391 |
+
enh_one_st = gr.HTML("")
|
| 2392 |
+
with gr.Column(scale=2):
|
| 2393 |
+
enh_html = gr.HTML("<div style='text-align:center;padding:60px;color:#999;direction:rtl;'><div style='font-size:48px;'>๐ง </div><div>ุงุฑูุน ุตูุฑุฉ ููุชุญุณูู</div></div>")
|
| 2394 |
+
|
| 2395 |
+
gr.HTML("<div style='background:#1565C0;padding:8px;border-radius:8px;text-align:center;color:white;font-weight:bold;margin:8px 0;'>๐ ู
ูุงุฑูุฉ 6 ุชูููุงุช</div>")
|
| 2396 |
+
with gr.Row():
|
| 2397 |
+
enh_r1 = gr.Image(label="๐ CLAHE", type="pil", height=220)
|
| 2398 |
+
enh_r2 = gr.Image(label="๐ HistEQ", type="pil", height=220)
|
| 2399 |
+
enh_r3 = gr.Image(label="โก Sharpen", type="pil", height=220)
|
| 2400 |
+
with gr.Row():
|
| 2401 |
+
enh_r4 = gr.Image(label="๐ Combined", type="pil", height=220)
|
| 2402 |
+
enh_r5 = gr.Image(label="๐ Neural", type="pil", height=220)
|
| 2403 |
+
enh_r6 = gr.Image(label="๐ฌ Super Res x2", type="pil", height=220)
|
| 2404 |
+
|
| 2405 |
+
gr.HTML("<div style='background:#2E7D32;padding:8px;border-radius:8px;text-align:center;color:white;font-weight:bold;margin:8px 0;'>๐ ูุจู / ุจุนุฏ</div>")
|
| 2406 |
+
with gr.Row():
|
| 2407 |
+
enh_before = gr.Image(label="๐ท ูุจู", type="pil", height=300)
|
| 2408 |
+
enh_after = gr.Image(label="๐ ุจุนุฏ", type="pil", height=300)
|
| 2409 |
+
|
| 2410 |
+
def _run_all(img):
|
| 2411 |
+
html, r1, r2, r3, r4, r5, r6 = enhance_all_independent(img)
|
| 2412 |
+
best = r4 if r4 is not None else (r5 if r5 is not None else img)
|
| 2413 |
+
return html, r1, r2, r3, r4, r5, r6, img, best
|
| 2414 |
+
|
| 2415 |
+
enh_btn_all.click(_run_all, inputs=[enh_img],
|
| 2416 |
+
outputs=[enh_html, enh_r1, enh_r2, enh_r3, enh_r4, enh_r5, enh_r6, enh_before, enh_after])
|
| 2417 |
+
enh_btn_one.click(enhance_single_independent, inputs=[enh_img, enh_tech], outputs=[enh_one_res, enh_one_st])
|
| 2418 |
|
| 2419 |
with gr.Tab("๐ท๏ธ ูุงุนุฏุฉ ุงูุฃุตูุงู"):
|
| 2420 |
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>")
|