SPPAS 4.22

https://sppas.org/

Module sppas.src.imgdata

Class sppasImageObjectDetection

Description

Detect objects in an image.

This class allows to analyze an image in order to detect objects. It stores a list of sppasCoords() for each detected object.

Example
Example
 >>> f = sppasImageObjectDetection()
 >>> f.load_model(filename1, filename2...)
 >>> # Detect all the objects in an image
 >>> f.detect(sppasImage(filename="image path"))
 >>> # Get number of detected objects
 >>> len(f)
 >>> # Browse through the detected object coordinates:
 >>> for c in f:
 >>> print(c)
 >>> # Get the detected object with the highest score
 >>> f.get_best()
 >>> # Get the 2 objects with the highest scores
 >>> f.get_best(2)
 >>> # Get detected objects with a confidence score greater than 0.9
 >>> f.get_confidence(0.9)

Contrariwise to the base class, this class allows multiple models in order to launch multiple detections and to combine their results.

Constructor

Create a new ImageObjectDetection instance.

View Source
def __init__(self):
    """Create a new ImageObjectDetection instance."""
    super(sppasImageObjectDetection, self).__init__()
    self._extension = ''
    self._detector = None

Public functions

get_nb_recognizers

Return the number of initialized object recognizers.

View Source
def get_nb_recognizers(self):
    """Return the number of initialized object recognizers."""
    if self._detector is None:
        return 0
    return len(self._detector)

get_nb_enabled_recognizers

Return the number of enabled object recognizers.

View Source
def get_nb_enabled_recognizers(self):
    """Return the number of enabled object recognizers."""
    nb = 0
    if self._detector is not None:
        for detector in self._detector:
            if self._detector[detector][1] is True:
                nb += 1
    return nb

get_recognizer_names

Return the name of all the initialized recognizers.

View Source
def get_recognizer_names(self):
    """Return the name of all the initialized recognizers."""
    if self._detector is None:
        return list()
    return [self._detector[d][0] for d in self._detector]

get_enabled_recognizer_names

Return the name of all the initialized recognizers.

View Source
def get_enabled_recognizer_names(self):
    """Return the name of all the initialized recognizers. """
    r = list()
    if self._detector is not None:
        for d in self._detector:
            if self._detector[d][1] is True:
                r.append(self._detector[d][0])
    return r

get_recognizer

Return the recognizer of the given name or None.

Parameters
  • name: (str) Name of a recognizer.
Returns
  • (BaseObjectsDetector or None)
View Source
def get_recognizer(self, name):
    """Return the recognizer of the given name or None.

        :param name: (str) Name of a recognizer.
        :return: (BaseObjectsDetector or None)

        """
    if self._detector is not None:
        for detector in self._detector:
            if self._detector[detector][0] == name:
                return detector
    return None

enable_recognizer

Enable or disable a recognizer.

Parameters
  • name: (str) Name of a recognizer.
  • value: (bool)
View Source
def enable_recognizer(self, name, value=True):
    """Enable or disable a recognizer.

        :param name: (str) Name of a recognizer.
        :param value: (bool)

        """
    value = bool(value)
    if self._detector is not None:
        for detector in self._detector:
            if self._detector[detector][0] == name:
                self._detector[detector] = (name, value)
                return value
    return False

extensions

Return the whole list of supported extensions in lower case.

View Source
@staticmethod
def extensions():
    """Return the whole list of supported extensions in lower case."""
    return list(sppasImageObjectDetection.DETECTORS.keys())

load_model

Instantiate detector(s) from the given models.

Calling this method invalidates the existing detectors. All instantiated detectors are enabled by default. The min ratio is divided by the number of detectors.

Parameters
  • model: (str) Default required model filename
  • args: Other models to load in order to create object detectors
Raises

IOError, Exception

