{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[],"dockerImageVersionId":28755,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install mediapipe==0.10.35 -q\n!pip install opencv-python-headless -q","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport cv2\nimport numpy as np\nimport pickle\nimport pandas as pd\nfrom sklearn.ensemble import RandomForestClassifier\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import accuracy_score, classification_report\nfrom tqdm import tqdm\nimport mediapipe as mp\nfrom mediapipe.tasks import python\nfrom mediapipe.tasks.python import vision\nimport urllib.request\n\n# Download hand landmarker model\nprint(\"Downloading hand landmarker model...\")\nmodel_url = 'https://storage.googleapis.com/mediapipe-models/hand_landmarker/hand_landmarker/float16/1/hand_landmarker.task'\nurllib.request.urlretrieve(model_url, 'hand_landmarker.task')\nprint(\"Downloaded!\")\n\nbase_options = python.BaseOptions(model_asset_path='hand_landmarker.task')\noptions = vision.HandLandmarkerOptions(\n    base_options=base_options,\n    num_hands=1,\n    min_hand_detection_confidence=0.5\n)\ndetector = vision.HandLandmarker.create_from_options(options)\n\ndef extract_landmarks_from_image(img):\n    try:\n        rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        mp_image = mp.Image(image_format=mp.ImageFormat.SRGB, data=rgb)\n        result = detector.detect(mp_image)\n        if not result.hand_landmarks:\n            return None\n        landmarks = []\n        for lm in result.hand_landmarks[0]:\n            landmarks.extend([lm.x, lm.y, lm.z])\n        return landmarks if len(landmarks) == 63 else None\n    except:\n        return None\n\n# Alphabets + space + del + nothing\nALPHABET = [\n    'A','B','C','D','E','F','G','H','I','J',\n    'K','L','M','N','O','P','Q','R','S','T',\n    'U','V','W','X','Y','Z',\n    'space','del','nothing'\n]\n\nX = []\ny = []\n\nprint(\"\\nLoading ASL Alphabet dataset...\")\nasl_path = '/kaggle/input/datasets/grassknoted/asl-alphabet/asl_alphabet_train/asl_alphabet_train'\n\nfor label in tqdm(ALPHABET):\n    folder = os.path.join(asl_path, label)\n    if not os.path.exists(folder):\n        print(f\"Missing: {label}\")\n        continue\n    count = 0\n    for img_file in os.listdir(folder):\n        if count >= 1000:  # 1000 per sign for better accuracy\n            break\n        img = cv2.imread(os.path.join(folder, img_file))\n        if img is None:\n            continue\n        landmarks = extract_landmarks_from_image(img)\n        if landmarks:\n            X.append(landmarks)\n            y.append(label)\n            count += 1\n\nprint(f\"✅ Total samples: {len(X)}\")\nprint(f\"✅ Total signs: {len(set(y))}\")\n\nX_final = np.array(X)\ny_final = np.array(y)\n\n# Remove signs with less than 2 samples\nfrom collections import Counter\nlabel_counts = Counter(y_final)\nvalid_mask = np.array([label_counts[label] >= 2 for label in y_final])\nX_final = X_final[valid_mask]\ny_final = y_final[valid_mask]\nprint(f\"After filtering: {len(X_final)} samples, {len(set(y_final))} signs\")\n\nX_train, X_test, y_train, y_test = train_test_split(\n    X_final, y_final,\n    test_size=0.2,\n    random_state=42,\n    stratify=y_final\n)\n\nprint(f\"\\nTraining: {len(X_train)} | Testing: {len(X_test)}\")\nprint(\"\\n🤖 Training Random Forest...\")\n\nmodel = RandomForestClassifier(\n    n_estimators=500,\n    max_depth=30,\n    random_state=42,\n    n_jobs=-1,\n    verbose=1\n)\nmodel.fit(X_train, y_train)\n\ny_pred = model.predict(X_test)\naccuracy = accuracy_score(y_test, y_pred)\nprint(f\"\\n🎯 Accuracy: {accuracy * 100:.2f}%\")\nprint(\"\\n📊 Per sign accuracy:\")\nprint(classification_report(y_test, y_pred))\n\nwith open('/kaggle/working/model_alpha.pkl', 'wb') as f:\n    pickle.dump(model, f)\n\nwith open('/kaggle/working/labels_alpha.pkl', 'wb') as f:\n    pickle.dump(ALPHABET, f)\n\nprint(\"\\n✅ model_alpha.pkl saved!\")\nprint(\"✅ labels_alpha.pkl saved!\")\nprint(\"🎉 Alphabet training complete!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-06-09T02:45:49.361182Z","iopub.execute_input":"2026-06-09T02:45:49.361934Z","iopub.status.idle":"2026-06-09T03:06:20.701452Z","shell.execute_reply.started":"2026-06-09T02:45:49.361902Z","shell.execute_reply":"2026-06-09T03:06:20.700556Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\n# Find exact dataset paths\nprint(\"All input datasets:\")\nfor item in os.listdir('/kaggle/input'):\n    print(item)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\n# Check datasets folder\nprint(\"=== DATASETS ===\")\ndatasets_path = '/kaggle/input/datasets'\nif os.path.exists(datasets_path):\n    for item in os.listdir(datasets_path):\n        print(item)\n\n# Check competitions folder        \nprint(\"\\n=== COMPETITIONS ===\")\ncomp_path = '/kaggle/input/competitions'\nif os.path.exists(comp_path):\n    for item in os.listdir(comp_path):\n        print(item)\n\n# Full recursive search\nprint(\"\\n=== FULL SEARCH ===\")\nfor root, dirs, files in os.walk('/kaggle/input'):\n    level = root.replace('/kaggle/input', '').count(os.sep)\n    if level < 3:\n        print(root)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\n# Check grassknoted dataset\nprint(\"=== ASL ALPHABET ===\")\nfor root, dirs, files in os.walk('/kaggle/input/datasets/grassknoted'):\n    level = root.replace('/kaggle/input/datasets/grassknoted', '').count(os.sep)\n    if level < 3:\n        print(root)\n        if files:\n            print(\"  Files:\", files[:3])\n\n# Check asl-signs competition\nprint(\"\\n=== ASL SIGNS ===\")\nfor root, dirs, files in os.walk('/kaggle/input/competitions/asl-signs'):\n    level = root.replace('/kaggle/input/competitions/asl-signs', '').count(os.sep)\n    if level < 3:\n        print(root)\n        if files:\n            print(\"  Files:\", files[:3])","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}