Shortcuts

Source code for caer.preprocessing.mean_subtraction

#    _____           ______  _____ 
#  / ____/    /\    |  ____ |  __ \
# | |        /  \   | |__   | |__) | Caer - Modern Computer Vision
# | |       / /\ \  |  __|  |  _  /  Languages: Python, C, C++, Cuda
# | |___   / ____ \ | |____ | | \ \  http://github.com/jasmcaus/caer
#  \_____\/_/    \_ \______ |_|  \_\

# Licensed under the MIT License <http://opensource.org/licenses/MIT>
# SPDX-License-Identifier: MIT
# Copyright (c) 2020-2021 The Caer Authors <http://github.com/jasmcaus>


#pylint:disable=pointless-string-statement

from .._internal import _check_mean_sub_values
from ..path import exists, list_images
from ..io import imread 
from ..coreten import Tensor
from ..annotations import Tuple, List

import numpy as np
import cv2 as cv

"""
    Important notes:
    Mean subtract must be computed ONLY on the training set and then later applied on the validation/test set
"""

__all__ = [
    'MeanProcess',
    'compute_mean',
    'compute_mean_from_dir',
    'subtract_mean',
]

class MeanProcess:
    def __init__(self, mean_sub_values, channels) -> None:
        # mean_sub_values is a tuple
        flag = _check_mean_sub_values(mean_sub_values, channels)
        if flag:
            if channels == 3:
                self.rMean = mean_sub_values[0]
                self.gMean = mean_sub_values[1]
                self.bMean = mean_sub_values[2]
            else:
                self.bgrMean = mean_sub_values[0]

    def mean_preprocess(self, image, channels) -> Tensor:
        """
            Mean Subtraction performed per channel
            Mean must be calculated ONLY on the training set
        """

        if channels == 3:
            b, g, r = cv.split(image.astype('float32'))[:3]

            # Subtracting the mean
            r -= self.rMean
            g -= self.gMean
            b -= self.bMean

            # Merging 
            return cv.merge([b,g,r])
        
        if channels == 1:
            image -= self.bgrMean
            return image
            

[docs]def compute_mean_from_dir(DIR, channels, per_channel_subtraction=True, recursive=True) -> Tuple: """ Computes mean per channel Mean must be computed ONLY on the train set """ if not exists(DIR): raise ValueError('The specified directory does not exist') image_list = list_images(DIR, recursive=recursive, use_fullpath=True, verbose=0) if len(image_list) == 0: raise ValueError(f'No images found at {DIR}') if channels == 3: rMean, gMean, bMean = 0, 0, 0 if channels == 1: bgrMean = 0 count = 0 for tens_filepath in image_list: count += 1 tens = imread(tens_filepath, rgb=True) if channels == 3: b, g, r = cv.mean(tens.astype('float32'))[:3] rMean += r bMean += b gMean += g if channels == 1: bgrMean += np.mean(tens.astype('float32')) # Computing average mean if channels == 3: rMean /= count bMean /= count gMean /= count if per_channel_subtraction: return rMean, bMean, gMean else: mean_of_means = (rMean + bMean + gMean) / 3 return mean_of_means, mean_of_means, mean_of_means if channels == 1: bgrMean /= count return tuple([bgrMean])
[docs]def compute_mean(data, channels, per_channel_subtraction=True) -> Tuple: """ Computes mean per channel over the train set and returns a tuple of dimensions=channels Train should not be normalized """ if len(data) == 0: raise ValueError('Dataset is empty') if not isinstance(data, (list, Tensor)): raise ValueError('Dataset must be a list of size=number of images and shape=image shape') if channels == 3: rMean, gMean, bMean = 0,0,0 if channels == 1: bgrMean = 0 count = 0 for tens in data: count += 1 if channels == 3: b, g, r = cv.mean(tens.astype('float32'))[:3] rMean += r gMean += g bMean += b if channels == 1: bgrMean += np.mean(tens.astype('float32')) # Computing average mean if channels == 3: rMean /= count bMean /= count gMean /= count if per_channel_subtraction: return rMean, bMean, gMean else: mean_of_means = (rMean + bMean + gMean) / 3 return mean_of_means, mean_of_means, mean_of_means if channels == 1: bgrMean /= count return tuple([bgrMean])
[docs]def subtract_mean(data, channels, mean_sub_values) -> List[str]: """ Per channel subtraction values computed from compute_mean() or compute_mean_from_dir() Subtracts mean from the validation set """ mean_process = MeanProcess(mean_sub_values, channels) if len(data) == 0: raise ValueError('Dataset is empty') if not isinstance(data, (list, Tensor)): raise ValueError('Dataset must be a list of size = number of images and shape = image shape') data = [mean_process.mean_preprocess(tens, channels) for tens in data] return data
Read the Docs v: stable
Versions
latest
stable
Downloads
pdf
On Read the Docs
Project Home
Builds

Free document hosting provided by Read the Docs.