View Source
def load_model(self, model, *args):
    """Instantiate detector(s) from the given models.

        Calling this method invalidates the existing detectors.
        All instantiated detectors are enabled by default.
        The min ratio is divided by the number of detectors.

        :param model: (str) Default required model filename
        :param args: Other models to load in order to create object detectors
        :raise: IOError, Exception

        """
    self._detector = dict()
    detector = sppasImageObjectDetection.create_recognizer_from_extension(model)
    detector.load_model(model)
    detector_name = os.path.basename(model)
    self._detector[detector] = (detector_name, True)
    for filename in args:
        try:
            detector = sppasImageObjectDetection.create_recognizer_from_extension(filename)
            detector.load_model(filename)
            detector_name = os.path.basename(filename)
            self._detector[detector] = (detector_name, True)
        except Exception as e:
            logging.error(e)
    for detector in self._detector:
        detector.set_min_ratio(self.get_min_ratio() / len(self._detector))

create_recognizer_from_extension

Return an object detector according to a given filename.

Only the extension of the filename is used.

Parameters
  • filename: (str)
Returns
  • BaseObjectsDetector
Raises

IOError

View Source
@staticmethod
def create_recognizer_from_extension(filename):
    """Return an object detector according to a given filename.

        Only the extension of the filename is used.

        :param filename: (str)
        :return: BaseObjectsDetector
        :raise: IOError

        """
    extension = os.path.splitext(filename)[1]
    extension = extension.lower()
    if extension in sppasImageObjectDetection.extensions():
        return sppasImageObjectDetection.DETECTORS[extension]()
    raise IOExtensionError(filename)

filter_overlapped

Remove overlapping detected objects and too small scores.

It is supposed that the scores are already sorted by scores.

Parameters
  • overlap: (float) Minimum percentage of overlapped area to invalidate an object
  • norm_score: (bool) Normalize the score of the detected objects by the number of detectors
View Source
def filter_overlapped(self, overlap=50.0, norm_score=True):
    """Remove overlapping detected objects and too small scores.

        It is supposed that the scores are already sorted by scores.

        :param overlap: (float) Minimum percentage of overlapped area to invalidate an object
        :param norm_score: (bool) Normalize the score of the detected objects by the number of detectors

        """
    overlap = float(overlap)
    if overlap < 0.0 or overlap > 100.0:
        raise IntervalRangeException(overlap, 0.0, 100.0)
    detected = list()
    for coord in self._coords:
        c = coord.copy()
        score = c.get_confidence()
        nb = self.get_nb_enabled_recognizers()
        if norm_score is True and nb > 1:
            c.set_confidence(score / float(nb - 1))
        detected.append(c)
    for i, coord in enumerate(detected):
        for j, other in enumerate(detected):
            if other.get_confidence() == 0.0 or i == j:
                continue
            if coord.intersection_area(other) > 0:
                area_o, area_s = coord.overlap(other)
                if area_o > overlap:
                    c = min(1.0, other.get_confidence() + coord.get_confidence())
                    coord.set_confidence(c)
                    other.set_confidence(0.0)
                '\n                    # reject "i" object if more than 50% of its area is\n                    # overlapping "j" and "j" has a significant bigger \n                    # dimension, either w or h or both\n                    if area_s > overlap and (coord.w < other.w or coord.h < other.h):\n                        c = min(1., other.get_confidence() + coord.get_confidence())\n                        coord.set_confidence(0.)\n                        other.set_confidence(c)\n                    '
    self._coords = [c for c in detected if c.get_confidence() > self.get_min_score()]

Private functions

_detection

Determine the coordinates of all the detected objects.

No filter nor sort is applied. Results are "as it".

Parameters
  • image: (sppasImage or numpy.ndarray)
View Source
def _detection(self, image):
    """Determine the coordinates of all the detected objects.

        No filter nor sort is applied. Results are "as it".

        :param image: (sppasImage or numpy.ndarray)

        """
    if self.get_nb_enabled_recognizers() == 0:
        raise sppasError('None of the recognizers is enabled. At least one is required...')
    for detector in self._detector:
        if self._detector[detector][1] is True:
            detector.detect(image)
            for coord in detector:
                self._coords.append(coord)