{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceType":"competition","sourceId":52950,"databundleVersionId":5973250}],"dockerImageVersionId":31259,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"Uses data from Kaggle competition: https://www.kaggle.com/competitions/asl-fingerspelling","metadata":{}},{"cell_type":"markdown","source":"## Landmark visualization\nAdapted from https://www.kaggle.com/code/nadigshreekanth/data-visualization-using-mediapipe-apis\n& https://colab.research.google.com/github/googlesamples/mediapipe/blob/main/examples/hand_landmarker/python/hand_landmarker.ipynb","metadata":{}},{"cell_type":"code","source":"!pip install mediapipe","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-21T07:34:05.000498Z","iopub.execute_input":"2026-02-21T07:34:05.000822Z","iopub.status.idle":"2026-02-21T07:34:12.889762Z","shell.execute_reply.started":"2026-02-21T07:34:05.000784Z","shell.execute_reply":"2026-02-21T07:34:12.888596Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport pyarrow.parquet as pq\nimport matplotlib.pyplot as plt","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-21T07:34:12.892221Z","iopub.execute_input":"2026-02-21T07:34:12.892719Z","iopub.status.idle":"2026-02-21T07:34:13.269068Z","shell.execute_reply.started":"2026-02-21T07:34:12.89268Z","shell.execute_reply":"2026-02-21T07:34:13.268276Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def get_hands(seq_df):\n    import mediapipe as mp\n    from mediapipe.tasks.python.components.containers.landmark import NormalizedLandmark\n    #import numpy as np\n    \n    mp_hands = mp.tasks.vision.HandLandmarksConnections\n    mp_drawing = mp.tasks.vision.drawing_utils\n    mp_drawing_styles = mp.tasks.vision.drawing_styles\n    \n    images = []\n    all_hand_landmarks = []\n    for seq_idx in range(len(seq_df)):\n        x_pose = seq_df.iloc[seq_idx].filter(regex=\"x_right_hand.*\").values\n        y_pose = seq_df.iloc[seq_idx].filter(regex=\"y_right_hand.*\").values\n        z_pose = seq_df.iloc[seq_idx].filter(regex=\"z_right_hand.*\").values\n\n        right_hand_landmarks = [NormalizedLandmark(x, y, z) for x, y, z in zip(x_pose, y_pose, z_pose)]\n\n        right_hand_image = np.zeros((900, 600, 3), dtype=\"int8\")\n\n        mp_drawing.draw_landmarks(\n              right_hand_image,\n              right_hand_landmarks,\n              mp_hands.HAND_CONNECTIONS,\n              mp_drawing_styles.get_default_hand_landmarks_style(),\n              mp_drawing_styles.get_default_hand_connections_style())\n        \n        x_pose = seq_df.iloc[seq_idx].filter(regex=\"x_left_hand.*\").values\n        y_pose = seq_df.iloc[seq_idx].filter(regex=\"y_left_hand.*\").values\n        z_pose = seq_df.iloc[seq_idx].filter(regex=\"z_left_hand.*\").values\n\n        left_hand_landmarks = [NormalizedLandmark(x, y, z) for x, y, z in zip(x_pose, y_pose, z_pose)]\n        \n        left_hand_image = np.zeros((900, 600, 3), dtype=\"int8\")\n\n        mp_drawing.draw_landmarks(\n                left_hand_image,\n                left_hand_landmarks,\n                mp_hands.HAND_CONNECTIONS,\n                mp_drawing_styles.get_default_hand_landmarks_style(),\n                mp_drawing_styles.get_default_hand_connections_style())\n        \n        images.append([right_hand_image.astype(np.uint8), left_hand_image.astype(np.uint8)])\n        all_hand_landmarks.append([right_hand_landmarks, left_hand_landmarks])\n    return images, all_hand_landmarks","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-21T07:34:13.270417Z","iopub.execute_input":"2026-02-21T07:34:13.271015Z","iopub.status.idle":"2026-02-21T07:34:13.283014Z","shell.execute_reply.started":"2026-02-21T07:34:13.27096Z","shell.execute_reply":"2026-02-21T07:34:13.281866Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from matplotlib import animation, rc\nrc('animation', html='jshtml')\n\ndef create_animation(images):\n    fig = plt.figure(figsize=(2, 3))\n    ax = plt.Axes(fig, [0., 0., 1., 1.])\n    ax.set_axis_off()\n    fig.add_axes(ax)\n    im=ax.imshow(images[0], cmap=\"gray\")\n    plt.close(fig)\n    \n    def animate_func(i):\n        im.set_array(images[i])\n        return [im]\n\n    return animation.FuncAnimation(fig, animate_func, frames=len(images), interval=1000/10)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-21T07:34:13.286336Z","iopub.execute_input":"2026-02-21T07:34:13.286699Z","iopub.status.idle":"2026-02-21T07:34:13.308005Z","shell.execute_reply.started":"2026-02-21T07:34:13.28667Z","shell.execute_reply":"2026-02-21T07:34:13.306835Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train = pd.read_csv(\"/kaggle/input/asl-fingerspelling/train.csv\")\ntrain.head(10)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-21T07:34:13.3097Z","iopub.execute_input":"2026-02-21T07:34:13.310106Z","iopub.status.idle":"2026-02-21T07:34:13.440103Z","shell.execute_reply.started":"2026-02-21T07:34:13.310049Z","shell.execute_reply":"2026-02-21T07:34:13.439258Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"seq_id=1817141095\nfile_id=train.loc[train['sequence_id']==seq_id, 'file_id'].iloc[0]\npath = f\"/kaggle/input/asl-fingerspelling/train_landmarks/{file_id}.parquet\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-21T07:34:13.44138Z","iopub.execute_input":"2026-02-21T07:34:13.44176Z","iopub.status.idle":"2026-02-21T07:34:13.448462Z","shell.execute_reply.started":"2026-02-21T07:34:13.441714Z","shell.execute_reply":"2026-02-21T07:34:13.447638Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df=pq.read_table(\n    path,\n    filters=[['sequence_id', '=', seq_id]]\n).to_pandas()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-21T07:34:13.469465Z","iopub.execute_input":"2026-02-21T07:34:13.469843Z","iopub.status.idle":"2026-02-21T07:34:14.90473Z","shell.execute_reply.started":"2026-02-21T07:34:13.469801Z","shell.execute_reply":"2026-02-21T07:34:14.90362Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# df corresponds to a selected sequence\ndf.index.unique()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-21T07:34:14.906272Z","iopub.execute_input":"2026-02-21T07:34:14.906706Z","iopub.status.idle":"2026-02-21T07:34:14.914051Z","shell.execute_reply.started":"2026-02-21T07:34:14.906665Z","shell.execute_reply":"2026-02-21T07:34:14.913119Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-21T07:34:14.915301Z","iopub.execute_input":"2026-02-21T07:34:14.915683Z","iopub.status.idle":"2026-02-21T07:34:14.935608Z","shell.execute_reply.started":"2026-02-21T07:34:14.915646Z","shell.execute_reply":"2026-02-21T07:34:14.93443Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"hand_images, hand_landmarks = get_hands(df)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-21T07:34:14.936777Z","iopub.execute_input":"2026-02-21T07:34:14.937828Z","iopub.status.idle":"2026-02-21T07:34:38.299923Z","shell.execute_reply.started":"2026-02-21T07:34:14.937796Z","shell.execute_reply":"2026-02-21T07:34:38.29848Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"create_animation(np.array(hand_images)[:, 0])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-21T07:34:38.301694Z","iopub.execute_input":"2026-02-21T07:34:38.302488Z","iopub.status.idle":"2026-02-21T07:34:44.563676Z","shell.execute_reply.started":"2026-02-21T07:34:38.302451Z","shell.execute_reply":"2026-02-21T07:34:44.562496Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}