Package: eyepop
EyePop.ai Python SDKThe EyePop.ai Python SDK provides convenient access to the EyePop.ai's inference API from applications written in the
Python language.RequirementsPython 3.8+InstallpipinstalleyepopConfigurationThe EyePop SDK needs to be configured with thePop Idand yourSecret Api Key.importosfromeyepopimportEyePopSdkendpoint=EyePopSdk.endpoint(# This is the default and can be omittedpop_id=os.environ.get('EYEPOP_POP_ID'),# This is the default and can be omittedsecret_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 productionhttp://api.eyepop.aiUsage ExamplesUploading and processing one single imagefromeyepopimportEyePopSdkdefupload_photo(file_path:str):withEyePopSdk.endpoint()asendpoint:result=endpoint.upload(file_path).predict()print(result)upload_photo('examples/example.jpg')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.The usage ofwith ... 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.endpoint.upload('examples/example.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.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.To upload a binary stream, i.e. a file-like object, you can use the methodupload_stream()and pass the file-like
object and the mime-type:fromeyepopimportEyePopSdkdefupload_photo_from_stream(file_path:str,mime_type:str):withEyePopSdk.endpoint()asendpoint:withopen(file_path,'rb')asfile:result=endpoint.upload_stream(file,mime_type).predict()print(result)upload_photo_from_stream('examples/example.jpg','image/jpeg')Visualizing ResultsThe EyePop SDK includes helper classes to visualize the predictions for images usingmatplotlib.pyplot.fromPILimportImageimportmatplotlib.pyplotaspltfromeyepopimportEyePopSdkwithEyePopSdk.endpoint()asendpoint:result=endpoint.upload('examples/example.jpg').predict()withImage.open('examples/example.jpg')asimage:plt.imshow(image)plot=EyePopSdk.plot(plt.gca())plot.prediction(result)plt.show()Depending on the environment, you might need to install an interactive backend, e.g. withpip3 install pyqt5.Uploading and processing batches of imagesFor batches of images, instead of waiting for each resultpredict()beforesubmitting 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.fromeyepopimportEyePopSdkdefupload_photos(file_paths:list[str]):withEyePopSdk.endpoint()asendpoint:jobs=[]forfile_pathinfile_paths:jobs.append(endpoint.upload(file_path))forjobinjobs:print(job.predict())upload_photos(['examples/example.jpg']*100)Asynchronous uploading and processing of imagesThe abovesynchronousway is great for individual images or reasonable sized batches. If your batch size is 'large'
this can cause memory and performance issues. Consider thatendpoint.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 callsenpoint.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 viapredict()after the
entire list was submitted.For high throughput applications, consider using theasyncvariant which supports a callback parameteron_ready.
Within the callback, your code can process the results asynchronously and clearing the task list as soon as the results
are available.importasynciofromeyepopimportEyePopSdkfromeyepopimportJobasyncdefasync_upload_photos(file_paths:list[str]):asyncdefon_ready(job:Job):print(awaitjob.predict())asyncwithEyePopSdk.endpoint(is_async=True)asendpoint:forfile_pathinfile_paths:awaitendpoint.upload(file_path,on_ready)asyncio.run(async_upload_photos(['examples/example.jpg']*100000000))Loading images from URLsAlternatively 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)fromeyepopimportEyePopSdkdefload_from_url(url:str):withEyePopSdk.endpoint()asendpoint:result=endpoint.load_from(url).predict()print(result)load_from_url('https://farm2.staticflickr.com/1080/1301049949_532835a8b5_z.jpg')Processing VideosYou 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.fromeyepopimportEyePopSdkdefload_video_from_url(url:str):withEyePopSdk.endpoint()asendpoint:job=endpoint.load_from(url)whileresult:=job.predict():print(result)load_video_from_url('https://demo-eyepop-videos.s3.amazonaws.com/test1_vlog.mp4')Canceling JobsAny 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.fromeyepopimportEyePopSdkdefload_video_from_url(url:str):withEyePopSdk.endpoint()asendpoint:job=endpoint.load_from(url)whileresult:=job.predict():print(result)ifresult['seconds']>=10.0:job.cancel()load_video_from_url('https://demo-eyepop-videos.s3.amazonaws.com/test1_vlog.mp4')Other Usage OptionsAuto start workersBy default,EyePopSdk.endpoint().connect()will start a worker if none is running yet. To disable this behavior
create an endpoint withEyePopSdk.endpoint(auto_start=False).Stop pending jobsBy default,EyePopSdk.endpoint().connect()will cancel all currently running or queued jobs on the worker.
It is assumed that the callertakes full controlof that worker. To disable this behavior create an endpoint withEyePopSdk.endpoint(stop_jobs=False).