-
Notifications
You must be signed in to change notification settings - Fork 131
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #213 from roboflow/feature/notebook
Built In Jupyter Notebook
- Loading branch information
Showing
50 changed files
with
900 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"id": "83db9682-cfc4-4cd0-889f-c8747c4033b3", | ||
"metadata": {}, | ||
"source": [ | ||
"# Inference Pipeline\n", | ||
"\n", | ||
"Inference Pipelines are a great way to process video streams with Inference. You can configure different sources that include streams from local devices, RTSP streams, and local video files. You can also configure different sinks that include UDP streaming of results, render of results, and custom callbacks to run your own logic after each new set of predictions is available. " | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "4ec4136f-53e9-4c8c-9217-a2c533d498ae", | ||
"metadata": {}, | ||
"source": [ | ||
"### Roboflow API Key\n", | ||
"\n", | ||
"To load models with `inference`, you'll need a Roboflow API Key. Find instructions for retrieving your API key [here](https://docs.roboflow.com/api-reference/authentication). The utility function below attempts to load your Roboflow API key from your enviornment. If it isn't found, it then prompts you to input it. To avoid needing to input your API key for each example, you can configure your Roboflow API key in your environment via the variable `ROBOFLOW_API_KEY`." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "af3aad40-d41b-4bc1-ade8-dac052951257", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"from utils import get_roboflow_api_key\n", | ||
"\n", | ||
"api_key = get_roboflow_api_key()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "86f3f805-f628-4e94-91ac-3b2f44bebdc0", | ||
"metadata": {}, | ||
"source": [ | ||
"### Inference Pipeline Example\n", | ||
"\n", | ||
"In this example we create a new InferencePipeline. We pass the model ID, the video reference, and a method to render our results. Out pipeline does the rest!" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "58dd049c-dcc6-4d0b-85ad-e6d1c0ba805b", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"from functools import partial\n", | ||
"\n", | ||
"import numpy as np\n", | ||
"from matplotlib import pyplot as plt\n", | ||
"from IPython import display\n", | ||
"\n", | ||
"from inference.core.interfaces.stream.inference_pipeline import InferencePipeline\n", | ||
"from inference.core.interfaces.stream.sinks import render_boxes\n", | ||
"\n", | ||
"# Define source video\n", | ||
"video_url = \"https://storage.googleapis.com/com-roboflow-marketing/football-video.mp4\"\n", | ||
"\n", | ||
"# Prepare to plot results\n", | ||
"\n", | ||
"fig, ax = plt.subplots()\n", | ||
"frame_placeholder = np.zeros((480, 640, 3), dtype=np.uint8) # Adjust the dimensions to match your frame size\n", | ||
"image_display = ax.imshow(frame_placeholder)\n", | ||
"\n", | ||
"# Define our plotting function\n", | ||
"def update_plot(new_frame):\n", | ||
" # Update the image displayed\n", | ||
" image_display.set_data(new_frame)\n", | ||
" # Redraw the canvas immediately\n", | ||
" display.display(plt.gcf())\n", | ||
" display.clear_output(wait=True)\n", | ||
"\n", | ||
"# Define our pipeline's sink\n", | ||
"render = partial(render_boxes, on_frame_rendered=update_plot)\n", | ||
"\n", | ||
"# Instantiate the pipeline\n", | ||
"pipeline = InferencePipeline.init(\n", | ||
" model_id=\"soccer-players-5fuqs/1\",\n", | ||
" video_reference=video_url,\n", | ||
" on_prediction=render,\n", | ||
" api_key=api_key,\n", | ||
")\n", | ||
"\n", | ||
"# Start the pipeline\n", | ||
"pipeline.start()\n", | ||
"pipeline.join()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"id": "07762936-ff33-46c0-a4a2-0a8e729053d1", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [] | ||
} | ||
], | ||
"metadata": { | ||
"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": 5 | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import getpass | ||
import requests | ||
|
||
import cv2 | ||
import numpy as np | ||
|
||
from inference.core.env import API_KEY | ||
|
||
def get_roboflow_api_key(): | ||
if API_KEY is None: | ||
api_key = getpass.getpass("Roboflow API Key:") | ||
else: | ||
api_key = API_KEY | ||
return api_key | ||
|
||
def load_image_from_url(url): | ||
# Send a GET request to the URL | ||
response = requests.get(url) | ||
|
||
# Ensure that the request was successful | ||
if response.status_code == 200: | ||
# Convert the response content into a numpy array | ||
image_array = np.asarray(bytearray(response.content), dtype=np.uint8) | ||
|
||
# Decode the image array into an OpenCV image | ||
image = cv2.imdecode(image_array, cv2.IMREAD_COLOR) | ||
|
||
return image | ||
else: | ||
print(f"Failed to retrieve the image. HTTP status code: {response.status_code}") | ||
return None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from pydantic import BaseModel, Field, ValidationError | ||
|
||
|
||
class NotebookStartResponse(BaseModel): | ||
"""Response model for notebook start request""" | ||
|
||
success: str = Field(..., description="Status of the request") | ||
message: str = Field(..., description="Message of the request", optional=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import os | ||
import subprocess | ||
|
||
import requests | ||
|
||
from inference.core.env import NOTEBOOK_PASSWORD, NOTEBOOK_PORT | ||
|
||
|
||
def check_notebook_is_running(): | ||
try: | ||
response = requests.get(f"http://localhost:{NOTEBOOK_PORT}/") | ||
return response.status_code == 200 | ||
except: | ||
return False | ||
|
||
|
||
def start_notebook(): | ||
if not check_notebook_is_running(): | ||
os.makedirs("/notebooks", exist_ok=True) | ||
subprocess.Popen( | ||
f"jupyter-lab --allow-root --port={NOTEBOOK_PORT} --ip=0.0.0.0 --notebook-dir=/notebooks --NotebookApp.token='{NOTEBOOK_PASSWORD}' --NotebookApp.password='{NOTEBOOK_PASSWORD}'".split( | ||
" " | ||
) | ||
) |
Oops, something went wrong.