Mr-HASSAN commited on
Commit
fa53bfa
·
verified ·
1 Parent(s): 3cb49a8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +46 -32
app.py CHANGED
@@ -5,15 +5,10 @@ import google.generativeai as genai
5
  from ultralytics import YOLO
6
  import tempfile
7
  import torch
 
8
 
9
  # =============================
10
- # اختيار الجهاز (GPU / CPU)
11
- # =============================
12
- DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
13
- print(f"🚀 Using device: {DEVICE}")
14
-
15
- # =============================
16
- # إعداد مفتاح Gemini (مكتوب صريح في الكود)
17
  # =============================
18
 
19
  GEMINI_API_KEY = "AIzaSyAvm28ZnTMaZ1Jtg9sYM-EO4qlAN2W4BIQ"
@@ -31,7 +26,6 @@ SYSTEM_PROMPT = (
31
  )
32
 
33
 
34
-
35
  def fix_with_gemini(raw_text: str) -> str:
36
  if not raw_text:
37
  return ""
@@ -45,18 +39,18 @@ def fix_with_gemini(raw_text: str) -> str:
45
 
46
 
47
  # =============================
48
- # إعدادات YOLO + السرعة
49
  # =============================
50
 
51
  WEIGHTS_PATH = "best.pt"
52
  IMG_SIZE = 320
53
- CONF_THRESHOLD = 0.25 # خفضناها عشان يسوي ديتكشن أسهل
54
 
55
  # إعدادات تجميع الحروف
56
- MIN_STABLE_FRAMES = 1 # اعتبر الحرف من أول مرة للاستكشاف
57
- FRAME_SKIP = 1 # حلّل كل فريم (مع GPU تقدر تخليه 1)
58
- MAX_FRAMES = 1000 # حد أقصى للفريمات
59
- WORD_GAP_FRAMES = 10 # فجوة (بدون حروف) لنهاية الكلمة
60
 
