Source code for cv2ext.detection._blob

# Copyright (c) 2024 Justin Davis (davisjustin302@gmail.com)
#
# MIT License
from __future__ import annotations

from typing import TYPE_CHECKING

import cv2

if TYPE_CHECKING:
    import numpy as np
    from typing_extensions import Self


[docs] def detect_blobs( image: np.ndarray, kernel_size: int = 9, sigma: float = 2.0, max_area: float = 0.9, min_area: float = 0.05, *, use_blur: bool | None = None, is_rgb: bool | None = None, filter_size: bool | None = None, ) -> list[tuple[int, int, int, int]]: """ Detect blobs in an image. Blob detection is performed using OpenCVs, findContours function. Each contour is identified and then a bounding box is created for each one. Parameters ---------- image : np.ndarray The image to detect blobs in. kernel_size : int The size of the kernel for the Gaussian blur. sigma : float The standard deviation for the Gaussian blur. max_area : float The maximum area a bounding box can be relative to the image. Default is 0.9, so bounding boxes larger than 90% of the image will be removed from final result if filtering enabled. min_area : float The minimum area a bounding box can be relative to the image. Default is 0.01, so bounding boxes smaller than 5% of the image will be removed from final result if filtering enabled. use_blur : bool, optional Whether or not to use a Gaussian blur on the image. By default, blur will be used. is_rgb : bool, optional Whether or not the image is in RGB format. Pass True if input image is RGB instead of BGR (OpenCV default). filter_size : bool, optional Whether or not to filter the final bounding boxes by the area of the bounding box. Returns ------- list[tuple[int, int, int, int]] A list of bounding boxes for each blob. """ # polish parameters if use_blur is None: use_blur = True if filter_size is None: filter_size = False # image info img_height, img_width = image.shape[:2] img_area = img_height * img_width # color conversion conversion = cv2.COLOR_RGB2GRAY if is_rgb else cv2.COLOR_BGR2GRAY gray = cv2.cvtColor(image, conversion) if use_blur: gray = cv2.GaussianBlur(gray, (kernel_size, kernel_size), sigma) _, threshold = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) # actual contour detection contours, _ = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # create bounding boxes bboxes = [] for contour in contours: x, y, w, h = cv2.boundingRect(contour) if filter_size: area = w * h if area / img_area > max_area or area / img_area < min_area: continue bboxes.append((x, y, x + w, y + h)) return bboxes
[docs] class BlobDetector: """Class for detecting blobs in images.""" def __init__( self: Self, kernel_size: int = 9, sigma: float = 2.0, max_area: float = 0.9, min_area: float = 0.05, *, use_blur: bool | None = None, is_rgb: bool | None = None, filter_size: bool | None = None, ) -> None: """ Create a new BlobDetector. Parameters ---------- kernel_size : int The size of the kernel for the Gaussian blur. sigma : float The standard deviation for the Gaussian blur. max_area : float The maximum area a bounding box can be relative to the image. Default is 0.9, so bounding boxes larger than 90% of the image will be removed from final result if filtering enabled. min_area : float The minimum area a bounding box can be relative to the image. Default is 0.01, so bounding boxes smaller than 5% of the image will be removed from final result if filtering enabled. use_blur : bool, optional Whether or not to use a Gaussian blur on the image. By default, blur will be used. is_rgb : bool, optional Whether or not the image is in RGB format. Pass True if input image is RGB instead of BGR (OpenCV default). filter_size : bool, optional Whether or not to filter the final bounding boxes by the area of the bounding box. """ self._kernel_size = kernel_size self._sigma = sigma self._max_area = max_area self._min_area = min_area self._use_blur = use_blur self._is_rgb = is_rgb self._filter_size = filter_size def __call__(self: Self, image: np.ndarray) -> list[tuple[int, int, int, int]]: """ Detect blobs in an image. Parameters ---------- image : np.ndarray The image to detect blobs in. Returns ------- list[tuple[int, int, int, int]] A list of bounding boxes for each blob. """ return self.detect(image)
[docs] def detect(self: Self, image: np.ndarray) -> list[tuple[int, int, int, int]]: """ Detect blobs in an image. Parameters ---------- image : np.ndarray The image to detect blobs in. Returns ------- list[tuple[int, int, int, int]] A list of bounding boxes for each blob. """ return detect_blobs( image, self._kernel_size, self._sigma, self._max_area, self._min_area, use_blur=self._use_blur, is_rgb=self._is_rgb, filter_size=self._filter_size, )