Merge pull request #935 from NickHerrig/cookbooks/add-visuals

Cookbooks/add visuals
This commit is contained in:
Piotr Skalski authored and GitHub committed 2024-02-29 10:36:16 +01:00
commit 07763bb2d0
3 files changed
+524 -140

No files matched your search

+277 -82
View File
@@ -2,7 +2,9 @@
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"metadata": {
"id": "TfUZYrKbqlF7"
},
"source": [
"# Annotate Video with Detections\n",
"\n",
@@ -10,9 +12,72 @@
"\n",
"[![Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/roboflow/supervision/blob/develop/docs/notebooks/annotate-video-with-detections.ipynb)\n",
"\n",
"One of the most common requirements of computer vision applications is detecting objects in images and displaying bounding boxes around those objects. In this cookbook we'll walk through the steps on how to utilize the open source Roboflow ecosystem to accomplish this task on a video. Let's dive in! \n",
"One of the most common requirements of computer vision applications is detecting objects in images and displaying bounding boxes around those objects. In this cookbook we'll walk through the steps on how to utilize the open source Roboflow ecosystem to accomplish this task on a video. Let's dive in!"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "rUo1u17yqlF9"
},
"source": [
"## Before you start\n",
"\n",
"## Installing Dependencies \n",
"Let's make sure that we have access to GPU. We can use `nvidia-smi` command to do that. In case of any problems navigate to `Edit` -> `Notebook settings` -> `Hardware accelerator`, set it to `GPU`, and then click `Save`."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "0Er370WTqlF9",
"outputId": "57b00a1e-87ea-4912-b4f9-5b94f0e6bf48",
"vscode": {
"languageId": "shellscript"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Fri Feb 23 03:15:00 2024 \n",
"+---------------------------------------------------------------------------------------+\n",
"| NVIDIA-SMI 535.104.05 Driver Version: 535.104.05 CUDA Version: 12.2 |\n",
"|-----------------------------------------+----------------------+----------------------+\n",
"| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |\n",
"| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |\n",
"| | | MIG M. |\n",
"|=========================================+======================+======================|\n",
"| 0 Tesla V100-SXM2-16GB Off | 00000000:00:04.0 Off | 0 |\n",
"| N/A 33C P0 24W / 300W | 0MiB / 16384MiB | 0% Default |\n",
"| | | N/A |\n",
"+-----------------------------------------+----------------------+----------------------+\n",
" \n",
"+---------------------------------------------------------------------------------------+\n",
"| Processes: |\n",
"| GPU GI CI PID Type Process name GPU Memory |\n",
"| ID ID Usage |\n",
"|=======================================================================================|\n",
"| No running processes found |\n",
"+---------------------------------------------------------------------------------------+\n"
]
}
],
"source": [
"!nvidia-smi"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "WuSnN7ejqlF-"
},
"source": [
"## Installing Dependencies\n",
"\n",
"In this cookbook we'll be utilizing the open source packages [Inference](https://inference.roboflow.com/) and [Supervision](https://supervision.roboflow.com/latest/) to accomplish our goals. Let's get those installed in our notebook with pip."
]
@@ -21,40 +86,68 @@
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "1YgQGum4qlF-",
"vscode": {
"languageId": "shellscript"
}
},
"outputs": [],
"source": [
"\n",
"!pip install -q inference \"supervision[assets]\""
"!pip install -q inference-gpu \"supervision[assets]\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"metadata": {
"id": "PZRnzh7EqlF-"
},
"source": [
"## Download a Video Asset\n",
"\n",
"First, let's download a video that we can detect objects in. Supervision comes with a great utility called Assets to help us hit the ground running. Wehn we run this script, the video is saved in our local directory and can be accessed with the variable `path_to_video`."
"First, let's download a video that we can detect objects in. Supervision comes with a great utility called Assets to help us hit the ground running. When we run this script, the video is saved in our local directory and can be accessed with the variable `path_to_video`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"metadata": {
"id": "NMg4KOFiqlF-"
},
"outputs": [],
"source": [
"from supervision.assets import download_assets, VideoAssets\n",
"\n",
"# Download a supervision video asset \n",
"# Download a supervision video asset\n",
"path_to_video = download_assets(VideoAssets.PEOPLE_WALKING)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"metadata": {
"id": "x93oxF0zrQOU"
},
"source": [
"As a result, we've downloaded a video. Let's take a look at the video below. Keep in mind that the video preview below works only in the web version of the cookbooks and not in Google Colab.\n",
"\n",
"<div style=\"display: flex; justify-content: center;\">\n",
" <video controls width=\"1000\"\">\n",
" <source\n",
" src=\"https://media.roboflow.com/supervision/video-examples/people-walking.mp4\"\n",
" type=\"video/mp4\"\n",
" >\n",
" </video>\n",
"</div>\n",
"\n",
"\n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "T8bU7fQ6qlF-"
},
"source": [
"## Detecting Objects\n",
"\n",
@@ -63,128 +156,230 @@
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"execution_count": 4,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "hlONWHfQqlF-",
"outputId": "81b277fb-ea7c-4242-f49d-5af0c665ea58"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Detections(xyxy=array([[1140., 951., 1245., 1079.],\n",
" [ 666., 648., 745., 854.],\n",
" [ 34., 794., 142., 990.],\n",
" [1140., 505., 1211., 657.],\n",
" [ 260., 438., 332., 612.],\n",
" [1413., 702., 1523., 887.],\n",
" [1462., 472., 1543., 643.],\n",
" [1446., 318., 1516., 483.],\n",
" [ 753., 451., 821., 623.],\n",
" [ 924., 172., 983., 307.],\n",
" [1791., 144., 1852., 275.],\n",
" [ 93., 132., 146., 251.],\n",
" [ 708., 240., 765., 388.],\n",
" [ 200., 44., 267., 161.],\n",
" [1204., 131., 1255., 266.],\n",
" [ 569., 267., 628., 408.],\n",
" [1163., 150., 1210., 280.],\n",
" [ 799., 78., 847., 204.],\n",
" [1690., 152., 1751., 283.],\n",
" [ 344., 495., 396., 641.],\n",
" [1722., 77., 1782., 178.]]),\n",
" mask=None,\n",
" confidence=array([0.83215541, 0.80572134, 0.7919845 , 0.7912274 , 0.77121079,\n",
" 0.7599591 , 0.75711554, 0.75494027, 0.73076195, 0.71452248,\n",
" 0.69572842, 0.65269446, 0.63952065, 0.62914598, 0.61361706,\n",
" 0.5968492 , 0.55311316, 0.5470854 , 0.54070991, 0.52209878,\n",
" 0.41217673]),\n",
" class_id=array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),\n",
" tracker_id=None,\n",
" data={'class_name': array(['person', 'person', 'person', 'person', 'person', 'person',\n",
" 'person', 'person', 'person', 'person', 'person', 'person',\n",
" 'person', 'person', 'person', 'person', 'person', 'person',\n",
" 'person', 'person', 'person'], dtype='<U6')})\n"
]
}
],
"source": [
"import supervision as sv\n",
"from supervision.assets import download_assets, VideoAssets\n",
"from inference.models.utils import get_roboflow_model\n",
"\n",
"\n",
"if __name__ == \"__main__\":\n",
" # Download the video asset from Supervision assets.\n",
" PATH_TO_VIDEO = download_assets(VideoAssets.PEOPLE_WALKING)\n",
"# Load a yolov8 model from roboflow.\n",
"model = get_roboflow_model(\"yolov8s-640\")\n",
"\n",
" # Load a yolov8 nano model from roboflow.\n",
" model = get_roboflow_model(\"yolov8n-640\")\n",
"# Create a frame generator and video info object from supervision utilities.\n",
"frame_generator = sv.get_video_frames_generator(path_to_video)\n",
"\n",
" # Create a frame generator and video info object from supervision utilities.\n",
" frame_generator = sv.get_video_frames_generator(PATH_TO_VIDEO)\n",
"# Yield a single frame from the generator.\n",
"frame = next(frame_generator)\n",
"\n",
" # Yield a single frame from the generator.\n",
" frame = next(frame_generator)\n",
"# Run inference on our frame\n",
"result = model.infer(frame)[0]\n",
"\n",
" # Run inference on our frame.\n",
" result = model.infer(frame)[0]\n",
"# Parse result into detections data model.\n",
"detections = sv.Detections.from_inference(result)\n",
"\n",
" # Parse result into detections data model.\n",
" detections = sv.Detections.from_inference(result)\n",
"\n",
" # Display the detections data model.\n",
" print(detections)"
"# Pretty Print the resulting detections.\n",
"from pprint import pprint\n",
"pprint(detections)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"metadata": {
"id": "mL7QrQvyqlF-"
},
"source": [
"First, we load our model using the method `get_roboflow_model()`. Notice how we pass in a `model_id`? We're using an [alias](https://inference.roboflow.com/reference_pages/model_aliases/) here. This is where we can pass in other models from Roboflow Universe like this [rock, paper, scissors](https://universe.roboflow.com/roboflow-58fyf/rock-paper-scissors-sxsw) model utilizing our roboflow api key. \n",
"First, we load our model using the method `get_roboflow_model()`. Notice how we pass in a `model_id`? We're using an [alias](https://inference.roboflow.com/reference_pages/model_aliases/) here. This is where we can pass in other models from Roboflow Universe like this [rock, paper, scissors](https://universe.roboflow.com/roboflow-58fyf/rock-paper-scissors-sxsw) model utilizing our roboflow api key.\n",
"\n",
"```\n",
"model = get_roboflow_mode(\n",
" model_id=\"rock-paper-scissors-sxsw/11\", \n",
" model_id=\"rock-paper-scissors-sxsw/11\",\n",
" api_key=\"roboflow_private_api_key\"\n",
")\n",
"```\n",
"\n",
"If you don't have an api key, you can [create an free Roboflow account](https://app.roboflow.com/login). This model wouldn't be much help with detecting people, but it's a nice exercise to see how our code becomes model agnostic!\n",
"\n",
"We then create a `frame_generator` object and yeild a single frame for inference using `next()`. We pass our frame to `model.infer()` to run inference, then pass that data into a little helpfer function called `sv.Detections.from_inference()` to parse it. Lastly we print our detections to show we are in fact detecting a few people in the frame! \n",
"We then create a `frame_generator` object and yeild a single frame for inference using `next()`. We pass our frame to `model.infer()` to run inference. After, we pass that data into a little helpfer function called `sv.Detections.from_inference()` to parse it. Lastly we print our detections to show we are in fact detecting a few people in the frame!"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "tM6geyUBwdej"
},
"source": [
"## Annotaing the Frame with Bounding Boxes\n",
"\n",
"## Saving Bounding Boxes to the Video\n",
"Now that we're detecting images, let's get to the fun part. Let's annotate the frame and display the bounding boxes on the frame."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 560
},
"id": "8gkUxKei0RaV",
"outputId": "84a95332-70cf-4f26-c4bb-15479afafd04"
},
"outputs": [
{
"data": {
"image/png": "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 truncated
"text/plain": [
"<Figure size 1200x1200 with 1 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Create a bounding box annotator object.\n",
"bounding_box = sv.BoundingBoxAnnotator()\n",
"\n",
"Now comes the fun part. Let's wrap up our code by utilizing `Annotators` and a `VideoSink` to draw bounding boxes and save the resulting video respectively. Take a peak at the final code example below. This might can take up to a minute to run, since we're processing a full video. "
"# Annotate our frame with detections.\n",
"annotated_frame = bounding_box.annotate(scene=frame.copy(), detections=detections)\n",
"\n",
"# Display the frame.\n",
"sv.plot_image(annotated_frame)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "o8SsyCid6YV3"
},
"source": [
"Notice that we create a `box_annoator` variable by initalizing a [BoundingBoxAnnotator](https://supervision.roboflow.com/latest/annotators/#boundingboxannotator). We can change the color and thickness, but for simplicity we keep the defaults. There are a ton of easy to use [annotators](https://supervision.roboflow.com/latest/annotators/) available in the Supervision package other than a bounding box that are fun to play with."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "gKHSYO14vGC7"
},
"source": [
"## Saving Bounding Boxes to a Video\n",
"\n",
"Let's wrap up our code by utilizing a `VideoSink` to draw bounding boxes and save the resulting video. Take a peak at the final code example below. This can take a couple minutes deppending on your runtime and since since we're processing a full video. Feel free to skip ahead to see the resulting video."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"metadata": {
"id": "Es4SUdPGqlF-"
},
"outputs": [],
"source": [
"import supervision as sv\n",
"from supervision.assets import download_assets, VideoAssets\n",
"from inference.models.utils import get_roboflow_model\n",
"from tqdm import tqdm\n",
"\n",
"# Create a video_info object for use in the VideoSink.\n",
"video_info = sv.VideoInfo.from_video_path(video_path=path_to_video)\n",
"\n",
"if __name__ == \"__main__\":\n",
" # Download the video asset from Supervision assets.\n",
" PATH_TO_VIDEO = download_assets(VideoAssets.PEOPLE_WALKING)\n",
"# Create a VideoSink context manager to save our frames.\n",
"with sv.VideoSink(target_path=\"output.mp4\", video_info=video_info) as sink:\n",
"\n",
" # Load a yolov8 nano model from roboflow.\n",
" model = get_roboflow_model(\"yolov8n-640\")\n",
" # Iterate through frames yielded from the frame_generator.\n",
" for frame in tqdm(frame_generator, total=video_info.total_frames):\n",
"\n",
" # Initalize the bounding box frame annotator.\n",
" box_annotator = sv.BoundingBoxAnnotator()\n",
" # Run inference on our frame.\n",
" result = model.infer(frame)[0]\n",
"\n",
" # Create a frame generator object from video path.\n",
" frame_generator = sv.get_video_frames_generator(PATH_TO_VIDEO)\n",
" # Parse the result into the detections data model.\n",
" detections = sv.Detections.from_inference(result)\n",
"\n",
" # Create a video info object from video path.\n",
" video_info = sv.VideoInfo.from_video_path(PATH_TO_VIDEO)\n",
" # Apply bounding box to detections on a copy of the frame.\n",
" annotated_frame = bounding_box.annotate(\n",
" scene=frame.copy(),\n",
" detections=detections\n",
" )\n",
"\n",
" # Use a VideoSink context manager for saving frames of a video.\n",
" with sv.VideoSink(target_path=\"output.mp4\", video_info=video_info) as sink:\n",
"\n",
" # Iterate through frames yielded from the frame_generator.\n",
" for frame in frame_generator:\n",
"\n",
" # Run inference on our frame.\n",
" result = model.infer(frame)[0]\n",
"\n",
" # Parse the result into the detections data model.\n",
" detections = sv.Detections.from_inference(result)\n",
"\n",
" # Apply bounding box to detections on a copy of the frame.\n",
" annotated_frame = box_annotator.annotate(\n",
" scene=frame.copy(), \n",
" detections=detections\n",
" )\n",
"\n",
" # Write the annotated frame to the video sink.\n",
" sink.write_frame(frame=annotated_frame)"
" # Write the annotated frame to the video sink.\n",
" sink.write_frame(frame=annotated_frame)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"metadata": {
"id": "EXTE3zWxqlF-"
},
"source": [
" Notice that we create a `box_annoator` variable by initalizing a [BoundingBoxAnnotator](https://supervision.roboflow.com/latest/annotators/#boundingboxannotator). We can change the color and thickness, but for simplicity we keep the defaults. There are a ton of easy to use [annotators](https://supervision.roboflow.com/latest/annotators/) available in the Supervision package other than a bounding box that are fun to play with. Next, we create a `video_info` variable to pass information about the video to our `VideoSink`. The `VideoSink` is a cool little context manager that allows us to `write_frames()` to a video ouput file. Prior to writing the frame, we annotate a copy of it utilizing `box_annotator.annotate()`. Let's take a look at the resulting video. It will be installed locally and is called `output.mp4`. When run, you will see bounding boxes around the detections. Pretty awesome! "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We only scratched the surface of all of the customizable Annotators and additional features that Supervision and Inference have to offer. Stay tuned for more cookbooks on how to take advantge of them in your computer vision applications. Happy building! "
"<div style=\"display: flex; justify-content: center;\">\n",
" <video controls width=\"1000\">\n",
" <source\n",
" src=\"https://storage.googleapis.com/com-roboflow-marketing/supervision/cookbooks/annotate-video-with-detections.mp4\"\n",
" type=\"video/mp4\"\n",
" >\n",
" </video>\n",
"</div>\n",
"<br>\n",
"\n",
"\n",
"In the code above we've created a`video_info` variable to pass information about the video to our `VideoSink`. The `VideoSink` is a cool little context manager that allows us to `write_frames()` to a video ouput file. We're also optionally using `tqdm` to display a progress bar with a % complete. We only scratched the surface of all of the customizable Annotators and additional features that Supervision and Inference have to offer. Stay tuned for more cookbooks on how to take advantge of them in your computer vision applications. Happy building! \ud83d\ude80"
]
}
],
"metadata": {
"accelerator": "GPU",
"colab": {
"gpuType": "V100",
"provenance": []
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
@@ -197,9 +392,9 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.7"
"version": "3.11.8"
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 0
}
+25 -3
View File
@@ -17,7 +17,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 10,
"metadata": {
"vscode": {
"languageId": "shellscript"
@@ -45,6 +45,7 @@
"source": [
"from supervision.assets import download_assets, VideoAssets\n",
"\n",
"# Download the a video of the subway.\n",
"path_to_video = download_assets(VideoAssets.SUBWAY)"
]
},
@@ -52,7 +53,28 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"We're now equipt with a video asset from Supervision to run some experiments on! For more information on available video assets, visit the [Supervision API Reference](https://supervision.roboflow.com/latest/assets/#videoassets). Happy building!"
"With this, we now have a high quality video asset for use in demos. Let's take a look at what we downloaded. Keep in mind that the video preview below works only in the web version of the cookbooks and not in Google Colab.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<div style=\"display: flex; justify-content: center;\">\n",
" <video controls width=\"320\" height=\"240\">\n",
" <source\n",
" src=\"https://media.roboflow.com/supervision/video-examples/subway.mp4\"\n",
" type=\"video/mp4\"\n",
" >\n",
" </video>\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We're now equipt with a video asset from Supervision to run some experiments on! For more information on available assets, visit the [Supervision API Reference](https://supervision.roboflow.com/latest/assets). Happy building!"
]
}
],
@@ -72,7 +94,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.7"
"version": "3.11.8"
}
},
"nbformat": 4,
+222 -55
View File
@@ -2,7 +2,9 @@
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"metadata": {
"id": "BsraWznGULVc"
},
"source": [
"# Object Tracking\n",
"\n",
@@ -14,8 +16,71 @@
"\n",
"## What is a Tracker?\n",
"\n",
"Trackers are a piece of code that identifies objects across frames and assigns them a unique `tracker_id`. There are a few popular trackers at the time of writing this including ByteTrack and Bot-SORT. Supervision makes using trackers a breeze and comes with ByteTrack built-in. But first, let's get our deppendencies installed. \n",
"Trackers are a piece of code that identifies objects across frames and assigns them a unique `tracker_id`. There are a few popular trackers at the time of writing this including ByteTrack and Bot-SORT. Supervision makes using trackers a breeze and comes with ByteTrack built-in."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "7h__vutkUZSY"
},
"source": [
"## Before you start\n",
"\n",
"Let's make sure that we have access to GPU. We can use `nvidia-smi` command to do that. In case of any problems navigate to `Edit` -> `Notebook settings` -> `Hardware accelerator`, set it to `GPU`, and then click `Save`."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "pzm2gQlYUbmd",
"outputId": "71217cbf-f7d0-4496-c150-1c363386a16f",
"vscode": {
"languageId": "shellscript"
}
},
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Fri Feb 23 03:18:02 2024 \n",
"+---------------------------------------------------------------------------------------+\n",
"| NVIDIA-SMI 535.104.05 Driver Version: 535.104.05 CUDA Version: 12.2 |\n",
"|-----------------------------------------+----------------------+----------------------+\n",
"| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |\n",
"| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |\n",
"| | | MIG M. |\n",
"|=========================================+======================+======================|\n",
"| 0 Tesla V100-SXM2-16GB Off | 00000000:00:04.0 Off | 0 |\n",
"| N/A 33C P0 24W / 300W | 0MiB / 16384MiB | 0% Default |\n",
"| | | N/A |\n",
"+-----------------------------------------+----------------------+----------------------+\n",
" \n",
"+---------------------------------------------------------------------------------------+\n",
"| Processes: |\n",
"| GPU GI CI PID Type Process name GPU Memory |\n",
"| ID ID Usage |\n",
"|=======================================================================================|\n",
"| No running processes found |\n",
"+---------------------------------------------------------------------------------------+\n"
]
}
],
"source": [
"!nvidia-smi"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ZI4EwAnEUTFC"
},
"source": [
"## Install Dependencies"
]
},
@@ -23,18 +88,18 @@
"cell_type": "code",
"execution_count": null,
"metadata": {
"vscode": {
"languageId": "powershell"
}
"id": "NaEjHlAWULVd"
},
"outputs": [],
"source": [
"!pip install -q inference \"supervision[assets]\""
"!pip install -q inference-gpu \"supervision[assets]\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"metadata": {
"id": "zUKICBWFULVe"
},
"source": [
"## Download a Video Asset\n",
"\n",
@@ -44,94 +109,196 @@
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"metadata": {
"id": "MyNzGpzOULVe"
},
"outputs": [],
"source": [
"from supervision.assets import download_assets, VideoAssets\n",
"\n",
"# Download a supervision video asset \n",
"# Download a supervision video asset\n",
"path_to_video = download_assets(VideoAssets.PEOPLE_WALKING)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"metadata": {
"id": "0cMveUy5U-tN"
},
"source": [
"## Tracking Objects\n",
"<div style=\"display: flex; justify-content: center;\">\n",
" <video controls width=\"1000\"\">\n",
" <source\n",
" src=\"https://media.roboflow.com/supervision/video-examples/people-walking.mp4\"\n",
" type=\"video/mp4\"\n",
" >\n",
" </video>\n",
"</div>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "lowrxifpULVe"
},
"source": [
"## Tracking Objects in a Frame\n",
"\n",
"Now that we have our video installed, let's get to work on tracking objects. We'll first pull in a model from roboflow Inference to detect people in our video. Then let's create a `byte_tracker` object that we'll pass our detections to. This will give us a `tracker_id`. We'll then utilize that tracker id to label our detections with a `label_annotator` to display the tracker id. Finally, we'll use a utility called `VideoSink` to save the annotated frames to a video. Let's dive in to the code."
"Now that we have our video installed, let's get to work on tracking objects. We'll first pull in a model from roboflow Inference to detect people in our video. Then let's create a `byte_tracker` object that we'll pass our detections to. This will give us a `tracker_id`. We'll then utilize that tracker id to label our detections with a `label_annotator` to display the tracker id."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 560
},
"id": "gtbnWeT8ULVe",
"outputId": "0fbc468d-ea0d-4d23-a44f-1d50e37f95bf"
},
"outputs": [
{
"output_type": "display_data",
"data": {
"text/plain": [
"<Figure size 1200x1200 with 1 Axes>"
],
"image/png": "iVBORw0KGgoAAAANSUhEUgAAA7YAAAIfCAYAAABEnkAKAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOz9Z5BtyXUeCn6Zex9T59Qpe+uaut63B9qi0bCEIQmSoGhEmSDFCSr0Y2KkCEUoNKEfMz9GPxUx789Ib16E3rwgFCRECSDBAQQSIIAGugl0A93o7tvXtLveVNWtqlveHLv3zvmRe+VemTv3qVNN8s1jRK0bdc8526RZuXK5XLlSKKUU9mAP9mAP9mAP9mAP9mAP9mAP9mAP/p6C/P93A/ZgD/ZgD/ZgD/ZgD/ZgD/ZgD/ZgD/4msGfY7sEe7MEe7MEe7MEe7MEe7MEe7MHfa9gzbPdgD/ZgD/ZgD/ZgD/ZgD/ZgD/bg7zXsGbZ7sAd7sAd7sAd7sAd7sAd7sAd78Pca9gzbPdiDPdiDPdiDPdiDPdiDPdiDPfh7DXuG7R7swR7swR7swR7swR7swR7swR78vYY9w3YP9mAP9mAP9mAP9mAP9mAP9mAP/l7DnmG7B3uwB3uwB3uwB3uwB3uwB3uwB3+vYc+w3YM92IM92IM92IM92IM92IM92IO/1xAO+uC///f/vu99IYT1WQRKKesd+pNSolQqQUqZu9+vnDiOEUUR4jiGUsoqk7/vlkV10rUwDBGGYe4ZX71CCCilzB8ASCnxJ3/yJ7h8+TKefvppHD16FBMTExgaGjL18Hc3NzcRRRE2NzcxOzuL6elpfPSjH0WpVDLPSSktfFD9vN4kSXJ92c048LL4O3TdxSO/F8cxkiSx3k+SBL1eD3EcmzFJkgQXL17E97//fVSrVUxNTeEzn/kMqtUq7t27h4sXL2JxcRFBEEBKacorl8v4xV/8RXz0ox9FFEVWW3i9ABAEAcIwxH/9r/8VV69exfT0NEZGRtBqtRCGISqVCqIoQq/XQ7vdRrvdxtraGoIgwNjYGP71v/7XGB8fR5IkFn24+HdxSM+XSiUEQWC1aaexIBwCGf2VSiXvO0mSIIoiUyene+p/EARWnXxuSSkRBIGhP/4M4dalIV/7Od3w++Vy2fSfnvc96/af44DmP+HU97z7qZRCr9dDkiQIw/7srF97hBCoVCp2X6Gg4G8LBxobl3/46nav8fZXKpXCZ/q1nehACIGhoSHMzc3hj/7oj0y5RJsAMDw8jF//9V/HxMSEt328fKUUyuUy/vRP/xR/+Zd/iVKphC9+8Yv4+Mc/jrGxMfyn//SfcP36dZw5cwb/6l/9K1QqFcOP+vFuF2g+B0Fg6L8I3Pbx79RX3/0iSJIEc3NzWF9fx9LSEu7du4cDBw6gXq+jVCp552GSJNi3bx9OnTpl1RXHMcrlssUz+NgV9Z2A5gHRAR8TzvcIaF7z5zqdDmq1Wk4e83lfRIsA0Ol0jCwedPw4EF+iuej23y3Th99er4dyuVwof11w5T3JnVKphECGECiek27b6HcURUamuM/yOenyKi7r4zhGtVot7OtO13u9HpRShm/z8otw4ZbX7XYNbyT8KCgACi5aeLkcDwDM+67s4Nd4m/i1brdrypBSIhBh7hmCRCU5nhtFkRmPcrlcSAM0HhcuXMB//s//GUmS4NChQ/jN3/xN/P7v/58wMjyC96++hz/6oz/C4cOH0Wg0UKlUcOvWLZw/fx4jIyNIksTMX7cepZSRlcRn+tF2EZBuxPHo1uP+9uHYHQPSx9x7Lg/wlc/bXzTvSOdSShm+49bpvp8sTKH3g08iR2wAwirw5O9JvP3VBHEEPPSrAuuzQFgGTn1W4NX/V4LOpvOSjFH6te8D9a1c++I4hlobBb7/Syhasxs5CmzdB5IIEBIYPQKszwIq9j6u58rnvguMr3p5qg9P9OnjL0Rbg+jnxEv5+/y+awdwXhTHseEf/F6328VLL72Ey5cvG3lCf0VyIY5jnDt3Dv/4H/9jM+6+OSKlzOlALg54Xf1sDyEEwjA0vI/+/i//53/ZF28EAxu2OwE32oqEl+8eMWoS0lxQFxlqHCncCHSVKvd9H2ERAvsNSBHj4QNWqVTwqU99CpcvX8Zrr72GCxcuIAxDDA8PY2hoCKVSCe12G1EUodlsotVq4ejRo3jqqacwOjpqmL7LiHYCjj8X5/0MDFcg+XBV1H9+n48pF77cYBFC4MyZM+h0OhgeHsbY2BiklJibm8Nrr72G7e1tVCoVTExMQEqJxcXFHCP3tZW3q1qtYnl5Gc1m0yilgDb4er2eZdjRmAPA2NgYkiTBwsICJicnrTq4YdtPmHIFqAiKDMYoiizDk3BXJGy4MUhChRusLv37lJVBFP5Bgde5kxLre5f+yPAqErr8OxeyZOS7fGO3CsdOBlW/PpDD4cO+zwXFTs/yT18ZSZKgXC6jXC4jDENLqJHSf/fuXTMH+5VPuO12u6afMzMzUEobvCdOnMCNGzfwwQcf4Oc//zk++9nPmmepPTspbbweer7IscH7yn/TO/2Utn7lcQUiDEN0Oh3jZHF5MuGR172b+gahxZ2M0J3qc/nAoO/Rs3EcWw7WQWib44TkMK+HGwyDlEN8bdDneV30XSlVaNT2K494P3ca+viJDz/8OzlSudzZCVzeT3OBeORORi2/x/th6RUQUKK/s4WeLZVKufnp4sF1Rrp9CILAOBugUmMBeT5d1Bdy2nIHnmuskRwlnWJrawulUgm9Xg9vv/02xsbG8NnPfBY/ffWn+NGPfoRWq4UkUXj66afwpS99CRMTE9Z8LqJ9Vz5zPOw0NnSf6Klo7rq/i57j85zK9+m3O4Hv2UHojNdZpK8MUj8AJD3gxosKhz4qUKoBm/NArz3Qq1Y7CuxTAxv3su8qAdbuDl5HEfC+c5pxaZW3dSeg/gRB0FceUv2ubkS8i5dFjt8XXngBd+7cwdraWs7ALIIDBw6gWq16dZ1+8sb329VJqAxe3t8U/tYM20HAxygI6T5mxZ/h312r3zVCXOBGs1sW9woAxcrKTkw4jmOcP38eH//4x/H973/fXGs2mwiCAIcOHcLMzIwl4Hu9Hk6cOIF2u42RkZFdKdcuM+MM10dggzBM3keXgRdNXp9BTE4CWskC9Orro48+iq2tLSPwh4eHcezYMYRhiJGRETQaDSwtLWF5edliCjTWvC4Slrze69evY21tzWpPuVxGpVJBu922lBZS/icnJ9Hr9XD9+nU8+uijlkeK00uRYsKFidvGIseAOwaVSsUYtW45RULNZV68PbxsPidIOXHLct/zldWP/l3j38VD0Xyi73yVw21D0TXCATHIQZVm3/zgePLNf7cPrhAZpP4i/NH7gyjxVGeRUkXOlXq9bpxIvV4PnU7HPBPHMe7cuYOHH34Y1Wo1V5Zr1G5ubmJpackoyLQCBGhnEtHg1atX8fzzz5s27jRvfHggA7Pfir1LY1yJAPJ49PE4DlEUodvtot1uQ0qJkZERs8Lkg53mJefBRX3YCR+uYeB+FvEVusdx08/w89UL2LQ8qJLB5xVfte1n+BXxCDKCuF4wCC/1tSMQGS0NomxzY41kV1EkC3fG8X6RDCHHkutg4nX5jCL+1+v1AGj5WdTnIiAc+nhLPz7HcU5ylvQYeoa+k0whxdmnZ3Deqpx63H7oa3mdguOG2sbLDYIAt27dwv/0//yfMD8/DwV9f3NzEzMzM/jBD36AS5cuYWhoCE8//TRefvllrK2t4ZVXXsH58+dx5MgR45Tj/XdlIBmlPkfNoHOFynFXO32yrgg4nwZgjY0Pd279RfPffcedez590G2Txfv7dgKIu9A0IYB954DutkKpJrB8XSHpFXbeW5+UEiIMEQkBDDYUu4J+/NQH3CHWz+DrVw7xHuMYKmgX0STnGe68Il1aCIHJyUlsb2+j1Wp528DbJ4XE5OSkVy776nDv82u0gEfRZFxm8XoH0Rn6wd+6YetrkKvo8AnEkVHk1fUpkm59RUySGzMu06aVWrceX5+IKIqAPLOf+MQncOHCBWxtbWWhN0GAz33uc3j77bfx9ttvG6bWbrcxPDyMffv2FdbZz+AAUCi4fIKSl+MSk0/JKDJsuIBxjRJu6JHXP45jayWEv/f000+b93u9HtbX1y3jktrGV7QJyBisVqt499138eKLL2J9fR2NRsO0kZQKCpMkBVgpbVBKKVGr1fDBBx9gfX0dExMTxvtbhA+Ox34GXNFverfX66FSqVhhYr73XLzzfrirSu5Y8SgGHtXAx9UXQl1k8Pj6zqMd+inMPuDMjfexHxPn313PH2+zD3zjNahC4iuL6Nt1SvmUB9+1onnkA+qvS4dCCOO4qVarqNVqGBkZwczMDCYnJ40gofDO1dVV3Lt3D+fPn/cqo2EYYn19Ha+//jpefullrKyu4MCBA1hZWcHExATGxsawvb2Ne/fumXdnZmawsrKCWq2WcyT6okl4+10F0tdvl4e5NMPpaCelgd8n51u320Wv10Oj0cDa2hqq1WqOB/P32+224Wv8ej/6L1IyeZ9obhfxFRdPPlxyXPmUB9dAcMvqp0QVAcc9yTfOk3xztWiOlkolY2TQc7tRdOjZKIoQyhBA8ep10TWSOUX6hY8muLFFny4eOAxC96TUUpmurHXnj/s+kCnYtPpD5uUgPJ7rZDyk+f79+7h48SLm5+dx4MABfOYzn8HQ0FCOP3H8JUkClSSAE51j0TCyVXZXZ+ErnRyntPXpD//wD3F//r4pq9lsIgxDnDhxAnEco9VqodPp4K233sLGxgaCIECr1cJ3v/tdPP3000ZHGBQGjULwQT9HwCC/fePFcd1vju0kY/h7g+o0bhnG6VBYExB1gQ++myDq6AeXrwMHHgeaSwrzl/u82Ke9fzcwWNmuXePTZTjfLZJT7n36TQ5XdzsCpyNyoPn0VLine truncated
},
"metadata": {}
}
],
"source": [
"import supervision as sv\n",
"from inference.models.utils import get_roboflow_model\n",
"\n",
"# Load a pre trained yolov8 nano model from Roboflow Inference.\n",
"model = get_roboflow_model('yolov8n-640')\n",
"\n",
"# Create a video info object from the video path.\n",
"video_info = sv.VideoInfo.from_video_path(path_to_video)\n",
"\n",
"# Create a label annotator for labeling detections with our tracker_id.\n",
"label = sv.LabelAnnotator()\n",
"\n",
"# Create a ByteTrack object to track detections.\n",
"byte_tracker = sv.ByteTrack(frame_rate=video_info.fps)\n",
"\n",
"# Create a frame generator from video path for iteration of frames.\n",
"frame_generator = sv.get_video_frames_generator(path_to_video)\n",
"\n",
"# Grab a frame from the frame_generator.\n",
"frame = next(frame_generator)\n",
"\n",
"# Run inference on the frame by passing it to our model.\n",
"result = model.infer(frame)[0]\n",
"\n",
"# Convert model results to a supervision detection object.\n",
"detections = sv.Detections.from_inference(result)\n",
"\n",
"# Update detections with tracker ids fro byte_tracker.\n",
"tracked_detections = byte_tracker.update_with_detections(detections)\n",
"\n",
"# Create labels with tracker_id for label annotator.\n",
"labels = [ f\"{tracker_id}\" for tracker_id in tracked_detections.tracker_id ]\n",
"\n",
"# Apply label annotator to frame.\n",
"annotated_frame = label.annotate(scene=frame.copy(), detections=tracked_detections, labels=labels)\n",
"\n",
"# Display the frame.\n",
"sv.plot_image(annotated_frame)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "wR2nrNUiVOGq"
},
"source": [
"## Tracking Objects in a Video\n",
"\n",
"Finally, we'll use a utility called `VideoSink` to save the annotated frames to a video. Let's dive in to the code."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"metadata": {
"id": "b4lOhjcfVYAl"
},
"outputs": [],
"source": [
"import supervision as sv\n",
"from supervision.assets import download_assets, VideoAssets\n",
"from inference.models.utils import get_roboflow_model\n",
"from tqdm import tqdm\n",
"\n",
"# Load a pre trained yolov8 nano model from Roboflow Inference.\n",
"model = get_roboflow_model('yolov8n-640')\n",
"\n",
"if __name__ == '__main__':\n",
"# Create a video info object from the video path.\n",
"video_info = sv.VideoInfo.from_video_path(path_to_video)\n",
"\n",
" # Install our video from supervision assets.\n",
" PATH_TO_VIDEO = download_assets(VideoAssets.PEOPLE_WALKING)\n",
"# Create a label annotator for labeling detections with our tracker_id.\n",
"label = sv.LabelAnnotator()\n",
"\n",
" # Load a pre trained yolov8 nano model from Roboflow Inference.\n",
" model = get_roboflow_model('yolov8n-640')\n",
"# Create a ByteTrack object to track detections.\n",
"byte_tracker = sv.ByteTrack(frame_rate=video_info.fps)\n",
"\n",
" # Create a video info object from the video path.\n",
" video_info = sv.VideoInfo.from_video_path(PATH_TO_VIDEO)\n",
"# Create a frame generator from video path for iteration of frames.\n",
"frame_generator = sv.get_video_frames_generator(path_to_video)\n",
"\n",
" # Create a label annotator for labeling detections with our tracker_id.\n",
" label = sv.LabelAnnotator()\n",
"# Create a video sink context manager to save resulting video.\n",
"with sv.VideoSink(target_path=\"output.mp4\", video_info=video_info) as sink:\n",
"\n",
" # Create a ByteTrack object to track detections.\n",
" byte_tracker = sv.ByteTrack(frame_rate=video_info.fps)\n",
" # Iterate through frames yielded from the frame_generator.\n",
" for frame in tqdm(frame_generator, total=video_info.total_frames):\n",
"\n",
" # Create a frame generator from video path for iteration of frames.\n",
" frame_generator = sv.get_video_frames_generator(PATH_TO_VIDEO)\n",
" # Run inference on the frame by passing it to our model.\n",
" result = model.infer(frame)[0]\n",
"\n",
" # Create a video sink context manager to save resulting video.\n",
" with sv.VideoSink(target_path=\"output.mp4\", video_info=video_info) as sink:\n",
" # Convert model results to a supervision detection object.\n",
" detections = sv.Detections.from_inference(result)\n",
"\n",
" # Iterate over frames of the video.\n",
" for frame in frame_generator:\n",
" # Update detections with tracker ids fro byte_tracker.\n",
" tracked_detections = byte_tracker.update_with_detections(detections)\n",
"\n",
" # Run inference on the frame by passing it to our model.\n",
" result = model.infer(frame)[0]\n",
" # Create labels with tracker_id for label annotator.\n",
" labels = [ f\"{tracker_id}\" for tracker_id in tracked_detections.tracker_id ]\n",
"\n",
" # Convert model results to a supervision detection object.\n",
" detections = sv.Detections.from_inference(result)\n",
" # Apply label annotator to frame.\n",
" annotated_frame = label.annotate(scene=frame.copy(), detections=tracked_detections, labels=labels)\n",
"\n",
" # Update detections with tracker ids fro byte_tracker.\n",
" tracked_detections = byte_tracker.update_with_detections(detections)\n",
"\n",
" # Create labels with tracker_id for label annotator.\n",
" labels = [ f\"{tracker_id}\" for tracker_id in tracked_detections.tracker_id ]\n",
"\n",
" # Apply label annotator to frame.\n",
" annotated_frame = label.annotate(scene=frame.copy(), detections=tracked_detections, labels=labels)\n",
"\n",
" # Save the annotated frame to an output video.\n",
" sink.write_frame(frame=annotated_frame)"
" # Save the annotated frame to an output video.\n",
" sink.write_frame(frame=annotated_frame)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"metadata": {
"id": "0J10FczGULVe"
},
"source": [
"# View the Video\n",
"Let's take a look at our resulting video. It will also be created in your current directory with the name `output.mp4` Notice how even with a little flicker, we can see the `tracker_id` on the people walking in the video. With trackers under your belt, there are now a wide variety of use cases you can solve for! Happy building!\n",
"\n",
"Let's take a look at our resulting video. It will be created in your current directory with the name `output.mp4` Notice how even with a little flicker, we can see the `tracker_id` on the people walking in the video. With trackers under your belt, there are now a wide variety of use cases you can solve for! Happy building! "
"<div style=\"display: flex; justify-content: center;\">\n",
" <video controls width=\"1000\">\n",
" <source\n",
" src=\"https://media.roboflow.com/supervision/cookbooks/object-tracking.mp4\"\n",
" type=\"video/mp4\"\n",
" >\n",
" </video>\n",
"</div>"
]
}
],
"metadata": {
"accelerator": "GPU",
"colab": {
"gpuType": "V100",
"provenance": []
},
"kernelspec": {
"display_name": "venv",
"language": "python",
"display_name": "Python 3",
"name": "python3"
},
"language_info": {
@@ -144,9 +311,9 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.7"
"version": "3.11.8"
}
},
"nbformat": 4,
"nbformat_minor": 2
"nbformat_minor": 0
}