Python cv2.BORDER_REFLECT Examples

The following are 30 code examples of cv2.BORDER_REFLECT(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module cv2 , or try the search function .
Example #1
Source File: data_augment.py    From ssds.pytorch with MIT License 7 votes vote down vote up
def _elastic(image, p, alpha=None, sigma=None, random_state=None):
    """Elastic deformation of images as described in [Simard2003]_ (with modifications).
    .. [Simard2003] Simard, Steinkraus and Platt, "Best Practices for
         Convolutional Neural Networks applied to Visual Document Analysis", in
         Proc. of the International Conference on Document Analysis and
         Recognition, 2003.
     Based on https://gist.github.com/erniejunior/601cdf56d2b424757de5
     From: 
     https://www.kaggle.com/bguberfain/elastic-transform-for-data-augmentation
    """
    if random.random() > p:
        return image
    if alpha == None:
        alpha = image.shape[0] * random.uniform(0.5,2)
    if sigma == None:
        sigma = int(image.shape[0] * random.uniform(0.5,1))
    if random_state is None:
        random_state = np.random.RandomState(None)

    shape = image.shape[:2]
    
    dx, dy = [cv2.GaussianBlur((random_state.rand(*shape) * 2 - 1) * alpha, (sigma|1, sigma|1), 0) for _ in range(2)]
    x, y = np.meshgrid(np.arange(shape[1]), np.arange(shape[0]))
    x, y = np.clip(x+dx, 0, shape[1]-1).astype(np.float32), np.clip(y+dy, 0, shape[0]-1).astype(np.float32)
    return cv2.remap(image, x, y, interpolation=cv2.INTER_LINEAR, borderValue= 0, borderMode=cv2.BORDER_REFLECT) 
Example #2
Source File: spfunctions.py    From spfeas with MIT License 6 votes vote down vote up
def get_mag_avg(img):

    img = np.sqrt(img)

    kernels = get_kernels()

    mag = np.zeros(img.shape, dtype='float32')

    for kernel_filter in kernels:

        gx = cv2.filter2D(np.float32(img), cv2.CV_32F, kernel_filter[1], borderType=cv2.BORDER_REFLECT)
        gy = cv2.filter2D(np.float32(img), cv2.CV_32F, kernel_filter[0], borderType=cv2.BORDER_REFLECT)

        mag += cv2.magnitude(gx, gy)

    mag /= len(kernels)

    return np.uint8(mag) 
Example #3
Source File: step2_train_mass_segmenter.py    From kaggle_ndsb2017 with MIT License 6 votes vote down vote up
def random_translate_img(img, xy_range, border_mode="constant"):
    if random.random() > xy_range.chance:
        return img
    import cv2
    if not isinstance(img, list):
        img = [img]

    org_height, org_width = img[0].shape[:2]
    translate_x = random.randint(xy_range.x_min, xy_range.x_max)
    translate_y = random.randint(xy_range.y_min, xy_range.y_max)
    trans_matrix = numpy.float32([[1, 0, translate_x], [0, 1, translate_y]])

    border_const = cv2.BORDER_CONSTANT
    if border_mode == "reflect":
        border_const = cv2.BORDER_REFLECT

    res = []
    for img_inst in img:
        img_inst = cv2.warpAffine(img_inst, trans_matrix, (org_width, org_height), borderMode=border_const)
        res.append(img_inst)
    if len(res) == 1:
        res = res[0]
    xy_range.last_x = translate_x
    xy_range.last_y = translate_y
    return res 
Example #4
Source File: eval.py    From dsb2018_topcoders with MIT License 6 votes vote down vote up
def predict8tta(model, batch, sigmoid):
    ret = []
    for cls in TTA:
        ret.append(cls(sigmoid)(model, batch))
    scale_tta = False
    if scale_tta:
        for scale in [0.8, 1.25]:
            data = np.moveaxis(np.squeeze(batch.numpy()[0]), 0, -1)
            srows, scols = data.shape[:2]
            data = cv2.resize(data, (0, 0), fx=scale, fy=scale)
            rows, cols = data.shape[:2]
            data = cv2.copyMakeBorder(data, 0, (32-rows%32), 0, (32-cols%32), cv2.BORDER_REFLECT)
            data = np.expand_dims(np.moveaxis(data, -1, 0), 0)
            data = torch.from_numpy(data)
            for cls in TTA:
                r = (cls(sigmoid)(model, data))
                r = np.moveaxis(np.squeeze(r), 0, -1)
                r = r[:rows, :cols, ...]
                r = cv2.resize(r, (scols, srows))
                r = np.expand_dims(np.moveaxis(r, -1, 0), 0)
                ret.append(r)
    return np.moveaxis(np.mean(ret, axis=0), 1, -1) 
Example #5
Source File: utils.py    From StructuredForests with BSD 2-Clause "Simplified" License 6 votes vote down vote up
def conv_tri(src, radius):
    """
    Image convolution with a triangle filter.

    :param src: input image
    :param radius: gradient normalization radius
    :return: convolution result
    """

    if radius == 0:
        return src
    elif radius <= 1:
        p = 12.0 / radius / (radius + 2) - 2
        kernel = N.asarray([1, p, 1], dtype=N.float64) / (p + 2)
        return cv2.sepFilter2D(src, ddepth=-1, kernelX=kernel, kernelY=kernel,
                               borderType=cv2.BORDER_REFLECT)
    else:
        radius = int(radius)
        kernel = range(1, radius + 1) + [radius + 1] + range(radius, 0, -1)
        kernel = N.asarray(kernel, dtype=N.float64) / (radius + 1) ** 2
        return cv2.sepFilter2D(src, ddepth=-1, kernelX=kernel, kernelY=kernel,
                               borderType=cv2.BORDER_REFLECT) 
Example #6
Source File: mosse.py    From PyCV-time with MIT License 5 votes vote down vote up
def rnd_warp(a):
    h, w = a.shape[:2]
    T = np.zeros((2, 3))
    coef = 0.2
    ang = (np.random.rand()-0.5)*coef
    c, s = np.cos(ang), np.sin(ang)
    T[:2, :2] = [[c,-s], [s, c]]
    T[:2, :2] += (np.random.rand(2, 2) - 0.5)*coef
    c = (w/2, h/2)
    T[:,2] = c - np.dot(T[:2, :2], c)
    return cv2.warpAffine(a, T, (w, h), borderMode = cv2.BORDER_REFLECT) 
Example #7
Source File: mosse.py    From pyCFTrackers with MIT License 5 votes vote down vote up
def _rand_warp(self,img):
        h, w = img.shape[:2]
        C = .1
        ang = np.random.uniform(-C, C)
        c, s = np.cos(ang), np.sin(ang)
        W = np.array([[c + np.random.uniform(-C, C), -s + np.random.uniform(-C, C), 0],
                      [s + np.random.uniform(-C, C), c + np.random.uniform(-C, C), 0]])
        center_warp = np.array([[w / 2], [h / 2]])
        tmp = np.sum(W[:, :2], axis=1).reshape((2, 1))
        W[:, 2:] = center_warp - center_warp * tmp
        warped = cv2.warpAffine(img, W, (w, h), cv2.BORDER_REFLECT)
        return warped 
Example #8
Source File: mosse.py    From OpenCV-Python-Tutorial with MIT License 5 votes vote down vote up
def rnd_warp(a):
    h, w = a.shape[:2]
    T = np.zeros((2, 3))
    coef = 0.2
    ang = (np.random.rand()-0.5)*coef
    c, s = np.cos(ang), np.sin(ang)
    T[:2, :2] = [[c,-s], [s, c]]
    T[:2, :2] += (np.random.rand(2, 2) - 0.5)*coef
    c = (w/2, h/2)
    T[:,2] = c - np.dot(T[:2, :2], c)
    return cv2.warpAffine(a, T, (w, h), borderMode = cv2.BORDER_REFLECT) 
Example #9
Source File: opencv_functional.py    From ss-ood with MIT License 5 votes vote down vote up
def affine(img, angle, translate, scale, shear, interpolation=cv2.INTER_CUBIC, mode=cv2.BORDER_CONSTANT, fillcolor=0):
    """Apply affine transformation on the image keeping image center invariant
    Args:
        img (numpy ndarray): numpy ndarray to be transformed.
        angle (float or int): rotation angle in degrees between -180 and 180, clockwise direction.
        translate (list or tuple of integers): horizontal and vertical translations (post-rotation translation)
        scale (float): overall scale
        shear (float): shear angle value in degrees between -180 to 180, clockwise direction.
        interpolation (``cv2.INTER_NEAREST` or ``cv2.INTER_LINEAR`` or ``cv2.INTER_AREA``, ``cv2.INTER_CUBIC``):
            An optional resampling filter.
            See `filters`_ for more information.
            If omitted, it is set to ``cv2.INTER_CUBIC``, for bicubic interpolation.
        mode (``cv2.BORDER_CONSTANT`` or ``cv2.BORDER_REPLICATE`` or ``cv2.BORDER_REFLECT`` or ``cv2.BORDER_REFLECT_101``)
            Method for filling in border regions. 
            Defaults to cv2.BORDER_CONSTANT, meaning areas outside the image are filled with a value (val, default 0)
        val (int): Optional fill color for the area outside the transform in the output image. Default: 0
    """
    if not _is_numpy_image(img):
        raise TypeError('img should be numpy Image. Got {}'.format(type(img)))

    assert isinstance(translate, (tuple, list)) and len(translate) == 2, \
        "Argument translate should be a list or tuple of length 2"

    assert scale > 0.0, "Argument scale should be positive"

    output_size = img.shape[0:2]
    center = (img.shape[1] * 0.5 + 0.5, img.shape[0] * 0.5 + 0.5)
    matrix = _get_affine_matrix(center, angle, translate, scale, shear)
    
    if img.shape[2]==1:
        return cv2.warpAffine(img, matrix, output_size[::-1],interpolation, borderMode=mode, borderValue=fillcolor)[:,:,np.newaxis]
    else:
        return cv2.warpAffine(img, matrix, output_size[::-1],interpolation, borderMode=mode, borderValue=fillcolor) 
Example #10
Source File: opencv_functional.py    From ss-ood with MIT License 5 votes vote down vote up
def affine(img, angle, translate, scale, shear, interpolation=cv2.INTER_CUBIC, mode=cv2.BORDER_CONSTANT, fillcolor=0):
    """Apply affine transformation on the image keeping image center invariant
    Args:
        img (numpy ndarray): numpy ndarray to be transformed.
        angle (float or int): rotation angle in degrees between -180 and 180, clockwise direction.
        translate (list or tuple of integers): horizontal and vertical translations (post-rotation translation)
        scale (float): overall scale
        shear (float): shear angle value in degrees between -180 to 180, clockwise direction.
        interpolation (``cv2.INTER_NEAREST` or ``cv2.INTER_LINEAR`` or ``cv2.INTER_AREA``, ``cv2.INTER_CUBIC``):
            An optional resampling filter.
            See `filters`_ for more information.
            If omitted, it is set to ``cv2.INTER_CUBIC``, for bicubic interpolation.
        mode (``cv2.BORDER_CONSTANT`` or ``cv2.BORDER_REPLICATE`` or ``cv2.BORDER_REFLECT`` or ``cv2.BORDER_REFLECT_101``)
            Method for filling in border regions. 
            Defaults to cv2.BORDER_CONSTANT, meaning areas outside the image are filled with a value (val, default 0)
        val (int): Optional fill color for the area outside the transform in the output image. Default: 0
    """
    if not _is_numpy_image(img):
        raise TypeError('img should be numpy Image. Got {}'.format(type(img)))

    assert isinstance(translate, (tuple, list)) and len(translate) == 2, \
        "Argument translate should be a list or tuple of length 2"

    assert scale > 0.0, "Argument scale should be positive"

    output_size = img.shape[0:2]
    center = (img.shape[1] * 0.5 + 0.5, img.shape[0] * 0.5 + 0.5)
    matrix = _get_affine_matrix(center, angle, translate, scale, shear)
    
    if img.shape[2]==1:
        return cv2.warpAffine(img, matrix, output_size[::-1],interpolation, borderMode=mode, borderValue=fillcolor)[:,:,np.newaxis]
    else:
        return cv2.warpAffine(img, matrix, output_size[::-1],interpolation, borderMode=mode, borderValue=fillcolor) 
Example #11
Source File: utils.py    From PartiallyReversibleUnet with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def dense_image_warp(im, dx, dy, interp=cv2.INTER_LINEAR):

        map_x, map_y = deformation_to_transformation(dx, dy)

        do_optimization = (interp == cv2.INTER_LINEAR)
        # The following command converts the maps to compact fixed point representation
        # this leads to a ~20% increase in speed but could lead to accuracy losses
        # Can be uncommented
        if do_optimization:
            map_x, map_y = cv2.convertMaps(map_x, map_y, dstmap1type=cv2.CV_16SC2)

        remapped = cv2.remap(im, map_x, map_y, interpolation=interp, borderMode=cv2.BORDER_REFLECT) #borderValue=float(np.min(im)))
        if im.ndim > remapped.ndim:
            remapped = np.expand_dims(remapped, im.ndim)
        return remapped 
Example #12
Source File: image_ops.py    From vel with MIT License 5 votes vote down vote up
def pad(img, pad, mode=cv2.BORDER_REFLECT):
    return cv2.copyMakeBorder(img, pad, pad, pad, pad, mode) 
Example #13
Source File: image_ops.py    From vel with MIT License 5 votes vote down vote up
def mode_to_cv2(mode='constant'):
    if mode == 'constant':
        return cv2.BORDER_CONSTANT
    if mode == 'reflect':
        return cv2.BORDER_REFLECT

    raise ValueError(f"Invalid mode {mode}") 
Example #14
Source File: random_rotate.py    From vel with MIT License 5 votes vote down vote up
def __call__(self, x_data):
        if random.random() < self.p:
            random_degree = random.uniform(-self.deg, self.deg)
            return data.rotate_img(x_data, random_degree, mode=cv2.BORDER_REFLECT)
        else:
            # No, don't do it
            return x_data 
Example #15
Source File: test_box_filter.py    From guided-filter with MIT License 5 votes vote down vote up
def test_box_filter_reflect(self):
        I = np.array(range(1, 50)).reshape(7, 7).astype(np.float32)
        r = 2
        ret1 = cv.smooth.box_filter(I, r, normalize=True, border_type='reflect')
        ret2 = cv2.blur(I, (5,5), borderType=cv2.BORDER_REFLECT)
        self.assertTrue(np.array_equal(ret1, ret2)) 
Example #16
Source File: mosse.py    From PyCV-time with MIT License 5 votes vote down vote up
def rnd_warp(a):
    h, w = a.shape[:2]
    T = np.zeros((2, 3))
    coef = 0.2
    ang = (np.random.rand()-0.5)*coef
    c, s = np.cos(ang), np.sin(ang)
    T[:2, :2] = [[c,-s], [s, c]]
    T[:2, :2] += (np.random.rand(2, 2) - 0.5)*coef
    c = (w/2, h/2)
    T[:,2] = c - np.dot(T[:2, :2], c)
    return cv2.warpAffine(a, T, (w, h), borderMode = cv2.BORDER_REFLECT) 
Example #17
Source File: cloud_mask.py    From eo-learn with MIT License 5 votes vote down vote up
def _red_ssim(self, data_x, data_y, valid_mask, mu1, mu2, sigma1_2, sigma2_2, const1=1e-6, const2=1e-5):
        """Slightly reduced (pre-computed) SSIM computation."""

        # Increase precision and mask invalid regions
        valid_mask = valid_mask.astype(np.float64)
        data_x = data_x.astype(np.float64) * valid_mask
        data_y = data_y.astype(np.float64) * valid_mask

        # Init
        mu1_2 = mu1 * mu1
        mu2_2 = mu2 * mu2
        mu1_mu2 = mu1 * mu2

        sigma12 = cv2.GaussianBlur(
            (data_x*data_y).astype(np.float64), (0, 0), self.sigma, borderType=cv2.BORDER_REFLECT)
        sigma12 -= mu1_mu2

        # Formula
        tmp1 = 2. * mu1_mu2 + const1
        tmp2 = 2. * sigma12 + const2
        num = tmp1 * tmp2

        tmp1 = mu1_2 + mu2_2 + const1
        tmp2 = sigma1_2 + sigma2_2 + const2
        den = tmp1 * tmp2

        return np.divide(num, den) 
Example #18
Source File: cloud_mask.py    From eo-learn with MIT License 5 votes vote down vote up
def _win_avg(self, data):
        """Spatial window average."""

        return cv2.GaussianBlur(data.astype(np.float64), (0, 0), self.sigma, borderType=cv2.BORDER_REFLECT) 
Example #19
Source File: cloud_mask.py    From eo-learn with MIT License 5 votes vote down vote up
def _win_prevar(self, data):
        """Incomplete spatial window variance."""

        return cv2.GaussianBlur((data*data).astype(np.float64), (0, 0), self.sigma, borderType=cv2.BORDER_REFLECT) 
Example #20
Source File: cloud_mask.py    From eo-learn with MIT License 5 votes vote down vote up
def _average(self, data):
        return cv2.filter2D(data.astype(np.float64), -1, self.avg_kernel, borderType=cv2.BORDER_REFLECT) 
Example #21
Source File: augmenters.py    From netharn with Apache License 2.0 5 votes vote down vote up
def __init__(self, target_size, fill_color=127, mode='letterbox',
                 border='constant', random_state=None):
        super(Resize, self).__init__(random_state=random_state)
        self.target_size = None if target_size is None else np.array(target_size)
        self.mode = mode

        import imgaug.parameters as iap
        if fill_color == imgaug.ALL:
            self.fill_color = iap.Uniform(0, 255)
        else:
            self.fill_color = iap.handle_continuous_param(
                fill_color, "fill_color", value_range=None,
                tuple_to_uniform=True, list_to_choice=True)

        self._cv2_border_type_map = {
            'constant': cv2.BORDER_CONSTANT,
            'edge': cv2.BORDER_REPLICATE,
            'linear_ramp': None,
            'maximum': None,
            'mean': None,
            'median': None,
            'minimum': None,
            'reflect': cv2.BORDER_REFLECT_101,
            'symmetric': cv2.BORDER_REFLECT,
            'wrap': cv2.BORDER_WRAP,
            cv2.BORDER_CONSTANT: cv2.BORDER_CONSTANT,
            cv2.BORDER_REPLICATE: cv2.BORDER_REPLICATE,
            cv2.BORDER_REFLECT_101: cv2.BORDER_REFLECT_101,
            cv2.BORDER_REFLECT: cv2.BORDER_REFLECT
        }
        if isinstance(border, six.string_types):
            if border == imgaug.ALL:
                border = [k for k, v in self._cv2_border_type_map.items()
                          if v is not None and isinstance(k, six.string_types)]
            else:
                border = [border]
        if isinstance(border, (list, tuple)):
            from imgaug.parameters import Choice
            border = Choice(border)
        self.border = border
        assert self.mode == 'letterbox', 'thats all folks' 
Example #22
Source File: utils.py    From PHiSeg-code with Apache License 2.0 5 votes vote down vote up
def dense_image_warp(im, dx, dy, interp=cv2.INTER_LINEAR, do_optimisation=True):

        map_x, map_y = deformation_to_transformation(dx, dy)

        # The following command converts the maps to compact fixed point representation
        # this leads to a ~20% increase in speed but could lead to accuracy losses
        # Can be uncommented
        if do_optimisation:
            map_x, map_y = cv2.convertMaps(map_x, map_y, dstmap1type=cv2.CV_16SC2)
        return cv2.remap(im, map_x, map_y, interpolation=interp, borderMode=cv2.BORDER_REFLECT) #borderValue=float(np.min(im))) 
Example #23
Source File: abstract_dataset.py    From kaggle_carvana_segmentation with MIT License 5 votes vote down vote up
def reflect_border(self, image, b=12):
        return cv2.copyMakeBorder(image, b, b, b, b, cv2.BORDER_REFLECT) 
Example #24
Source File: vidstab_utils.py    From python_video_stab with MIT License 5 votes vote down vote up
def border_frame(frame, border_size, border_type):
    """Convenience wrapper of cv2.copyMakeBorder for how vidstab applies borders

    :param frame: frame to apply border to
    :param border_size: int border size in number of pixels
    :param border_type: one of the following ['black', 'reflect', 'replicate']
    :return: bordered version of frame with alpha layer for frame overlay options
    """
    border_modes = {'black': cv2.BORDER_CONSTANT,
                    'reflect': cv2.BORDER_REFLECT,
                    'replicate': cv2.BORDER_REPLICATE}
    border_mode = border_modes[border_type]

    bordered_frame_image = cv2.copyMakeBorder(frame.image,
                                              top=border_size,
                                              bottom=border_size,
                                              left=border_size,
                                              right=border_size,
                                              borderType=border_mode,
                                              value=[0, 0, 0])

    bordered_frame = Frame(bordered_frame_image, color_format=frame.color_format)

    alpha_bordered_frame = bordered_frame.bgra_image
    alpha_bordered_frame[:, :, 3] = 0
    h, w = frame.image.shape[:2]
    alpha_bordered_frame[border_size:border_size + h, border_size:border_size + w, 3] = 255

    return alpha_bordered_frame, border_mode 
Example #25
Source File: augmentations.py    From PytorchToCaffe with MIT License 5 votes vote down vote up
def __call__(self, image, *args):
        size=self.size
        if self.type=='constant':
            image = cv2.copyMakeBorder(image, size, size, size, size, cv2.BORDER_CONSTANT, value=self.constant_color)
        elif self.type=='reflect':
            image = cv2.copyMakeBorder(image, size, size, size, size, cv2.BORDER_REFLECT)
        elif self.type=='replicate':
            image = cv2.copyMakeBorder(image, size, size, size, size, cv2.BORDER_REPLICATE)

        if len(args):
            return (image, *args)
        else:
            return image 
Example #26
Source File: augmentations.py    From nn_tools with MIT License 5 votes vote down vote up
def __call__(self, image, *args):
        size=self.size
        if self.type=='constant':
            image = cv2.copyMakeBorder(image, size, size, size, size, cv2.BORDER_CONSTANT, value=self.constant_color)
        elif self.type=='reflect':
            image = cv2.copyMakeBorder(image, size, size, size, size, cv2.BORDER_REFLECT)
        elif self.type=='replicate':
            image = cv2.copyMakeBorder(image, size, size, size, size, cv2.BORDER_REPLICATE)

        if len(args):
            return (image, *args)
        else:
            return image 
Example #27
Source File: a00_augmentation_functions.py    From Urban3d with MIT License 5 votes vote down vote up
def random_rotate_with_mask(image, mask, max_angle):
    cols = image.shape[1]
    rows = image.shape[0]

    angle = random.uniform(-max_angle, max_angle)
    M = cv2.getRotationMatrix2D((cols // 2, rows // 2), angle, 1)
    dst = cv2.warpAffine(image, M, (cols, rows), borderMode=cv2.BORDER_REFLECT)
    dst_msk = cv2.warpAffine(mask, M, (cols, rows), borderMode=cv2.BORDER_REFLECT)
    return dst, dst_msk 
Example #28
Source File: BaseStructuredForests.py    From StructuredForests with BSD 2-Clause "Simplified" License 5 votes vote down vote up
def get_features(self, src, smp_loc):
        bottom, right = (4 - src.shape[0] % 4) % 4, (4 - src.shape[1] % 4) % 4
        src = cv2.copyMakeBorder(src, 0, bottom, 0, right,
                                 borderType=cv2.BORDER_REFLECT)

        reg_ch, ss_ch = self.get_shrunk_channels(src)
        smp_loc = self.get_shrunk_loc(smp_loc)

        reg_ftr = self.get_reg_ftr(reg_ch, smp_loc)
        ss_ftr = self.get_ss_ftr(ss_ch, smp_loc)

        return reg_ftr, ss_ftr 
Example #29
Source File: mosse.py    From open-vot with MIT License 5 votes vote down vote up
def _random_warp(self, img):
        h, w = img.shape[:2]
        T = np.zeros((2, 3))
        coef = 0.2
        ang = (np.random.rand() - 0.5) * coef
        c, s = np.cos(ang), np.sin(ang)
        T[:2, :2] = [[c, -s], [s, c]]
        T[:2, :2] += (np.random.rand(2, 2) - 0.5) * coef
        c = (w / 2, h / 2)
        T[:, 2] = c - np.dot(T[:2, :2], c)

        return cv2.warpAffine(img, T, (w, h), borderMode=cv2.BORDER_REFLECT) 
Example #30
Source File: opencv_functional.py    From deep-smoke-machine with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
def affine(img, angle, translate, scale, shear, interpolation=cv2.INTER_LINEAR, mode=cv2.BORDER_CONSTANT, fillcolor=0):
    """Apply affine transformation on the image keeping image center invariant
    Args:
        img (numpy ndarray): numpy ndarray to be transformed.
        angle (float or int): rotation angle in degrees between -180 and 180, clockwise direction.
        translate (list or tuple of integers): horizontal and vertical translations (post-rotation translation)
        scale (float): overall scale
        shear (float): shear angle value in degrees between -180 to 180, clockwise direction.
        interpolation (``cv2.INTER_NEAREST` or ``cv2.INTER_LINEAR`` or ``cv2.INTER_AREA``, ``cv2.INTER_CUBIC``):
            An optional resampling filter.
            See `filters`_ for more information.
            If omitted, it is set to ``cv2.INTER_LINEAR``, for bilinear interpolation.
        mode (``cv2.BORDER_CONSTANT`` or ``cv2.BORDER_REPLICATE`` or ``cv2.BORDER_REFLECT`` or ``cv2.BORDER_REFLECT_101``)
            Method for filling in border regions.
            Defaults to cv2.BORDER_CONSTANT, meaning areas outside the image are filled with a value (val, default 0)
        val (int): Optional fill color for the area outside the transform in the output image. Default: 0
    """
    if not _is_numpy_image(img):
        raise TypeError('img should be numpy Image. Got {}'.format(type(img)))

    assert isinstance(translate, (tuple, list)) and len(translate) == 2, \
        "Argument translate should be a list or tuple of length 2"

    assert scale > 0.0, "Argument scale should be positive"

    output_size = img.shape[0:2]
    center = (img.shape[1] * 0.5 + 0.5, img.shape[0] * 0.5 + 0.5)
    matrix = _get_affine_matrix(center, angle, translate, scale, shear)

    if img.shape[2]==1:
        return cv2.warpAffine(img, matrix, output_size[::-1],interpolation, borderMode=mode, borderValue=fillcolor)[:,:,np.newaxis]
    else:
        return cv2.warpAffine(img, matrix, output_size[::-1],interpolation, borderMode=mode, borderValue=fillcolor)