44from io import BufferedReader , BytesIO
55from typing import Optional , Union
66
7+ from groundlight .optional_imports import Image
78from model import Detector , ImageQuery , PaginatedDetectorList , PaginatedImageQueryList
89from openapi_client import ApiClient , Configuration
910from openapi_client .api .detectors_api import DetectorsApi
1213
1314from groundlight .binary_labels import convert_display_label_to_internal , convert_internal_label_to_display
1415from groundlight .config import API_TOKEN_VARIABLE_NAME , API_TOKEN_WEB_URL , DEFAULT_ENDPOINT
15- from groundlight .images import buffer_from_jpeg_file , jpeg_from_numpy
16+ from groundlight .images import buffer_from_jpeg_file , jpeg_from_numpy , parse_supported_image_types
1617from groundlight .internalapi import GroundlightApiClient , sanitize_endpoint_url
1718from groundlight .optional_imports import np
1819
@@ -38,6 +39,8 @@ class Groundlight:
3839 ```
3940 """
4041
42+ DEFAULT_WAIT = 30
43+
4144 BEFORE_POLLING_DELAY = 3.0 # Expected minimum time for a label to post
4245 POLLING_INITIAL_DELAY = 0.5
4346 POLLING_EXPONENTIAL_BACKOFF = 1.3 # This still has the nice backoff property that the max number of requests
@@ -122,38 +125,28 @@ def list_image_queries(self, page: int = 1, page_size: int = 10) -> PaginatedIma
122125 def submit_image_query (
123126 self ,
124127 detector : Union [Detector , str ],
125- image : Union [str , bytes , BytesIO , BufferedReader , np .ndarray ],
126- wait : float = 30 ,
128+ image : Union [str , bytes , Image . Image , BytesIO , BufferedReader , np .ndarray ],
129+ wait : Optional [ float ] = None ,
127130 ) -> ImageQuery :
128131 """Evaluates an image with Groundlight.
129132 :param detector: the Detector object, or string id of a detector like `det_12345`
130133 :param image: The image, in several possible formats:
131- - a filename (string) of a jpeg file
132- - a byte array or BytesIO with jpeg bytes
133- - a numpy array in the 0-255 range (gets converted to jpeg)
134+ - filename (string) of a jpeg file
135+ - byte array or BytesIO or BufferedReader with jpeg bytes
136+ - numpy array with values 0-255 and dimensions (H,W,3) in RGB order
137+ (Note OpenCV uses BGR not RGB. `img[:, :, ::-1]` will reverse the channels)
138+ - PIL Image
139+ Any binary format must be JPEG-encoded already. Any pixel format will get
140+ converted to JPEG at high quality before sending to service.
134141 :param wait: How long to wait (in seconds) for a confident answer
135142 """
143+ if wait is None :
144+ wait = self .DEFAULT_WAIT
136145 if isinstance (detector , Detector ):
137146 detector_id = detector .id
138147 else :
139148 detector_id = detector
140- image_bytesio : Union [BytesIO , BufferedReader ]
141- # TODO: support PIL Images
142- if isinstance (image , str ):
143- # Assume it is a filename
144- image_bytesio = buffer_from_jpeg_file (image )
145- elif isinstance (image , bytes ):
146- # Create a BytesIO object
147- image_bytesio = BytesIO (image )
148- elif isinstance (image , BytesIO ) or isinstance (image , BufferedReader ):
149- # Already in the right format
150- image_bytesio = image
151- elif isinstance (image , np .ndarray ):
152- image_bytesio = BytesIO (jpeg_from_numpy (image ))
153- else :
154- raise TypeError (
155- "Unsupported type for image. We only support numpy arrays (3,W,H) or JPEG images specified through a filename, bytes, BytesIO, or BufferedReader object."
156- )
149+ image_bytesio : Union [BytesIO , BufferedReader ] = parse_supported_image_types (image )
157150
158151 raw_image_query = self .image_queries_api .submit_image_query (detector_id = detector_id , body = image_bytesio )
159152 image_query = ImageQuery .parse_obj (raw_image_query .to_dict ())
0 commit comments