diff --git a/.gitignore b/.gitignore index 6fcbd68..6b61e58 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,4 @@ _static/ _templates/ __pycache__/ .ipynb_checkpoints/ +.vscode/ \ No newline at end of file diff --git a/Augmentor/Operations.py b/Augmentor/Operations.py index 26b94ba..db5e120 100644 --- a/Augmentor/Operations.py +++ b/Augmentor/Operations.py @@ -35,6 +35,8 @@ import os import random import warnings +# Added CLAHE algorithm from CV2 +import cv2 # Python 2-3 compatibility - not currently needed. # try: @@ -2127,3 +2129,51 @@ def do(image1, image2, y1, y2): augmented_images.append(do(image, image, y1, y2)) return augmented_images + + +class Clahe(Operation): + """ + This class : Clahe is used to perform Contrast Limited Adaptive Histogram Equalization + as it is implemented in the OpenCV2 library 4.1.1 + """ + + def __init__(self, probability, clip_limit_min=0.0, clip_limit_max=40.0, tile_grid=(8, 8)): + """ + Initializes parameters + :param probability: Controls the probability that the operation is + performed when it is inovked in the pipeline + :param clip_limit_min: Sets the contrast limit min value + :param clip_limit_max: Sets the contrast limit max value + :param tile_grid: it controls the size of the blocks that are to be histogram equalized. Default + value as described in docs.opencv.org is 8x8 + """ + Operation.__init__(self, probability) + self.clip_limit_min = clip_limit_min + self.clip_limit_max = clip_limit_max + self.tile_grid = tile_grid + + def __str__(self): + return "Clahe contrast_limit_min: {}, contrast_limit_max {}, tile: {}".format(self.clip_limit_min, + self.clip_limit_max, + self.tile_grid) + + def perform_operation(self, images): + """ + Perform OpenCV Contrast Limited Adaptive Histogram Equalization + :param images: The image(s) to equalize + :return: The transformed image(s) as a list of object(s) of type PIL.Image. + """ + def do(image): + if not image.mode == 'L': + img_grayscale = ImageOps.grayscale(image) + else: + img_grayscale = image + + clip_limit_threshold = np.random.uniform(self.clip_limit_min, self.clip_limit_max) + img_cv2 = np.asarray(img_grayscale) + clahe_cv2 = cv2.createCLAHE(clipLimit=clip_limit_threshold, tileGridSize=self.tile_grid) + img_clahe = clahe_cv2.apply(img_cv2) + return img_clahe + + augmented_images = [Image.fromarray(do(img)) for img in images] + return augmented_images diff --git a/Augmentor/Pipeline.py b/Augmentor/Pipeline.py index c7a5aa0..96cc397 100644 --- a/Augmentor/Pipeline.py +++ b/Augmentor/Pipeline.py @@ -1311,6 +1311,32 @@ def histogram_equalisation(self, probability=1.0): else: self.add_operation(HistogramEqualisation(probability=probability)) + def clahe(self, probability, clip_limit_min, clip_limit_max, tile_grid): + """ + Apply Contrast Limited Adaptive Histogram Equalization + In order to avoid noise amplification a contrast limited is required. If clip_limit_min and clip_limit_max + have different values, different CLAHE will be obtained randomly + + If the user desires to use CLAHE as a preprocess by using the same clip_limit value, then set: + clip_limit_min = clip_limit_max + + :param probability: The probability that the function will execute + when the image is passed through the pipeline. + :param clip_limit_min: min value of clip_limit. + :param clip_limit_max: max value of clip_limit + :param tile_grid: the number of pixels of the block to be equalized + + More information consult at docs.opencv.org + + """ + if not 0 < probability <= 1: + raise ValueError(Pipeline._probability_error_text) + else: + self.add_operation(Clahe(probability=probability, + clip_limit_min=clip_limit_min, + clip_limit_max=clip_limit_max, + tile_grid=tile_grid)) + def scale(self, probability, scale_factor): """ Scale (enlarge) an image, while maintaining its aspect ratio. This diff --git a/requirements.txt b/requirements.txt index e75d9b1..b24059b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,5 @@ Pillow future futures tqdm -numpy \ No newline at end of file +numpy +opencv-python \ No newline at end of file