|
from time import perf_counter |
|
from typing import Any, List, Tuple, Union |
|
|
|
import numpy as np |
|
|
|
from inference.core.entities.requests.inference import InferenceRequest |
|
from inference.core.entities.responses.inference import InferenceResponse |
|
from inference.core.models.types import PreprocessReturnMetadata |
|
|
|
|
|
class BaseInference: |
|
"""General inference class. |
|
|
|
This class provides a basic interface for inference tasks. |
|
""" |
|
|
|
def infer(self, image: Any, **kwargs) -> Any: |
|
"""Runs inference on given data.""" |
|
preproc_image, returned_metadata = self.preprocess(image, **kwargs) |
|
predicted_arrays = self.predict(preproc_image, **kwargs) |
|
postprocessed = self.postprocess(predicted_arrays, returned_metadata, **kwargs) |
|
|
|
return postprocessed |
|
|
|
def preprocess( |
|
self, image: Any, **kwargs |
|
) -> Tuple[np.ndarray, PreprocessReturnMetadata]: |
|
raise NotImplementedError |
|
|
|
def predict(self, img_in: np.ndarray, **kwargs) -> Tuple[np.ndarray, ...]: |
|
raise NotImplementedError |
|
|
|
def postprocess( |
|
self, |
|
predictions: Tuple[np.ndarray, ...], |
|
preprocess_return_metadata: PreprocessReturnMetadata, |
|
**kwargs |
|
) -> Any: |
|
raise NotImplementedError |
|
|
|
def infer_from_request( |
|
self, request: InferenceRequest |
|
) -> Union[InferenceResponse, List[InferenceResponse]]: |
|
"""Runs inference on a request |
|
|
|
Args: |
|
request (InferenceRequest): The request object. |
|
|
|
Returns: |
|
Union[CVInferenceResponse, List[CVInferenceResponse]]: The response object(s). |
|
|
|
Raises: |
|
NotImplementedError: This method must be implemented by a subclass. |
|
""" |
|
raise NotImplementedError |
|
|
|
def make_response( |
|
self, *args, **kwargs |
|
) -> Union[InferenceResponse, List[InferenceResponse]]: |
|
"""Constructs an object detection response. |
|
|
|
Raises: |
|
NotImplementedError: This method must be implemented by a subclass. |
|
""" |
|
raise NotImplementedError |
|
|
|
|
|
class Model(BaseInference): |
|
"""Base Inference Model (Inherits from BaseInference to define the needed methods) |
|
|
|
This class provides the foundational methods for inference and logging, and can be extended by specific models. |
|
|
|
Methods: |
|
log(m): Print the given message. |
|
clear_cache(): Clears any cache if necessary. |
|
""" |
|
|
|
def log(self, m): |
|
"""Prints the given message. |
|
|
|
Args: |
|
m (str): The message to print. |
|
""" |
|
print(m) |
|
|
|
def clear_cache(self): |
|
"""Clears any cache if necessary. This method should be implemented in derived classes as needed.""" |
|
pass |
|
|
|
def infer_from_request( |
|
self, |
|
request: InferenceRequest, |
|
) -> Union[List[InferenceResponse], InferenceResponse]: |
|
""" |
|
Perform inference based on the details provided in the request, and return the associated responses. |
|
The function can handle both single and multiple image inference requests. Optionally, it also provides |
|
a visualization of the predictions if requested. |
|
|
|
Args: |
|
request (InferenceRequest): The request object containing details for inference, such as the image or |
|
images to process, any classes to filter by, and whether or not to visualize the predictions. |
|
|
|
Returns: |
|
Union[List[InferenceResponse], InferenceResponse]: A list of response objects if the request contains |
|
multiple images, or a single response object if the request contains one image. Each response object |
|
contains details about the segmented instances, the time taken for inference, and optionally, a visualization. |
|
|
|
Examples: |
|
>>> request = InferenceRequest(image=my_image, visualize_predictions=True) |
|
>>> response = infer_from_request(request) |
|
>>> print(response.time) # Prints the time taken for inference |
|
0.125 |
|
>>> print(response.visualization) # Accesses the visualization of the prediction if available |
|
|
|
Notes: |
|
- The processing time for each response is included within the response itself. |
|
- If `visualize_predictions` is set to True in the request, a visualization of the prediction |
|
is also included in the response. |
|
""" |
|
t1 = perf_counter() |
|
responses = self.infer(**request.dict(), return_image_dims=False) |
|
for response in responses: |
|
response.time = perf_counter() - t1 |
|
|
|
if request.visualize_predictions: |
|
for response in responses: |
|
response.visualization = self.draw_predictions(request, response) |
|
|
|
if not isinstance(request.image, list) and len(responses) > 0: |
|
responses = responses[0] |
|
|
|
return responses |
|
|
|
def make_response( |
|
self, *args, **kwargs |
|
) -> Union[InferenceResponse, List[InferenceResponse]]: |
|
"""Makes an inference response from the given arguments. |
|
|
|
Args: |
|
*args: Variable length argument list. |
|
**kwargs: Arbitrary keyword arguments. |
|
|
|
Returns: |
|
InferenceResponse: The inference response. |
|
""" |
|
raise NotImplementedError(self.__class__.__name__ + ".make_response") |
|
|