Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/sg 747 add full pipeline with preprocessing #807

Merged
merged 53 commits into from
Apr 3, 2023

Conversation

Louis-Dupont
Copy link
Contributor

@Louis-Dupont Louis-Dupont commented Mar 29, 2023

Includes code from #804, so #804 needs to be merged first

@dagshub
Copy link

dagshub bot commented Mar 29, 2023

Copy link
Collaborator

@shaydeci shaydeci left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Writing down the main concern we have discussed together:

  • Hard coding the default _image_processor and _class_names is bad practice, and might lead users who do not use these (which will probably happen - any time they do not train on coco). Lets add setters that will by the pretrained_weights str set these attributes accordingly.
  • Please also add a ticket for making it possible to set them from the recipe itself - so that when users complete their training they can use predict right away.

Dont forget to add the implementation for DeciYolo.

@Louis-Dupont Louis-Dupont marked this pull request as ready for review April 3, 2023 11:33
@Louis-Dupont
Copy link
Contributor Author

Louis-Dupont commented Apr 3, 2023

@shaydeci I also updated the Results classes to work with the changes that were introduced in the previous PR, so you can check it out now

from abc import ABC, abstractmethod
from typing import List, Optional, Tuple
from dataclasses import dataclass
from matplotlib import pyplot as plt
import numpy as np
from super_gradients.training.utils.detection_utils import DetectionVisualization
from super_gradients.training.models.predictions import Prediction, DetectionPrediction
@dataclass
class Result(ABC):
"""Results of a given computer vision task (detection, classification, etc.).
:attr image: Input image
:attr predictions: Predictions of the model
:attr class_names: List of the class names to predict
"""
image: np.ndarray
predictions: Prediction
class_names: List[str]
@abstractmethod
def draw(self) -> np.ndarray:
"""Draw the predictions on the image."""
pass
@abstractmethod
def show(self) -> None:
"""Display the predictions on the image."""
pass
@dataclass
class Results(ABC):
"""List of results of a given computer vision task (detection, classification, etc.).
:attr results: List of results of the run
"""
results: List[Result]
@abstractmethod
def draw(self) -> List[np.ndarray]:
"""Draw the predictions on the image."""
pass
@abstractmethod
def show(self) -> None:
"""Display the predictions on the image."""
pass
@dataclass
class DetectionResult(Result):
"""Result of a detection task.
:attr image: Input image
:attr predictions: Predictions of the model
:attr class_names: List of the class names to predict
"""
image: np.ndarray
predictions: DetectionPrediction
class_names: List[str]
def draw(self, box_thickness: int = 2, show_confidence: bool = True, color_mapping: Optional[List[Tuple[int]]] = None) -> np.ndarray:
"""Draw the predicted bboxes on the image.
:param box_thickness: Thickness of bounding boxes.
:param show_confidence: Whether to show confidence scores on the image.
:param color_mapping: List of tuples representing the colors for each class.
Default is None, which generates a default color mapping based on the number of class names.
:return: Image with predicted bboxes. Note that this does not modify the original image.
"""
image_np = self.image.copy()
color_mapping = color_mapping or DetectionVisualization._generate_color_mapping(len(self.class_names))
for pred_i in range(len(self.predictions)):
image_np = DetectionVisualization._draw_box_title(
color_mapping=color_mapping,
class_names=self.class_names,
box_thickness=box_thickness,
image_np=image_np,
x1=int(self.predictions.bboxes_xyxy[pred_i, 0]),
y1=int(self.predictions.bboxes_xyxy[pred_i, 1]),
x2=int(self.predictions.bboxes_xyxy[pred_i, 2]),
y2=int(self.predictions.bboxes_xyxy[pred_i, 3]),
class_id=int(self.predictions.labels[pred_i]),
pred_conf=self.predictions.confidence[pred_i] if show_confidence else None,
)
return image_np
def show(self, box_thickness: int = 2, show_confidence: bool = True, color_mapping: Optional[List[Tuple[int]]] = None) -> None:
"""Display the image with predicted bboxes.
:param box_thickness: Thickness of bounding boxes.
:param show_confidence: Whether to show confidence scores on the image.
:param color_mapping: List of tuples representing the colors for each class.
Default is None, which generates a default color mapping based on the number of class names.
"""
image_np = self.draw(box_thickness=box_thickness, show_confidence=show_confidence, color_mapping=color_mapping)
plt.imshow(image_np, interpolation="nearest")
plt.axis("off")
plt.show()
@dataclass
class DetectionResults(Results):
"""Results of a detection task.
:attr results: List of the predictions results
"""
def __init__(self, images: List[np.ndarray], predictions: List[DetectionPrediction], class_names: List[str]):
self.results: List[DetectionResult] = []
for image, prediction in zip(images, predictions):
self.results.append(DetectionResult(image=image, predictions=prediction, class_names=class_names))
def draw(self, box_thickness: int = 2, show_confidence: bool = True, color_mapping: Optional[List[Tuple[int]]] = None) -> List[np.ndarray]:
"""Draw the predicted bboxes on the images.
:param box_thickness: Thickness of bounding boxes.
:param show_confidence: Whether to show confidence scores on the image.
:param color_mapping: List of tuples representing the colors for each class.
Default is None, which generates a default color mapping based on the number of class names.
:return: List of Images with predicted bboxes for each image. Note that this does not modify the original images.
"""
return [prediction.draw(box_thickness=box_thickness, show_confidence=show_confidence, color_mapping=color_mapping) for prediction in self.results]
def show(self, box_thickness: int = 2, show_confidence: bool = True, color_mapping: Optional[List[Tuple[int]]] = None) -> None:
"""Display the predicted bboxes on the images.
:param box_thickness: Thickness of bounding boxes.
:param show_confidence: Whether to show confidence scores on the image.
:param color_mapping: List of tuples representing the colors for each class.
Default is None, which generates a default color mapping based on the number of class names.
"""
for prediction in self.results:
prediction.show(box_thickness=box_thickness, show_confidence=show_confidence, color_mapping=color_mapping)

Copy link
Collaborator

@shaydeci shaydeci left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@shaydeci shaydeci merged commit d5a456d into master Apr 3, 2023
@shaydeci shaydeci deleted the feature/SG-747-add_full_pipeline_with_preprocessing branch April 3, 2023 16:26
Louis-Dupont added a commit that referenced this pull request Apr 17, 2023
* wip

* move to imageprocessors

* wip

* add back changes

* making it work fully for yolox and almost for ppyoloe

* minor change

* working for det

* cleaning

* clean

* undo

* replace empty with none

* add _get_shift_params

* minor doc change

* cleaning wip

* working for multiple images

* add ppyoloe

* replace pydantic with dataclasses and fix typing

* add docstrings

* doc improvment and use get_shift_params in transforms

* add tests

* improve comment

* rename

* wip

* add option to keep ratio in rescale

* make functions private

* remove DetectionPaddedRescale

* fix doc

* big commit with wrong things

* try undo bad change

* doc

* minor doc

* add a lot of doc

* fix comment

* minor change

* add __init__.py to pipelines

* replace size with shape

* wip

* make pipeline work again with Predction objects

* set processing params based on checkpoints

* remove unwanted change

* use __call__ instead of _run

---------

Co-authored-by: Shay Aharon <80472096+shaydeci@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants