Spaces:
Running
Running
Foydalanuvchi commited on
Commit ·
f1841ce
1
Parent(s): 9b345f9
Phase 5: Ultra HD (EDSR+CLAHE) and Pro Stabilization
Browse files- filters.py +117 -51
- requirements.txt +1 -1
filters.py
CHANGED
|
@@ -61,13 +61,32 @@ def apply_retro_filter(image_path, output_path):
|
|
| 61 |
logger.error(f"Retro rasm xatosi: {e}")
|
| 62 |
return None
|
| 63 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 64 |
def upscale_image(image_path, output_path, scale=2):
|
| 65 |
-
"""Rasmni AI Super-Resolution (Swin2SR)
|
| 66 |
try:
|
| 67 |
image_path = os.path.abspath(image_path)
|
| 68 |
output_path = os.path.abspath(output_path)
|
| 69 |
|
| 70 |
-
# 1. Hugging Face AI orqali (Eng yuqori sifat)
|
| 71 |
hf_token = os.environ.get("HF_TOKEN")
|
| 72 |
if hf_token:
|
| 73 |
try:
|
|
@@ -78,7 +97,6 @@ def upscale_image(image_path, output_path, scale=2):
|
|
| 78 |
image_data = f.read()
|
| 79 |
|
| 80 |
logger.info("HF Upscale: AI Super-Resolution ishga tushirildi.")
|
| 81 |
-
# Super-resolution uchun to'g'ri API chaqiruvi
|
| 82 |
result_image = client.image_to_image(
|
| 83 |
image_data,
|
| 84 |
model="caidas/swin2SR-classical-sr-x2-64",
|
|
@@ -88,9 +106,9 @@ def upscale_image(image_path, output_path, scale=2):
|
|
| 88 |
logger.info("HF Upscale muvaffaqiyatli.")
|
| 89 |
return output_path
|
| 90 |
except Exception as e:
|
| 91 |
-
logger.warning(f"HF Upscale xatosi (
|
| 92 |
|
| 93 |
-
# 2. Lokal
|
| 94 |
img = cv2.imread(image_path)
|
| 95 |
if img is None: return None
|
| 96 |
|
|
@@ -99,26 +117,54 @@ def upscale_image(image_path, output_path, scale=2):
|
|
| 99 |
elif img.shape[2] == 4:
|
| 100 |
img = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)
|
| 101 |
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
|
|
|
|
| 109 |
pill_img = Image.fromarray(cv2.cvtColor(upscaled, cv2.COLOR_BGR2RGB))
|
| 110 |
-
|
| 111 |
-
# O'tkirlik va kontrastni tabiiy kuchaytirish
|
| 112 |
enhancer = ImageEnhance.Sharpness(pill_img)
|
| 113 |
-
pill_img = enhancer.enhance(1.
|
| 114 |
enhancer_c = ImageEnhance.Contrast(pill_img)
|
| 115 |
-
pill_img = enhancer_c.enhance(1.
|
| 116 |
|
| 117 |
upscaled_final = cv2.cvtColor(np.array(pill_img), cv2.COLOR_RGB2BGR)
|
| 118 |
cv2.imwrite(output_path, upscaled_final)
|
| 119 |
-
|
|
|
|
|
|
|
| 120 |
except Exception as e:
|
| 121 |
-
logger.error(f"Upscale rasm xatosi: {e}")
|
| 122 |
return None
|
| 123 |
|
| 124 |
def _apply_video_transform(video_path, output_path, transform_func, progress_callback=None, fps_override=None):
|
|
@@ -188,15 +234,27 @@ def process_video_retro(video_path, output_path, progress_callback=None):
|
|
| 188 |
|
| 189 |
|
| 190 |
def process_video_upscale(video_path, output_path, progress_callback=None):
|
| 191 |
-
"""Videoning sifatini (o'lcham va o'tkirlik) oshiradi."""
|
| 192 |
def upscale_frame(frame):
|
| 193 |
bgr = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
|
| 194 |
h, w = bgr.shape[:2]
|
| 195 |
-
upscaled = cv2.resize(bgr, (int(w*1.5), int(h*1.5)), interpolation=cv2.INTER_LANCZOS4)
|
| 196 |
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 200 |
|
| 201 |
return _apply_video_transform(video_path, output_path, upscale_frame, progress_callback)
|
| 202 |
|
|
@@ -1166,25 +1224,30 @@ def process_video_stabilize(video_path, output_path, progress_callback=None, smo
|
|
| 1166 |
cum_a += da
|
| 1167 |
trajectory.append((cum_x, cum_y, cum_a))
|
| 1168 |
|
| 1169 |
-
#
|
| 1170 |
-
def
|
| 1171 |
-
"""
|
| 1172 |
-
|
| 1173 |
-
|
| 1174 |
-
|
| 1175 |
-
|
| 1176 |
-
|
| 1177 |
-
|
| 1178 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1179 |
|
| 1180 |
traj_x = np.array([t[0] for t in trajectory])
|
| 1181 |
traj_y = np.array([t[1] for t in trajectory])
|
| 1182 |
traj_a = np.array([t[2] for t in trajectory])
|
| 1183 |
|
| 1184 |
-
# Trajectoryani tekislash
|
| 1185 |
-
smooth_x =
|
| 1186 |
-
smooth_y =
|
| 1187 |
-
smooth_a =
|
| 1188 |
|
| 1189 |
# Tuzatish = tekislangan - asl trajectory
|
| 1190 |
diff_x = smooth_x - traj_x
|
|
@@ -1207,26 +1270,23 @@ def process_video_stabilize(video_path, output_path, progress_callback=None, smo
|
|
| 1207 |
|
| 1208 |
cap = cv2.VideoCapture(video_path)
|
| 1209 |
|
| 1210 |
-
#
|
| 1211 |
-
|
| 1212 |
-
|
| 1213 |
-
crop_y = int(height * crop_ratio)
|
| 1214 |
-
out_w = width - 2 * crop_x
|
| 1215 |
-
out_h = height - 2 * crop_y
|
| 1216 |
|
| 1217 |
temp_video_path = output_path + "_stab_temp.avi"
|
| 1218 |
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
|
| 1219 |
writer = cv2.VideoWriter(temp_video_path, fourcc, fps, (out_w, out_h))
|
| 1220 |
|
| 1221 |
-
#
|
| 1222 |
-
|
|
|
|
|
|
|
| 1223 |
if not ret:
|
| 1224 |
cap.release()
|
| 1225 |
return None
|
| 1226 |
|
| 1227 |
-
|
| 1228 |
-
first_cropped = _[crop_y:crop_y+out_h, crop_x:crop_x+out_w]
|
| 1229 |
-
writer.write(first_cropped)
|
| 1230 |
|
| 1231 |
for i in range(len(smooth_transforms)):
|
| 1232 |
ret, frame = cap.read()
|
|
@@ -1243,15 +1303,21 @@ def process_video_stabilize(video_path, output_path, progress_callback=None, smo
|
|
| 1243 |
[sin_a, cos_a, dy]
|
| 1244 |
], dtype=np.float64)
|
| 1245 |
|
| 1246 |
-
# Transformatsiyani qo'llash
|
| 1247 |
stabilized = cv2.warpAffine(
|
| 1248 |
frame, transform_mat, (width, height),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1249 |
borderMode=cv2.BORDER_REFLECT_101
|
| 1250 |
)
|
| 1251 |
|
| 1252 |
-
|
| 1253 |
-
cropped = stabilized[crop_y:crop_y+out_h, crop_x:crop_x+out_w]
|
| 1254 |
-
writer.write(cropped)
|
| 1255 |
|
| 1256 |
if progress_callback and i % 5 == 0:
|
| 1257 |
progress_callback(min(95, 55 + int(i / len(smooth_transforms) * 40)))
|
|
|
|
| 61 |
logger.error(f"Retro rasm xatosi: {e}")
|
| 62 |
return None
|
| 63 |
|
| 64 |
+
def _get_superres_model():
|
| 65 |
+
"""EDSR_x2 modelini keshdan oladi yoki avtomatik yuklaydi."""
|
| 66 |
+
cache_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "cache")
|
| 67 |
+
os.makedirs(cache_dir, exist_ok=True)
|
| 68 |
+
model_path = os.path.join(cache_dir, "EDSR_x2.pb")
|
| 69 |
+
|
| 70 |
+
if not os.path.exists(model_path):
|
| 71 |
+
logger.info("EDSR_x2 AI modeli topilmadi. Yuklab olinmoqda (birinchi marta ishlaganda biroz vaqt oladi)...")
|
| 72 |
+
try:
|
| 73 |
+
import urllib.request
|
| 74 |
+
# EDSR x2 modelini to'g'ridan-to'g'ri Saafke repo dan tortish
|
| 75 |
+
url = "https://github.com/Saafke/EDSR_TensorFlow/raw/master/models/EDSR_x2.pb"
|
| 76 |
+
urllib.request.urlretrieve(url, model_path)
|
| 77 |
+
logger.info("✅ EDSR_x2 muvaffaqiyatli yuklandi va keshlandi!")
|
| 78 |
+
except Exception as e:
|
| 79 |
+
logger.error(f"EDSR modelini yuklashda xatolik: {e}")
|
| 80 |
+
return None
|
| 81 |
+
return model_path
|
| 82 |
+
|
| 83 |
def upscale_image(image_path, output_path, scale=2):
|
| 84 |
+
"""Rasmni AI Super-Resolution (Swin2SR/EDSR) yoki ilg'or Matematik (LAB CLAHE) algoritm bilan oshirish."""
|
| 85 |
try:
|
| 86 |
image_path = os.path.abspath(image_path)
|
| 87 |
output_path = os.path.abspath(output_path)
|
| 88 |
|
| 89 |
+
# 1. Hugging Face AI orqali (Eng yuqori sifat, agar Premium Token berilgan bo'lsa)
|
| 90 |
hf_token = os.environ.get("HF_TOKEN")
|
| 91 |
if hf_token:
|
| 92 |
try:
|
|
|
|
| 97 |
image_data = f.read()
|
| 98 |
|
| 99 |
logger.info("HF Upscale: AI Super-Resolution ishga tushirildi.")
|
|
|
|
| 100 |
result_image = client.image_to_image(
|
| 101 |
image_data,
|
| 102 |
model="caidas/swin2SR-classical-sr-x2-64",
|
|
|
|
| 106 |
logger.info("HF Upscale muvaffaqiyatli.")
|
| 107 |
return output_path
|
| 108 |
except Exception as e:
|
| 109 |
+
logger.warning(f"HF Upscale xatosi (Lokal AI/Fallback ga o'tilmoqda): {e}")
|
| 110 |
|
| 111 |
+
# 2. Lokal Asosiy Algoritmga tayyorlash
|
| 112 |
img = cv2.imread(image_path)
|
| 113 |
if img is None: return None
|
| 114 |
|
|
|
|
| 117 |
elif img.shape[2] == 4:
|
| 118 |
img = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)
|
| 119 |
|
| 120 |
+
# 3. YECHIM: Local AI DNN Super-Resolution (EDSR_x2 moduli)
|
| 121 |
+
ai_upscaled = False
|
| 122 |
+
try:
|
| 123 |
+
from cv2 import dnn_superres
|
| 124 |
+
model_path = _get_superres_model()
|
| 125 |
+
if model_path and os.path.exists(model_path):
|
| 126 |
+
sr = dnn_superres.DnnSuperResImpl_create()
|
| 127 |
+
sr.readModel(model_path)
|
| 128 |
+
sr.setModel("edsr", 2) # Scale 2x ekanligi sababli x2 qilingan
|
| 129 |
+
logger.info("Lokal AI (EDSR) ishlashni boshladi...")
|
| 130 |
+
upscaled = sr.upsample(img)
|
| 131 |
+
ai_upscaled = True
|
| 132 |
+
logger.info("Lokal AI (EDSR) orqali rasm muvaffaqiyatli kattalashtirildi.")
|
| 133 |
+
except Exception as ai_err:
|
| 134 |
+
logger.warning(f"Lokal AI upscale xatosi (Kutubxona yetishmayotgan bo'lishi mumkin): {ai_err}")
|
| 135 |
+
|
| 136 |
+
# 4. YECHIM Fallback: LAB CLAHE va Matematik HDR tizimi (Agar AI ishlamasa)
|
| 137 |
+
if not ai_upscaled:
|
| 138 |
+
logger.info("Lokal AI ishlamadi. Matematik HDR (LAB CLAHE) ga o'tildi.")
|
| 139 |
+
height, width = img.shape[:2]
|
| 140 |
+
new_size = (width * scale, height * scale)
|
| 141 |
+
upscaled = cv2.resize(img, new_size, interpolation=cv2.INTER_LANCZOS4)
|
| 142 |
+
|
| 143 |
+
# Rasmni rang intensivligi asosida piksellash (HDR effekti uchun L-channel CLAHE)
|
| 144 |
+
lab = cv2.cvtColor(upscaled, cv2.COLOR_BGR2LAB)
|
| 145 |
+
l, a, b = cv2.split(lab)
|
| 146 |
+
clahe = cv2.createCLAHE(clipLimit=1.8, tileGridSize=(8, 8))
|
| 147 |
+
cl = clahe.apply(l)
|
| 148 |
+
merged = cv2.merge((cl, a, b))
|
| 149 |
+
upscaled = cv2.cvtColor(merged, cv2.COLOR_LAB2BGR)
|
| 150 |
+
|
| 151 |
+
# Yakuniy ishlov (Shovqinni ozgina maydalash)
|
| 152 |
+
upscaled = cv2.fastNlMeansDenoisingColored(upscaled, None, 3, 3, 5, 15)
|
| 153 |
|
| 154 |
+
# O'tkirlik va kontrastni tabiiy kuchaytirish (Plastmassa darajasiga kirtimaydi)
|
| 155 |
pill_img = Image.fromarray(cv2.cvtColor(upscaled, cv2.COLOR_BGR2RGB))
|
|
|
|
|
|
|
| 156 |
enhancer = ImageEnhance.Sharpness(pill_img)
|
| 157 |
+
pill_img = enhancer.enhance(1.3)
|
| 158 |
enhancer_c = ImageEnhance.Contrast(pill_img)
|
| 159 |
+
pill_img = enhancer_c.enhance(1.05)
|
| 160 |
|
| 161 |
upscaled_final = cv2.cvtColor(np.array(pill_img), cv2.COLOR_RGB2BGR)
|
| 162 |
cv2.imwrite(output_path, upscaled_final)
|
| 163 |
+
|
| 164 |
+
# Agar rasm aqlqili yozilgan bo'lsa qaytarish
|
| 165 |
+
return output_path if os.path.exists(output_path) else None
|
| 166 |
except Exception as e:
|
| 167 |
+
logger.error(f"Upscale rasm xatosi (Asosiy block): {e}")
|
| 168 |
return None
|
| 169 |
|
| 170 |
def _apply_video_transform(video_path, output_path, transform_func, progress_callback=None, fps_override=None):
|
|
|
|
| 234 |
|
| 235 |
|
| 236 |
def process_video_upscale(video_path, output_path, progress_callback=None):
|
| 237 |
+
"""Videoning sifatini (o'lcham va o'tkirlik) optimallashtirilgan Matematik HDR bilan oshiradi."""
|
| 238 |
def upscale_frame(frame):
|
| 239 |
bgr = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
|
| 240 |
h, w = bgr.shape[:2]
|
|
|
|
| 241 |
|
| 242 |
+
# 1.5 baravar asossli kattalashtirish (Lanczos4 usuli - eng sifatlisi)
|
| 243 |
+
upscaled = cv2.resize(bgr, (int(w * 1.5), int(h * 1.5)), interpolation=cv2.INTER_LANCZOS4)
|
| 244 |
+
|
| 245 |
+
# LAB kanalida micro-contrast va HDR yoritish (CLAHE)
|
| 246 |
+
lab = cv2.cvtColor(upscaled, cv2.COLOR_BGR2LAB)
|
| 247 |
+
l, a, b = cv2.split(lab)
|
| 248 |
+
clahe = cv2.createCLAHE(clipLimit=1.5, tileGridSize=(8, 8))
|
| 249 |
+
cl = clahe.apply(l)
|
| 250 |
+
merged = cv2.merge((cl, a, b))
|
| 251 |
+
upscaled = cv2.cvtColor(merged, cv2.COLOR_LAB2BGR)
|
| 252 |
+
|
| 253 |
+
# Yumshoq "Unsharp Mask" bilan HD xususiyatini o'tkirlashtirish
|
| 254 |
+
gaussian = cv2.GaussianBlur(upscaled, (0, 0), 2.0)
|
| 255 |
+
unsharp = cv2.addWeighted(upscaled, 1.3, gaussian, -0.3, 0)
|
| 256 |
+
|
| 257 |
+
return cv2.cvtColor(unsharp, cv2.COLOR_BGR2RGB)
|
| 258 |
|
| 259 |
return _apply_video_transform(video_path, output_path, upscale_frame, progress_callback)
|
| 260 |
|
|
|
|
| 1224 |
cum_a += da
|
| 1225 |
trajectory.append((cum_x, cum_y, cum_a))
|
| 1226 |
|
| 1227 |
+
# L1-Optimized Trajectory Smoothing (scipy gaussian smoothing)
|
| 1228 |
+
def l1_smooth_trajectory(values, radius):
|
| 1229 |
+
"""Ilg'or filtering orqali haqiqiy Adobe Premiere kabi keskinlikni o'ldirish."""
|
| 1230 |
+
try:
|
| 1231 |
+
from scipy.ndimage import gaussian_filter1d
|
| 1232 |
+
return gaussian_filter1d(values, sigma=radius/2.5)
|
| 1233 |
+
except ImportError:
|
| 1234 |
+
# Agar scipy bo'lmasa fallback smooth
|
| 1235 |
+
n = len(values)
|
| 1236 |
+
smoothed = np.zeros(n)
|
| 1237 |
+
for i in range(n):
|
| 1238 |
+
start = max(0, i - radius)
|
| 1239 |
+
end = min(n, i + radius + 1)
|
| 1240 |
+
smoothed[i] = np.mean(values[start:end])
|
| 1241 |
+
return smoothed
|
| 1242 |
|
| 1243 |
traj_x = np.array([t[0] for t in trajectory])
|
| 1244 |
traj_y = np.array([t[1] for t in trajectory])
|
| 1245 |
traj_a = np.array([t[2] for t in trajectory])
|
| 1246 |
|
| 1247 |
+
# Trajectoryani tekislash
|
| 1248 |
+
smooth_x = l1_smooth_trajectory(traj_x, smoothing_radius)
|
| 1249 |
+
smooth_y = l1_smooth_trajectory(traj_y, smoothing_radius)
|
| 1250 |
+
smooth_a = l1_smooth_trajectory(traj_a, smoothing_radius)
|
| 1251 |
|
| 1252 |
# Tuzatish = tekislangan - asl trajectory
|
| 1253 |
diff_x = smooth_x - traj_x
|
|
|
|
| 1270 |
|
| 1271 |
cap = cv2.VideoCapture(video_path)
|
| 1272 |
|
| 1273 |
+
# Dinamik Inpainting uchun Original o'lchamni saqlab qolish
|
| 1274 |
+
out_w = width
|
| 1275 |
+
out_h = height
|
|
|
|
|
|
|
|
|
|
| 1276 |
|
| 1277 |
temp_video_path = output_path + "_stab_temp.avi"
|
| 1278 |
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
|
| 1279 |
writer = cv2.VideoWriter(temp_video_path, fourcc, fps, (out_w, out_h))
|
| 1280 |
|
| 1281 |
+
# Masshtabni ozgina (1.04) kattalashtirish orqali chetkalarni inpainting bilan qoplash matritsasi
|
| 1282 |
+
scale_dynamic_mat = cv2.getRotationMatrix2D((width / 2, height / 2), 0, 1.04)
|
| 1283 |
+
|
| 1284 |
+
ret, prev_first_frame = cap.read()
|
| 1285 |
if not ret:
|
| 1286 |
cap.release()
|
| 1287 |
return None
|
| 1288 |
|
| 1289 |
+
writer.write(prev_first_frame)
|
|
|
|
|
|
|
| 1290 |
|
| 1291 |
for i in range(len(smooth_transforms)):
|
| 1292 |
ret, frame = cap.read()
|
|
|
|
| 1303 |
[sin_a, cos_a, dy]
|
| 1304 |
], dtype=np.float64)
|
| 1305 |
|
| 1306 |
+
# Transformatsiyani qo'llash (BORDER_REFLECT_101 va Inpainting)
|
| 1307 |
stabilized = cv2.warpAffine(
|
| 1308 |
frame, transform_mat, (width, height),
|
| 1309 |
+
flags=cv2.INTER_LINEAR,
|
| 1310 |
+
borderMode=cv2.BORDER_REFLECT_101
|
| 1311 |
+
)
|
| 1312 |
+
|
| 1313 |
+
# Chekkalarda qora chiziq qolmasligi uchun 4% scale kattalashtirish qatlamini qo'llash
|
| 1314 |
+
final_stabilized = cv2.warpAffine(
|
| 1315 |
+
stabilized, scale_dynamic_mat, (width, height),
|
| 1316 |
+
flags=cv2.INTER_LINEAR,
|
| 1317 |
borderMode=cv2.BORDER_REFLECT_101
|
| 1318 |
)
|
| 1319 |
|
| 1320 |
+
writer.write(final_stabilized)
|
|
|
|
|
|
|
| 1321 |
|
| 1322 |
if progress_callback and i % 5 == 0:
|
| 1323 |
progress_callback(min(95, 55 + int(i / len(smooth_transforms) * 40)))
|
requirements.txt
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
python-telegram-bot[job-queue]
|
| 2 |
-
opencv-python
|
| 3 |
Pillow
|
| 4 |
moviepy
|
| 5 |
torch
|
|
|
|
| 1 |
python-telegram-bot[job-queue]
|
| 2 |
+
opencv-contrib-python
|
| 3 |
Pillow
|
| 4 |
moviepy
|
| 5 |
torch
|