Source code for gbvision.tools.image_tools
from typing import Union
import cv2
import numpy as np
import typing
from gbvision.constants.images import COLOR_TYPE
from gbvision.constants.types import Frame, Number, ROI, ColorThresholdParams, GrayScaleThresholdParams
from gbvision.utils.thresholds import ColorThreshold
from gbvision.utils.thresholds.threshold import Threshold
[docs]def crop(frame: Frame, x: int, y: int, w: int, h: int) -> Frame:
"""
crops the image from (x, y) to (x+w, y+h)
:param frame: the frame to crop
:param x: the x coordinate to crop from
:param y: the y coordinate to crop from
:param w: the width of the cropped image
:param h: the height of the cropped image
:return: the cropped image
"""
return frame[y:y + h, x:x + w]
[docs]def median_threshold(frame: Frame, stdv: Union[Number, np.ndarray],
box: Union[None, ROI] = None, color_encoding=ColorThreshold.THRESH_TYPE_BGR) -> Threshold:
"""
finds a threshold using the median threshold method
the median threshold method defines the lower bounds of the threshold as the median of a given region of the image
minus some deviation variable, and the upper bounds as the same median plus the deviation variable
in a mathematical term, the threshold is defined to be [median(X) - V, median(X) + V] where X is the frame region
and V is the deviation variable
:param frame: the frame
:param stdv: the deviation variable, can be a scalar (same deviation for every channel) or a numpy array with the
same size as the number of channels in the threshold, the deviation will be defined for each channel separately
:param box: optional, a sub region of the frame from which the median is calculated, when set to None the median is
calculated from the entire frame
:param color_encoding: the type of color encoding the threshold should use, default is BGR
:return: a Threshold object
"""
if box is not None:
frame = crop(frame, *box)
color_encoding = color_encoding.upper()
if color_encoding != ColorThreshold.THRESH_TYPE_BGR:
frame = cv2.cvtColor(frame, COLOR_TYPE[color_encoding])
med = np.median(frame, axis=(0, 1)).astype(int)
if type(med) is not np.ndarray:
med = np.array([med])
params = tuple(map(lambda x: tuple(map(int, x)),
np.vectorize(lambda x: min(255, max(0, x)))(np.array([med - stdv, med + stdv])).T))
return ColorThreshold(typing.cast(Union[ColorThresholdParams, GrayScaleThresholdParams], params), color_encoding)