# EyePop.ai Python SDK
The EyePop.ai Python SDK provides convenient access to the EyePop.ai's inference API from applications written in the
Python language.
## Requirements
* Python 3.8+
## Install
```shell
pip install eyepop-sdk-python
```
## Configuration
The EyePop SDK needs to be configured with the __Pop Id__ and your __Secret Api Key__.
```python
import os
from eyepop.eyepopsdk import EyePopSdk
endpoint = EyePopSdk.endpoint(
# This is the default and can be omitted
pop_id=os.environ.get('EYEPOP_POP_ID'),
# This is the default and can be omitted
secret_key=os.environ.get('EYEPOP_SECRET_KEY'),
)
endpoint.connect()
# do work ....
endpoint.disconnect()
```
While you can provide a secret_key keyword argument, we recommend using python-dotenv to add EYEPOP_SECRET_KEY="My API Key"
to your .env file so that your API Key is not stored in source control. By default, the SDK will read the following environment variables:
* `EYEPOP_POP_ID`: The Pop Id to use as an endpoint. You can copy'n paste this string from your EyePop Dashboard in the Pop -> Settings section.
* `EYEPOP_SECRET_KEY`: Your Secret Api Key. You can create Api Keys in the profile section of youe EyePop dashboard.
* `EYEPOP_URL`: (Optional) URL of the EyePop API service, if you want to use any other endpoint than production `http://api.eyepop.ai`
## Usage Examples
### Uploading and processing one single image
```python
from eyepop.eyepopsdk import EyePopSdk
def upload_photo(file_path: str):
with EyePopSdk.endpoint() as endpoint:
result = endpoint.upload(file_path).predict()
print(result)
upload_photo('examples/examples.jpg')
```
1. `EyePopSdk.endpoint()` returns a local endpoint object, that will authenticate with the Api Key found in
EYEPOP_SECRET_KEY and load the worker configuration for the Pop identified by EYEPOP_POP_ID.
2. The usage of `with ... endpoint:` will automatically manage the runtime context, connect to the worker upon entering
the context and releasing all underlying resources upon exiting the context. Alternatively your code can call
endpoint.connect() before any job is submitted and endpoint.disconnect() to release all resources.
2. `endpoint.upload('examples/examples.jpg')` initiates the upload to the local file to the worker service. The image will
be queued and processed immediately when the worker becomes available.
3. `predict()` waits for the first prediction result as reports it as a dict. In case of a single image, there will be
one single prediction result and subsequent calls to predict() will return None. If the uploaded file is a video
e.g. 'video/mp4' or image container format e.g. 'image/gif', subsequent calls to predict() will return a prediction
for each individual frame and None when the entire file has been processed.
### Uploading and processing batches of images
For batches of images, instead of waiting for each result `predict()` _before_ submitting the next job, you can queue
all jobs first, let them process in parallel and collect the results later. This avoids the sequential accumulation of
the HTTP roundtrip time.
```python
from eyepop.eyepopsdk import EyePopSdk
def upload_photos(file_paths: list[str]):
with EyePopSdk.endpoint() as endpoint:
jobs = []
for file_path in file_paths:
jobs.append(endpoint.upload(file_path))
for job in jobs:
print(job.predict())
upload_photos(['examples/examples.jpg'] * 100)
```
### Asynchronous uploading and processing of images
The above _synchronous_ way is great for individual images or reasonable sized batches. If your batch size is 'large'
this can cause memory and performance issues. Consider that `endpoint.upload()` is a very fast, local operation.
In fact, it creates and schedules a task that will execute the 'slow' IO operations in the background. Consequently,
when your code calls `enpoint.upload()` 1,000,000 times it will cause a background task list with ~ 1,000,000 entries.
And the example code above will only start clearing out this list by receiving the result via `predict()` after the
entire list was submitted.
For high throughput applications, consider using the `async` variant which supports a callback parameter `on_ready`.
Within the callback, your code can process the results asynchronously and clearing the task list as soon as the results
are available.
```python
import asyncio
from eyepop.eyepopsdk import EyePopSdk
from eyepop.jobs import Job
async def async_upload_photos(file_paths: list[str]):
async def on_ready(job: Job):
print(await job.predict())
async with EyePopSdk.endpoint(is_async=True) as endpoint:
for file_path in file_paths:
await endpoint.upload(file_path, on_ready)
asyncio.run(async_upload_photos(['examples/examples.jpg'] * 100000000))
```
### Loading images from URLs
Alternatively to uploading files, you can also submit a publicly accessible URL for processing. This works for both,
synchronous and asynchronous mode. Supported protocols are:
* HTTP(s) URLs with response Content-Type image/* or video/*
* RTSP (live streaming)
* RTMP (live streaming)
```python
from eyepop.eyepopsdk import EyePopSdk
def load_from_url(url: str):
with EyePopSdk.endpoint() as endpoint:
result = endpoint.load_from(url).predict()
print(result)
load_from_url('https://farm2.staticflickr.com/1080/1301049949_532835a8b5_z.jpg')
```
### Processing Videos
You can process videos via upload or public URLs. This example shows how to process all video frames of a file
retrieved from a public URL. This works for both, synchronous and asynchronous mode.
```python
from eyepop.eyepopsdk import EyePopSdk
def load_video_from_url(url: str):
with EyePopSdk.endpoint() as endpoint:
job = endpoint.load_from(url)
while result := job.predict():
print(result)
load_video_from_url('https://demo-eyepop-videos.s3.amazonaws.com/test1_vlog.mp4')
```
### Canceling Jobs
Any job that has been queued or is in-progress can be cancelled. E.g. stop the video processing after
predictions have been processed for 10 seconds duration of the video.
```python
from eyepop.eyepopsdk import EyePopSdk
def load_video_from_url(url: str):
with EyePopSdk.endpoint() as endpoint:
job = endpoint.load_from(url)
while result := job.predict():
print(result)
if result['seconds'] >= 10.0:
job.cancel()
load_video_from_url('https://demo-eyepop-videos.s3.amazonaws.com/test1_vlog.mp4')
```
### Visualizing Results
The EyePop SDK contains includes helper classes to visualize the predictions for images using `matplotlib.pyplot`.
```python
from PIL import Image
import matplotlib.pyplot as plt
from eyepop.eyepopsdk import EyePopSdk
from eyepop.visualize import EyePopPlot
with EyePopSdk.endpoint() as endpoint:
result = endpoint.upload('examples/examples.jpg').predict()
with Image.open('examples/examples.jpg') as image:
plt.imshow(image)
plot = EyePopPlot(plt.gca())
if result['objects'] is not None:
for obj in result['objects']:
plot.object(obj)
plt.show()
```
Depending on the environment, you might need to install an interactive backend, e.g. with `pip3 install pyqt5`.
## Other Usage Options
#### Auto start workers
By default, `EyePopSdk.endpoint().connect()` will start a worker if none is running yet. To disable this behavior
create an endpoint with `EyePopSdk.endpoint(auto_start=False)`.
#### Stop pending jobs
By default, `EyePopSdk.endpoint().connect()` will cancel all currently running or queued jobs on the worker.
It is assumed that the caller _takes full control_ of that worker. To disable this behavior create an endpoint with
`EyePopSdk.endpoint(stop_jobs=False)`.
Raw data
{
"_id": null,
"home_page": "https://github.com/eyepop-ai/eyepop-sdk-python",
"name": "eyepop-sdk-python",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "",
"keywords": "EyePop AI ML CV",
"author": "EyePop.ai",
"author_email": "info@eyepop.ai",
"download_url": "https://files.pythonhosted.org/packages/50/53/a42a37bd1681e30da98b6b5475e3cb9f88c10019981cbafad83876e0103f/eyepop-sdk-python-0.9.1.tar.gz",
"platform": null,
"description": "# EyePop.ai Python SDK\nThe EyePop.ai Python SDK provides convenient access to the EyePop.ai's inference API from applications written in the \nPython language. \n\n## Requirements \n* Python 3.8+\n\n## Install\n```shell\npip install eyepop-sdk-python\n```\n\n## Configuration\nThe EyePop SDK needs to be configured with the __Pop Id__ and your __Secret Api Key__. \n```python\nimport os\nfrom eyepop.eyepopsdk import EyePopSdk\n\nendpoint = EyePopSdk.endpoint(\n # This is the default and can be omitted\n pop_id=os.environ.get('EYEPOP_POP_ID'), \n # This is the default and can be omitted\n secret_key=os.environ.get('EYEPOP_SECRET_KEY'),\n)\n\nendpoint.connect()\n# do work ....\nendpoint.disconnect()\n```\nWhile you can provide a secret_key keyword argument, we recommend using python-dotenv to add EYEPOP_SECRET_KEY=\"My API Key\" \nto your .env file so that your API Key is not stored in source control. By default, the SDK will read the following environment variables:\n* `EYEPOP_POP_ID`: The Pop Id to use as an endpoint. You can copy'n paste this string from your EyePop Dashboard in the Pop -> Settings section.\n* `EYEPOP_SECRET_KEY`: Your Secret Api Key. You can create Api Keys in the profile section of youe EyePop dashboard.\n* `EYEPOP_URL`: (Optional) URL of the EyePop API service, if you want to use any other endpoint than production `http://api.eyepop.ai` \n## Usage Examples\n \n### Uploading and processing one single image\n```python\nfrom eyepop.eyepopsdk import EyePopSdk\n\ndef upload_photo(file_path: str):\n with EyePopSdk.endpoint() as endpoint:\n result = endpoint.upload(file_path).predict()\n print(result)\n\nupload_photo('examples/examples.jpg')\n```\n1. `EyePopSdk.endpoint()` returns a local endpoint object, that will authenticate with the Api Key found in \nEYEPOP_SECRET_KEY and load the worker configuration for the Pop identified by EYEPOP_POP_ID. \n2. The usage of `with ... endpoint:` will automatically manage the runtime context, connect to the worker upon entering\nthe context and releasing all underlying resources upon exiting the context. Alternatively your code can call \nendpoint.connect() before any job is submitted and endpoint.disconnect() to release all resources.\n2. `endpoint.upload('examples/examples.jpg')` initiates the upload to the local file to the worker service. The image will\nbe queued and processed immediately when the worker becomes available.\n3. `predict()` waits for the first prediction result as reports it as a dict. In case of a single image, there will be \none single prediction result and subsequent calls to predict() will return None. If the uploaded file is a video\ne.g. 'video/mp4' or image container format e.g. 'image/gif', subsequent calls to predict() will return a prediction \nfor each individual frame and None when the entire file has been processed. \n### Uploading and processing batches of images\nFor batches of images, instead of waiting for each result `predict()` _before_ submitting the next job, you can queue \nall jobs first, let them process in parallel and collect the results later. This avoids the sequential accumulation of \nthe HTTP roundtrip time.\n\n```python\nfrom eyepop.eyepopsdk import EyePopSdk\n\ndef upload_photos(file_paths: list[str]):\n with EyePopSdk.endpoint() as endpoint:\n jobs = []\n for file_path in file_paths:\n jobs.append(endpoint.upload(file_path))\n for job in jobs:\n print(job.predict())\n\nupload_photos(['examples/examples.jpg'] * 100)\n```\n### Asynchronous uploading and processing of images\nThe above _synchronous_ way is great for individual images or reasonable sized batches. If your batch size is 'large'\nthis can cause memory and performance issues. Consider that `endpoint.upload()` is a very fast, local operation. \nIn fact, it creates and schedules a task that will execute the 'slow' IO operations in the background. Consequently, \nwhen your code calls `enpoint.upload()` 1,000,000 times it will cause a background task list with ~ 1,000,000 entries. \nAnd the example code above will only start clearing out this list by receiving the result via `predict()` after the \nentire list was submitted.\n\nFor high throughput applications, consider using the `async` variant which supports a callback parameter `on_ready`. \nWithin the callback, your code can process the results asynchronously and clearing the task list as soon as the results \nare available.\n\n```python\nimport asyncio\nfrom eyepop.eyepopsdk import EyePopSdk\nfrom eyepop.jobs import Job\n\nasync def async_upload_photos(file_paths: list[str]):\n async def on_ready(job: Job):\n print(await job.predict())\n\n async with EyePopSdk.endpoint(is_async=True) as endpoint:\n for file_path in file_paths:\n await endpoint.upload(file_path, on_ready)\n\nasyncio.run(async_upload_photos(['examples/examples.jpg'] * 100000000))\n```\n### Loading images from URLs\nAlternatively to uploading files, you can also submit a publicly accessible URL for processing. This works for both,\nsynchronous and asynchronous mode. Supported protocols are:\n* HTTP(s) URLs with response Content-Type image/* or video/* \n* RTSP (live streaming)\n* RTMP (live streaming)\n\n```python\nfrom eyepop.eyepopsdk import EyePopSdk\n\ndef load_from_url(url: str):\n with EyePopSdk.endpoint() as endpoint:\n result = endpoint.load_from(url).predict()\n print(result)\n\nload_from_url('https://farm2.staticflickr.com/1080/1301049949_532835a8b5_z.jpg')\n```\n### Processing Videos \nYou can process videos via upload or public URLs. This example shows how to process all video frames of a file \nretrieved from a public URL. This works for both, synchronous and asynchronous mode.\n\n```python\nfrom eyepop.eyepopsdk import EyePopSdk\n\ndef load_video_from_url(url: str):\n with EyePopSdk.endpoint() as endpoint:\n job = endpoint.load_from(url)\n while result := job.predict():\n print(result)\n\nload_video_from_url('https://demo-eyepop-videos.s3.amazonaws.com/test1_vlog.mp4')\n```\n### Canceling Jobs\nAny job that has been queued or is in-progress can be cancelled. E.g. stop the video processing after\npredictions have been processed for 10 seconds duration of the video.\n```python\nfrom eyepop.eyepopsdk import EyePopSdk\n\ndef load_video_from_url(url: str):\n with EyePopSdk.endpoint() as endpoint:\n job = endpoint.load_from(url)\n while result := job.predict():\n print(result)\n if result['seconds'] >= 10.0:\n job.cancel()\n\nload_video_from_url('https://demo-eyepop-videos.s3.amazonaws.com/test1_vlog.mp4')\n```\n### Visualizing Results\nThe EyePop SDK contains includes helper classes to visualize the predictions for images using `matplotlib.pyplot`.\n```python\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nfrom eyepop.eyepopsdk import EyePopSdk\nfrom eyepop.visualize import EyePopPlot\n\nwith EyePopSdk.endpoint() as endpoint:\n result = endpoint.upload('examples/examples.jpg').predict()\n with Image.open('examples/examples.jpg') as image:\n plt.imshow(image)\n plot = EyePopPlot(plt.gca())\n if result['objects'] is not None:\n for obj in result['objects']:\n plot.object(obj)\n plt.show()\n```\nDepending on the environment, you might need to install an interactive backend, e.g. with `pip3 install pyqt5`.\n## Other Usage Options\n#### Auto start workers\nBy default, `EyePopSdk.endpoint().connect()` will start a worker if none is running yet. To disable this behavior \ncreate an endpoint with `EyePopSdk.endpoint(auto_start=False)`.\n#### Stop pending jobs\nBy default, `EyePopSdk.endpoint().connect()` will cancel all currently running or queued jobs on the worker. \nIt is assumed that the caller _takes full control_ of that worker. To disable this behavior create an endpoint with \n`EyePopSdk.endpoint(stop_jobs=False)`.\n\n\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "EyePop.ai Python SDK",
"version": "0.9.1",
"project_urls": {
"Bug Tracker": "https://github.com/eyepop-ai/eyepop-sdk-python/issues",
"Changes": "https://github.com/eyepop-ai/eyepop-sdk-python/blob/master/CHANGELOG.md",
"Documentation": "https://github.com/eyepop-ai/eyepop-sdk-python",
"Homepage": "https://github.com/eyepop-ai/eyepop-sdk-python",
"Source Code": "https://github.com/eyepop-ai/eyepop-sdk-python"
},
"split_keywords": [
"eyepop",
"ai",
"ml",
"cv"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "c9a942a787e04d7e4870ff6deab399deaac71d84ed7b6e74818f1c9a2ec494c6",
"md5": "b63d34b109556df338703eb2ad68375e",
"sha256": "111fc55f26b02858a47c37107233814760fe1ead288bc295758994ee2048ed3b"
},
"downloads": -1,
"filename": "eyepop_sdk_python-0.9.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "b63d34b109556df338703eb2ad68375e",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 12378,
"upload_time": "2023-12-22T20:40:53",
"upload_time_iso_8601": "2023-12-22T20:40:53.135370Z",
"url": "https://files.pythonhosted.org/packages/c9/a9/42a787e04d7e4870ff6deab399deaac71d84ed7b6e74818f1c9a2ec494c6/eyepop_sdk_python-0.9.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "5053a42a37bd1681e30da98b6b5475e3cb9f88c10019981cbafad83876e0103f",
"md5": "3c7859c06b3af5eaefb2edc499c6be4b",
"sha256": "38f8c33443027f45e1a136249c7df56ff33f10dc5dcb81f4943f7aab71d73d81"
},
"downloads": -1,
"filename": "eyepop-sdk-python-0.9.1.tar.gz",
"has_sig": false,
"md5_digest": "3c7859c06b3af5eaefb2edc499c6be4b",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 13906,
"upload_time": "2023-12-22T20:40:54",
"upload_time_iso_8601": "2023-12-22T20:40:54.249643Z",
"url": "https://files.pythonhosted.org/packages/50/53/a42a37bd1681e30da98b6b5475e3cb9f88c10019981cbafad83876e0103f/eyepop-sdk-python-0.9.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-12-22 20:40:54",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "eyepop-ai",
"github_project": "eyepop-sdk-python",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [],
"lcname": "eyepop-sdk-python"
}