Hardware components | ||||||
| × | 1 | ||||
![]() |
| × | 1 | |||
Software apps and online services | ||||||
![]() |
| |||||
| ||||||
| ||||||
| ||||||
| ||||||
| ||||||
| ||||||
| ||||||
| ||||||
![]() |
| |||||
|
Goal
This project aim to construct an automatic sign language recognition system for deaf (and mute) people to translate their sign language into text for a conversation and education app purpose.
The main goal is to give more help for people with disabilities in communicating easily and integrate them more in the society.
Introduction
As a target reference, manual signs for letters in the American Sign Language are used for training and testing the system.
American Sign Language (ASL) is a vibrant and complex visual language used primarily by the Deaf community in the United States and parts of Canada. Unlike spoken languages, ASL relies on hand shapes, movements, facial expressions, and body postures to convey meaning.
Linguistic Features: ASL is a complete language with its own grammar and syntax, distinct from English. It includes unique features such as:
- Manual Signs: Hand shapes, orientations, and movements.
- Non-manual Signals: Facial expressions, head movements, and shoulder raises.
- Spatial Grammar: Use of space to indicate relationships and actions.
Cultural Significance: ASL is more than just a means of communication; it is a cornerstone of Deaf culture. It fosters a sense of identity and community among its users. Deaf culture values visual communication and has its own traditions, norms, and social practices.
Learning ASL: ASL is increasingly being taught in schools and universities as a second language. It is also used by hearing individuals who have Deaf family members or who work in professions that require communication with the Deaf community.
ASL is a rich, expressive language that continues to evolve and thrive, playing a crucial role in the lives of many people around the world.
Setup
Steps
Results
The video below illustrates recognition of letters in the american sign language in the model test phase before using the NPU on AMD Ryzen AI processor.
Conclusion and perspectives
Regarding the tests the system can recognize different letters , but confuses with some of them.
Due to some technical issues (poor internet connection and the lack of available time), the system was tested arround a small version of the model:`yolo_nas_s`, which i recommended for real time and less precise use case. More large versions are availables : `yolo_nas_m` for medium and `yolo_nas_l`for large model and more precise.
Some technical issues were faced to make the model runing in the NPU in an indepedent way from the CPU, but the work is steel in progress and it will be updated even after contest ends.
As a furether improvement, more complex models will be used with more fine tuning.
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "LA9VI44c_Dex"
},
"source": [
"#** This code is a modified version of moin faisal's notebook to work on jupyter **\n",
"#** It is based on David LEE's dataset and work **\n",
"#** https://github.com/insigh1/Interactive_ABCs_with_American_Sign_Language_using_Yolov5.git **\n",
"#** under creativecommons.org licence**\n",
"#**due to poor internet connection and the lack of available time, a small version of the model is used `yolo_nas_s`."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "LA9VI44c_Dex"
},
"source": [
"#**Step 01: Installing the Packages**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "IrOIVb4g-9LV"
},
"outputs": [],
"source": [
"#%%capture\n",
"!pip install Cython\n",
"!pip install super-gradients==3.7.1\n",
"!pip install imutils\n",
"!pip install roboflow\n",
"!pip install pytube --upgrade\n",
"!pip install numpy==1.23.0\n",
"!pip install torchmetric==0.8.2\n",
"!pip install --default-timeout=1000 pandas\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "1GFVbqbnzlEP"
},
"source": [
"# **It is recommended to restart the Kernel**"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "8vj6ZhW5_ZiD"
},
"source": [
"#Step 02: Importing all the required libraries from super-gradients"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"id": "aiOenmAUA-2h"
},
"outputs": [],
"source": [
"from super_gradients.training import Trainer\n",
"from super_gradients.training import dataloaders\n",
"from super_gradients.training.dataloaders.dataloaders import coco_detection_yolo_format_train, coco_detection_yolo_format_val\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"id": "aiOenmAUA-2h"
},
"outputs": [],
"source": [
"from IPython.display import clear_output\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "Zy94Z08FCC9R"
},
"outputs": [],
"source": [
"from super_gradients.training.losses import PPYoloELoss\n",
"from super_gradients.training.metrics import DetectionMetrics_050\n",
"from super_gradients.training.models.detection_models.pp_yolo_e import PPYoloEPostPredictionCallback\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "vI9gsW6MJm9Y"
},
"outputs": [],
"source": [
"from super_gradients.training import models\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "2xSiKzfx_t9q"
},
"source": [
"#**Step 03: Setting a checkpoint directory and experiment name | Instantiated the trainer**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "caMG2wHQ_huB"
},
"outputs": [],
"source": [
"CHECKPOINT_DIR = 'checkpoints2'\n",
"trainer = Trainer(experiment_name='sign_yolonas_run2', ckpt_root_dir=CHECKPOINT_DIR)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "63PxbjJi_4jr"
},
"source": [
"#**Step 04: Exporting the Dataset from Roboflow into the Notebook**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "fHu6ewi2AABm",
"outputId": "6493b94f-9b92-4ca5-a0c8-9652c757c4b8"
},
"outputs": [],
"source": [
"!pip install roboflow\n",
"\n",
"from roboflow import Roboflow\n",
"rf = Roboflow(api_key=\"IuYv6KOKs5p62rFSLvGa\")\n",
"project = rf.workspace(\"david-lee-d0rhs\").project(\"american-sign-language-letters\")\n",
"dataset = project.version(6).download(\"yolov5\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ELYsCvoQANtB"
},
"source": [
"#**Step 05: Load your dataset parameters into a dictionary**"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "-SUct0GrAUV6"
},
"source": [
"You'll need to load your dataset parameters into a dictionary, specifically defining:\n",
"\n",
"- path to the parent directory where your data lives\n",
"- the child directory names for training, validation, and test (if you have testing set) images and labels\n",
"- class names"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "l8caxCpbASNj"
},
"outputs": [],
"source": [
"dataset_params = {\n",
" 'data_dir':'/content/American-Sign-Language-Letters-6',\n",
" 'train_images_dir':'train/images',\n",
" 'train_labels_dir':'train/labels',\n",
" 'val_images_dir':'valid/images',\n",
" 'val_labels_dir':'valid/labels',\n",
" 'test_images_dir':'test/images',\n",
" 'test_labels_dir':'test/labels',\n",
" 'classes': ['A', 'B', 'C', 'D', 'E', 'F', 'G','H', 'I', 'J', 'K', 'L','M','N','O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']\n",
"}\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "hciE-i_lA4zb"
},
"source": [
"#**Step 06: Pass the values for `dataset_params` into the `dataset_params` argument.**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "AiptliRUAq7Q",
"outputId": "61cf3b91-316b-4111-82b8-7ee18922c98e"
},
"outputs": [],
"source": [
"train_data = coco_detection_yolo_format_train(\n",
" dataset_params={\n",
" 'data_dir': dataset_params['data_dir'],\n",
" 'images_dir': dataset_params['train_images_dir'],\n",
" 'labels_dir': dataset_params['train_labels_dir'],\n",
" 'classes': dataset_params['classes']\n",
" },\n",
" dataloader_params={\n",
" 'batch_size':16,\n",
" 'num_workers':2\n",
" }\n",
")\n",
"\n",
"val_data = coco_detection_yolo_format_val(\n",
" dataset_params={\n",
" 'data_dir': dataset_params['data_dir'],\n",
" 'images_dir': dataset_params['val_images_dir'],\n",
" 'labels_dir': dataset_params['val_labels_dir'],\n",
" 'classes': dataset_params['classes']\n",
" },\n",
" dataloader_params={\n",
" 'batch_size':16,\n",
" 'num_workers':2\n",
" }\n",
")\n",
"\n",
"test_data = coco_detection_yolo_format_val(\n",
" dataset_params={\n",
" 'data_dir': dataset_params['data_dir'],\n",
" 'images_dir': dataset_params['test_images_dir'],\n",
" 'labels_dir': dataset_params['test_labels_dir'],\n",
" 'classes': dataset_params['classes']\n",
" },\n",
" dataloader_params={\n",
" 'batch_size':16,\n",
" 'num_workers':2\n",
" }\n",
")\n",
"\n",
"clear_output()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "RlzcTycuBN96"
},
"source": [
"#**Step 07: Inspect the Dataset Defined Earlier**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "n5d34uc6BBxz",
"outputId": "31de9d51-bfe5-4020-bd60-677923e49616"
},
"outputs": [],
"source": [
"train_data.dataset.transforms"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "HmSxlyhMBSsI",
"outputId": "ea719cb6-2073-4cf4-e65e-3983e949bfcf"
},
"outputs": [],
"source": [
"train_data.dataset.dataset_params['transforms'][1]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "jB92edn6BYE_"
},
"outputs": [],
"source": [
"train_data.dataset.dataset_params['transforms'][1]['DetectionRandomAffine']['degrees'] = 10.42"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Mxhxz9S3Bc_p"
},
"source": [
"#**Step 08: Plot a batch of training data with their augmentations applied to see what they look like**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 910
},
"id": "pMcKP5srBZKN",
"outputId": "d360f8d7-83fd-4553-fb49-183dbe49a77e"
},
"outputs": [],
"source": [
"train_data.dataset.plot()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "KdteZXfTBqu8"
},
"source": [
"#**Step 09: Instantiating the model**"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ZHAZf-u-B01b"
},
"source": [
"You saw how to instantiate the model for inference earlier.\n",
"Below is how to instantiate the model for finetuning.We need to add the `num_classes` argument here.\n",
"#**due to poor internet connection and the lack of available time, a small version of the model is used `yolo_nas_s` for real time and less precise, but SuperGradients has two other flavors of YOLONAS available : `yolo_nas_m` for medium and `yolo_nas_l`for large but more precise ."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "UanFJaQKBz2B",
"outputId": "ebaea68c-7ed1-4c95-9c86-c604643f5908"
},
"outputs": [],
"source": [
"model = models.get('yolo_nas_s',\n",
" num_classes=len(dataset_params['classes']),\n",
" pretrained_weights=\"coco\"\n",
" )"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "f6kMerfuCKBb"
},
"source": [
"#**Step 10: Define metrics and training parameters**\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "vPMB5je6CYn1"
},
"source": [
"We need to define the training parameters for training session.\n",
"\n",
"Full details about the training parameters can be found [here](https://github.com/Deci-AI/super-gradients/blob/master/src/super_gradients/recipes/training_hyperparams/default_train_params.yaml).\n",
"\n",
"\n",
"### There are a few **mandatory** arguments that we must define for training params \n",
"\n",
"- `max_epochs` - Max number of training epochs\n",
"\n",
"- `loss` - the loss function you want to use\n",
"\n",
"- `optimizer` - Optimizer you will be using\n",
"\n",
"- `train_metrics_list` - Metrics to log during training\n",
"\n",
"- `valid_metrics_list` - Metrics to log during training\n",
"\n",
"- `metric_to_watch` - metric which the model checkpoint will be saved according to\n",
"\n",
"We can choose from a variety of `optimizer`'s such as: Adam, AdamW, SGD, Lion, or RMSProps. If you choose to change the defualt parameters of these optimizrs you pass them into `optimizer_params`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "xdPgBDSSCTkp"
},
"outputs": [],
"source": [
"train_params = {\n",
" # ENABLING SILENT MODE\n",
" 'silent_mode': True,\n",
" \"average_best_models\":True,\n",
" \"warmup_mode\": \"linear_epoch_step\",\n",
" \"warmup_initial_lr\": 1e-6,\n",
" \"lr_warmup_epochs\": 3,\n",
" \"initial_lr\": 5e-4,\n",
" \"lr_mode\": \"cosine\",\n",
" \"cosine_final_lr_ratio\": 0.1,\n",
" \"optimizer\": \"Adam\",\n",
" \"optimizer_params\": {\"weight_decay\": 0.0001},\n",
" \"zero_weight_decay_on_bias_and_bn\": True,\n",
" \"ema\": True,\n",
" \"ema_params\": {\"decay\": 0.9, \"decay_type\": \"threshold\"},\n",
" # ONLY TRAINING FOR 10 EPOCHS FOR THIS EXAMPLE NOTEBOOK\n",
" \"max_epochs\": 25,\n",
" \"mixed_precision\": True,\n",
" \"loss\": PPYoloELoss(\n",
" use_static_assigner=False,\n",
" # NOTE: num_classes needs to be defined here\n",
" num_classes=len(dataset_params['classes']),\n",
" reg_max=16\n",
" ),\n",
" \"valid_metrics_list\": [\n",
" DetectionMetrics_050(\n",
" score_thres=0.1,\n",
" top_k_predictions=300,\n",
" # NOTE: num_classes needs to be defined here\n",
" num_cls=len(dataset_params['classes']),\n",
" normalize_targets=True,\n",
" post_prediction_callback=PPYoloEPostPredictionCallback(\n",
" score_threshold=0.01,\n",
" nms_top_k=1000,\n",
" max_predictions=300,\n",
" nms_threshold=0.7\n",
" )\n",
" )\n",
" ],\n",
" \"metric_to_watch\": 'mAP@0.50'\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "msdWxrVMDGji"
},
"source": [
"#**Step 11: Download the Demo Videos**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "ArXeDFXq-DGn",
"outputId": "b84e9b3c-e09d-46fc-81ec-2d9a1a63334b"
},
"outputs": [],
"source": [
"!gdown \"https://drive.google.com/uc?id=1bLlfh9gr6JxE9Wacw4xgv5FNijA7j9GZ&confirm=t\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "O3E9ECpo-DJ3",
"outputId": "0a704ba3-0ae2-414b-9289-5ef70b6c86c8"
},
"outputs": [],
"source": [
"!gdown \"https://drive.google.com/uc?id=1kju9OOo05c5XTfrKuLvsZcxu_NPloQk_&confirm=t\""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "riHN7oz9CugX"
},
"source": [
"#**Step 12: Training the model**\n",
"After instantiating the trainer, defining the dataset parameters and dataloaders, Instantiating the model and setting up training parameters; we can proceed with training the model using a SuperGradients by using the `trainer`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "d_lFrW51BhYo",
"outputId": "388cd761-b2aa-4164-fcfa-359dc2c1f745"
},
"outputs": [],
"source": [
"trainer.train(model=model,\n",
" training_params=train_params,\n",
" train_loader=train_data,\n",
" valid_loader=val_data)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "VWrhOdu7Mxdi"
},
"source": [
"#**Step 13: Get the best trained model**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 176
},
"id": "CJQBe5WdDYs-",
"outputId": "40a14f51-afdd-4bec-a03e-5bcae0845788"
},
"outputs": [],
"source": [
"best_model = models.get('yolo_nas_s',\n",
" num_classes=len(dataset_params['classes']),\n",
" checkpoint_path=\"checkpoints2/sign_yolonas_run2/ckpt_best.pth\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "j-qT7GHNNiS5"
},
"source": [
"#**Step 14: Evaluating the best trained model on the test set**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "YcuZNYAzNgPH",
"outputId": "a603ecd1-3ea8-4775-896e-20204e44b20a"
},
"outputs": [],
"source": [
"trainer.test(model=best_model,\n",
" test_loader=test_data,\n",
" test_metrics_list=DetectionMetrics_050(score_thres=0.1,\n",
" top_k_predictions=300,\n",
" num_cls=len(dataset_params['classes']),\n",
" normalize_targets=True,\n",
" post_prediction_callback=PPYoloEPostPredictionCallback(score_threshold=0.01,\n",
" nms_top_k=1000,\n",
" max_predictions=300,\n",
" nms_threshold=0.7)\n",
" ))"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "tFtxr3jfNq-T"
},
"source": [
"#**Step 15: Predicting with the best model- test on a sample image**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"background_save": true,
"base_uri": "https://localhost:8080/",
"height": 1000
},
"id": "5CFS5fxGNoJO",
"outputId": "a0c343b2-655f-4046-bd09-4bd22a35255b"
},
"outputs": [],
"source": [
"img_url = '/content/American-Sign-Language-Letters-6/valid/images/B5_jpg.rf.e1802440715c4bbb6de84d150dfe73b8.jpg'\n",
"best_model.predict(img_url).show()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "AndGR9tmcscm"
},
"source": [
"#**Step 16: Testing on Video 1**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "DNV5L1Z3Nzg0"
},
"outputs": [],
"source": [
"input_video_path = f\"/content/demonew1.mp4\"\n",
"output_video_path = \"vid1.mp4\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "B8YhhjpROBCZ"
},
"outputs": [],
"source": [
"import torch\n",
"device = 'cuda' if torch.cuda.is_available() else \"cpu\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "P2lSX_LuOBFY",
"outputId": "8ec1c6fe-c828-4bcc-e88d-fd702d449a2c"
},
"outputs": [],
"source": [
"best_model.to(device).predict(input_video_path).save(output_video_path)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "vjF4U-gsajOE"
},
"source": [
"#**Display the Output Video**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "XUv3BeouOHBN"
},
"outputs": [],
"source": [
"!rm '/content/result_compressed.mp4'"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 247
},
"id": "Hkc-Jwj-aqzU",
"outputId": "a2f897be-febd-441f-fd77-fb7946e2eec3"
},
"outputs": [],
"source": [
"from IPython.display import HTML\n",
"from base64 import b64encode\n",
"import os\n",
"\n",
"# Input video path\n",
"save_path = '/content/vid1.mp4'\n",
"\n",
"# Compressed video path\n",
"compressed_path = \"/content/result_compressed.mp4\"\n",
"\n",
"os.system(f\"ffmpeg -i {save_path} -vcodec libx264 {compressed_path}\")\n",
"\n",
"# Show video\n",
"mp4 = open(compressed_path,'rb').read()\n",
"data_url = \"data:video/mp4;base64,\" + b64encode(mp4).decode()\n",
"HTML(\"\"\"\n",
"<video width=400 controls>\n",
" <source src=\"%s\" type=\"video/mp4\">\n",
"</video>\n",
"\"\"\" % data_url)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "9coK1U08c0nM"
},
"source": [
"#**Step 17: Testing on Video 2**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "EQg3eojHcgQ3"
},
"outputs": [],
"source": [
"input_video_path = f\"/content/demo5.mp4\"\n",
"output_video_path = \"vid2.mp4\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "WOY2o3G3cgVX"
},
"outputs": [],
"source": [
"import torch\n",
"device = 'cuda' if torch.cuda.is_available() else \"cpu\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "QaEiPXNScgY_",
"outputId": "ccb00a5b-ef6b-46d1-8da6-8037bb1863d9"
},
"outputs": [],
"source": [
"best_model.to(device).predict(input_video_path).save(output_video_path)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "qcraVqkqc4fq"
},
"source": [
"#**Display the Output Video**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "2yhkqTg7cgbn"
},
"outputs": [],
"source": [
"!rm '/content/result_compressed.mp4'"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 247
},
"id": "Id8Xn-Ugasgs",
"outputId": "78056b6a-c86a-4c9b-92c3-91766c7838a2"
},
"outputs": [],
"source": [
"from IPython.display import HTML\n",
"from base64 import b64encode\n",
"import os\n",
"\n",
"# Input video path\n",
"save_path = '/content/vid2.mp4'\n",
"\n",
"# Compressed video path\n",
"compressed_path = \"/content/result_compressed.mp4\"\n",
"\n",
"os.system(f\"ffmpeg -i {save_path} -vcodec libx264 {compressed_path}\")\n",
"\n",
"# Show video\n",
"mp4 = open(compressed_path,'rb').read()\n",
"data_url = \"data:video/mp4;base64,\" + b64encode(mp4).decode()\n",
"HTML(\"\"\"\n",
"<video width=400 controls>\n",
" <source src=\"%s\" type=\"video/mp4\">\n",
"</video>\n",
"\"\"\" % data_url)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "FoR4nWHEv9yt"
},
"outputs": [],
"source": []
}
],
"metadata": {
"accelerator": "GPU",
"colab": {
"gpuType": "T4",
"provenance": []
},
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.18"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Comments