61
  arabic_map = {
62
  "aleff": "ا",
@@ -93,21 +87,41 @@ arabic_map = {
93
  "la": "لا",
94
  }
95
 
96
- print("🔹 Loading YOLO model...")
97
- model = YOLO(WEIGHTS_PATH)
 
98
 
99
- # ننقل الموديل إلى كرت الشاشة لو موجود
100
- try:
101
- model.to(DEVICE)
102
- print("✅ YOLO model moved to", DEVICE)
103
- except Exception as e:
104
- print("⚠️ تعذر نقل الموديل إلى الجهاز:", e)
105
 
106
- print("📚 Classes:", model.names)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
 
108
 
109
  # =============================
110
- # ضغط الفيديو قبل المعالجة (دقة 360p تقريباً + تقليل FPS)
111
  # =============================
112
 
113
  def preprocess_video(input_path: str, target_width: int = 640, target_fps: int = 8) -> str:
@@ -131,7 +145,6 @@ def preprocess_video(input_path: str, target_width: int = 640, target_fps: int =
131
  frame_step = max(1, int(round(orig_fps / target_fps)))
132
  out_fps = orig_fps / frame_step
133
 
134
- # ارتفاع النسخة 360p تقريباً حسب نسبة الأبعاد
135
  target_height = int(target_width * h / w)
136
 
137
  fd, tmp_path = tempfile.mkstemp(suffix=".mp4")
@@ -146,7 +159,6 @@ def preprocess_video(input_path: str, target_width: int = 640, target_fps: int =
146
  if not ret:
147
  break
148
 
149
- # نأخذ كل frame_step فريم واحد فقط
150
  if frame_idx % frame_step == 0:
151
  resized = cv2.resize(frame, (target_width, target_height), interpolation=cv2.INTER_AREA)
152
  out.write(resized)
@@ -160,17 +172,19 @@ def preprocess_video(input_path: str, target_width: int = 640, target_fps: int =
160
 
161
 
162
  # =============================
163
- # معالجة فريم واحد (YOLO على GPU)
164
  # =============================
165
 
166
  def detect_frame(frame_bgr):
 
 
167
  frame_rgb = cv2.cvtColor(frame_bgr, cv2.COLOR_BGR2RGB)
168
  result = model.predict(
169
  frame_rgb,
170
  conf=CONF_THRESHOLD,
171
  imgsz=IMG_SIZE,
172
  verbose=False,
173
- device=DEVICE # هنا نحدد إنه يشتغل على cuda لو متوفر
174
  )[0]
175
 
176
  boxes = result.boxes
@@ -222,7 +236,7 @@ def extract_and_render(video_path: str):
222
  height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
223
 
224
  if fps <= 0:
225
- fps = 8.0 # fallback
226
 
227
  out = cv2.VideoWriter(out_path, fourcc, fps, (width, height))
228
 
@@ -285,16 +299,16 @@ def extract_and_render(video_path: str):
285
 
286
 
287
  # =============================
288
- # Gradio واجهة كاملة
289
  # =============================
290
 
 
291
  def run(file):
292
  if file is None:
293
  return "لم يتم رفع فيديو", "", None
294
 
295
  video_path = file.name
296
 
297
- # خطوة تسريع الفيديو قبل التحليل (360p + ~8fps)
298
  light_path = preprocess_video(video_path, target_width=640, target_fps=8)
299
 
300
  raw, processed_path = extract_and_render(light_path)
@@ -307,7 +321,7 @@ def run(file):
307
 
308
 
309
  with gr.Blocks() as demo:
310
- gr.Markdown("## 🤟 ASL → Arabic (YOLO + Gemini) مع إعادة فيديو المعالجة 🎥 نسخة GPU")
311
 
312
  inp = gr.File(label="ارفع فيديو الإشارة")
313
  raw = gr.Textbox(label="النص الخام", lines=3)
 
5
  from ultralytics import YOLO
6
  import tempfile
7
  import torch
8
+ import spaces # مهم لـ @spaces.GPU
9
 
10
  # =============================
11
+ # إعداد مفتاح Gemini (حطه هنا)
 
 
 
 
 
 
12
  # =============================
13
 
14
  GEMINI_API_KEY = "AIzaSyAvm28ZnTMaZ1Jtg9sYM-EO4qlAN2W4BIQ"
 
26
  )
27
 
28
 
 
29
  def fix_with_gemini(raw_text: str) -> str:
30
  if not raw_text:
31
  return ""
 
39
 
40
 
41
  # =============================
42
+ # إعدادات YOLO + متغيرات عامة
43
  # =============================
44
 
45
  WEIGHTS_PATH = "best.pt"
46
  IMG_SIZE = 320
47
+ CONF_THRESHOLD = 0.25 # تخفيض للسهولة
48
 
49
  # إعدادات تجميع الحروف
50
+ MIN_STABLE_FRAMES = 1
51
+ FRAME_SKIP = 1
52
+ MAX_FRAMES = 1000
53
+ WORD_GAP_FRAMES = 10
54
 
55
  arabic_map = {
56
  "aleff": "ا",
 
87
  "la": "لا",
88
  }
89
 
90
+ # هنستخدم موديل عالمي لكن نحمّله عند أول استخدام فقط
91
+ yolo_model = None
92
+ DEVICE = "cpu"
93
 
 
 
 
 
 
 
94
 
95
+ def get_model():
96
+ """
97
+ يحمّل YOLO مرة واحدة، ويحاول نقله لـ GPU لو متوفر.
98
+ يُستدعى داخل دالة عليها @spaces.GPU بعد ما الـ GPU يشتغل فعليًا.
99
+ """
100
+ global yolo_model, DEVICE
101
+
102
+ if yolo_model is None:
103
+ print("🔹 Loading YOLO model...")
104
+ yolo_model = YOLO(WEIGHTS_PATH)
105
+ print("📚 Classes:", yolo_model.names)
106
+
107
+ # نعيد التحقق من CUDA هنا (بعد ما GPU يشتغل في Spaces)
108
+ if torch.cuda.is_available():
109
+ if DEVICE != "cuda":
110
+ DEVICE = "cuda"
111
+ try:
112
+ yolo_model.to(DEVICE)
113
+ print("✅ YOLO model moved to cuda")
114
+ except Exception as e:
115
+ print("⚠️ تعذر نقل الموديل إلى cuda:", e)
116
+ else:
117
+ DEVICE = "cpu"
118
+ print("⚠️ CUDA غير متوفر، سيتم استخدام CPU.")
119
+
120
+ return yolo_model
121
 
122
 
123
  # =============================
124
+ # ضغط الفيديو قبل المعالجة
125
  # =============================
126
 
127
  def preprocess_video(input_path: str, target_width: int = 640, target_fps: int = 8) -> str:
 
145
  frame_step = max(1, int(round(orig_fps / target_fps)))
146
  out_fps = orig_fps / frame_step
147
 
 
148
  target_height = int(target_width * h / w)
149
 
150
  fd, tmp_path = tempfile.mkstemp(suffix=".mp4")
 
159
  if not ret:
160
  break
161
 
 
162
  if frame_idx % frame_step == 0:
163
  resized = cv2.resize(frame, (target_width, target_height), interpolation=cv2.INTER_AREA)
164
  out.write(resized)
 
172
 
173
 
174
  # =============================
175
+ # معالجة فريم واحد
176
  # =============================
177
 
178
  def detect_frame(frame_bgr):
179
+ model = get_model() # نتأكد الموديل جاهز وعلى الجهاز الصحيح
180
+
181
  frame_rgb = cv2.cvtColor(frame_bgr, cv2.COLOR_BGR2RGB)
182
  result = model.predict(
183
  frame_rgb,
184
  conf=CONF_THRESHOLD,
185
  imgsz=IMG_SIZE,
186
  verbose=False,
187
+ device=DEVICE, # cuda أو cpu حسب المتاح
188
  )[0]
189
 
190
  boxes = result.boxes
 
236
  height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
237
 
238
  if fps <= 0:
239
+ fps = 8.0
240
 
241
  out = cv2.VideoWriter(out_path, fourcc, fps, (width, height))
242
 
 
299
 
300
 
301
  # =============================
302
+ # Gradio + @spaces.GPU
303
  # =============================
304
 
305
+ @spaces.GPU # هذا اللي يرضي Hugging Face ويشغّل GPU on demand
306
  def run(file):
307
  if file is None:
308
  return "لم يتم رفع فيديو", "", None
309
 
310
  video_path = file.name
311
 
 
312
  light_path = preprocess_video(video_path, target_width=640, target_fps=8)
313
 
314
  raw, processed_path = extract_and_render(light_path)
 
321
 
322
 
323
  with gr.Blocks() as demo:
324
+ gr.Markdown("## 🤟 ASL → Arabic (YOLO + Gemini) نسخة GPU على Hugging Face Spaces")
325
 
326
  inp = gr.File(label="ارفع فيديو الإشارة")
327
  raw = gr.Textbox(label="النص الخام", lines=3)