CoolFace
Apppublic

ahmedda/Arabic-Sign-Language-API

sourceHugging Faceupdated 6mo agoView on Hugging Face
0likes
app.py94 linesDownload Raw Back to root
1from fastapi import FastAPI, UploadFile, File, Form, HTTPException
2import tensorflow as tf
3from PIL import Image
4import io, base64, numpy as np
5import pandas as pd
6import re
7
8app = FastAPI(title="Sign ↔ Text API")
9
10# دالة تنظيف وتوحيد النص العربي
11def normalize_arabic(text):
12    text = str(text).strip()
13    text = re.sub("[إأآ]", "ا", text)
14    text = re.sub("ة", "ه", text)
15    return text
16
17# 1. تحميل ملف الإكسل وعمل القاموس
18word_to_id = {}
19try:
20    file_name = "KARSL-100_Labels (1).xlsx"
21    df = pd.read_excel(file_name)
22    df.columns = [str(col).strip() for col in df.columns]
23    
24    if 'Sign-Arabic' in df.columns and 'SignID' in df.columns:
25        for index, row in df.iterrows():
26            if pd.notna(row['Sign-Arabic']):
27                key = normalize_arabic(row['Sign-Arabic'])
28                word_to_id[key] = row['SignID']
29        print(f"✅ تم تحميل {len(word_to_id)} كلمة بنجاح")
30except Exception as e:
31    print(f"❌ خطأ في الإكسل: {e}")
32
33# 2. تحميل الموديلات
34try:
35    sign_to_text_model = tf.keras.models.load_model("best_model.h5", compile=False)
36    text_to_sign_model = tf.keras.models.load_model("word_to_sign_model.h5", compile=False)
37    print("✅ تم تحميل الموديلات بنجاح")
38except Exception as e:
39    print(f"❌ خطأ في الموديلات: {e}")
40
41@app.post("/text-to-sign")
42async def text_to_sign(text: str = Form(...)):
43    try:
44        clean_text = normalize_arabic(text)
45        label_id = word_to_id.get(clean_text)
46        
47        if label_id is None:
48            raise ValueError(f"الكلمة '{text}' مش موجودة في الإكسل.")
49
50        # --- الحل الجذري لمشكلة الـ Shape (100) ---
51        # بنعمل مصفوفة فيها 100 صفر
52        one_hot_input = np.zeros((1, 100), dtype=np.float32)
53        
54        # بننور الرقم بتاع الكلمة (مثلاً 72) بنخلي قيمته 1
55        # ملحوظة: لو الـ IDs في الإكسل بتبدأ من 1، بنطرح 1 عشان الـ index بيبدأ من 0
56        idx = int(label_id) - 1 if int(label_id) > 0 else 0
57        
58        if idx < 100:
59            one_hot_input[0, idx] = 1.0
60        else:
61            raise ValueError(f"الـ ID رقم {label_id} أكبر من حجم الموديل (100)")
62
63        # التوقع (دلوقتي الـ Shape بقا 100 ومظبوط)
64        prediction = text_to_sign_model.predict(one_hot_input)
65        # ---------------------------------------
66
67        if isinstance(prediction, np.ndarray):
68            img_data = prediction[0]
69            if img_data.max() <= 1.0: img_data = (img_data * 255).astype("uint8")
70            else: img_data = img_data.astype("uint8")
71            
72            if len(img_data.shape) == 3 and img_data.shape[-1] == 1:
73                img_data = img_data.reshape(img_data.shape[0], img_data.shape[1])
74            img = Image.fromarray(img_data)
75        else:
76            img = prediction
77
78        buf = io.BytesIO()
79        img.save(buf, format="PNG")
80        encoded = base64.b64encode(buf.getvalue()).decode("utf-8")
81
82        return {
83            "status": "success",
84            "word": clean_text,
85            "sign_id": int(label_id),
86            "image_base64": encoded
87        }
88
89    except Exception as e:
90        raise HTTPException(status_code=500, detail=f"خطأ في الموديل: {str(e)}")
91
92if __name__ == "__main__":
93    import uvicorn
94    uvicorn.run(app, host="0.0.0.0", port=8000)