mindarmour.natural_robustness.transform.image.blur 源代码

# Copyright 2022 Huawei Technologies Co., Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Image Blur
"""

import numpy as np
import cv2

from mindarmour.natural_robustness.transform.image.natural_perturb import _NaturalPerturb
from mindarmour.utils._check_param import check_param_multi_types, check_int_positive, check_param_type
from mindarmour.utils.logger import LogUtil

LOGGER = LogUtil.get_instance()
TAG = 'Image Blur'


[文档]class GaussianBlur(_NaturalPerturb): """ Blurs the image using Gaussian blur filter. Args: ksize (int): Size of gaussian kernel, this value must be non-negnative. Default: ``2``. auto_param (bool): Auto selected parameters. Selected parameters will preserve semantics of image. Default: ``False``. Examples: >>> import cv2 >>> img = cv2.imread('1.png') >>> img = np.array(img) >>> ksize = 5 >>> trans = GaussianBlur(ksize) >>> dst = trans(img) """ def __init__(self, ksize=2, auto_param=False): super(GaussianBlur, self).__init__() ksize = check_int_positive('ksize', ksize) if auto_param: ksize = 2 * np.random.randint(0, 5) + 1 else: ksize = 2 * ksize + 1 self.ksize = (ksize, ksize) def __call__(self, image): """ Transform the image. Args: image (numpy.ndarray): Original image to be transformed. Returns: numpy.ndarray, transformed image. """ ori_dtype = image.dtype _, chw, normalized, gray3dim, image = self._check(image) new_img = cv2.GaussianBlur(image, self.ksize, 0) new_img = self._original_format(new_img, chw, normalized, gray3dim) return new_img.astype(ori_dtype)
[文档]class MotionBlur(_NaturalPerturb): """ Motion blur for a given image. Args: degree (int): Degree of blur. This value must be positive. Suggested value range in [1, 15]. Default: ``5``. angle (union[float, int]): Direction of motion blur. Angle=0 means up and down motion blur. Angle is counterclockwise. Default: ``45``. auto_param (bool): Auto selected parameters. Selected parameters will preserve semantics of image. Default: ``False``. Examples: >>> import cv2 >>> img = cv2.imread('1.png') >>> img = np.array(img) >>> angle = 0 >>> degree = 5 >>> trans = MotionBlur(degree=degree, angle=angle) >>> new_img = trans(img) """ def __init__(self, degree=5, angle=45, auto_param=False): super(MotionBlur, self).__init__() self.degree = check_int_positive('degree', degree) self.degree = check_param_multi_types('degree', degree, [float, int]) auto_param = check_param_type('auto_param', auto_param, bool) if auto_param: self.degree = np.random.randint(1, 5) self.angle = np.random.uniform(0, 360) else: self.angle = angle - 45 def __call__(self, image): """ Motion blur for a given image. Args: image (numpy.ndarray): Original image. Returns: numpy.ndarray, image after motion blur. """ ori_dtype = image.dtype _, chw, normalized, gray3dim, image = self._check(image) matrix = cv2.getRotationMatrix2D((self.degree / 2, self.degree / 2), self.angle, 1) motion_blur_kernel = np.diag(np.ones(self.degree)) motion_blur_kernel = cv2.warpAffine(motion_blur_kernel, matrix, (self.degree, self.degree)) motion_blur_kernel = motion_blur_kernel / self.degree blurred = cv2.filter2D(image, -1, motion_blur_kernel) # convert to uint8 cv2.normalize(blurred, blurred, 0, 255, cv2.NORM_MINMAX) blurred = self._original_format(blurred, chw, normalized, gray3dim) return blurred.astype(ori_dtype)
[文档]class GradientBlur(_NaturalPerturb): """ Gradient blur. Args: point (union[tuple, list]): 2D coordinate of the Blur center point. kernel_num (int): Number of blur kernels. Suggested value range in [1, 8]. Default: ``3``. center (bool): Blurred or clear at the center of a specified point. auto_param (bool): Auto selected parameters. Selected parameters will preserve semantics of image. Default: ``False``. Examples: >>> import cv2 >>> img = cv2.imread('xx.png') >>> img = np.array(img) >>> number = 5 >>> h, w = img.shape[:2] >>> point = (int(h / 5), int(w / 5)) >>> center = True >>> trans = GradientBlur(point, number, center) >>> new_img = trans(img) """ def __init__(self, point, kernel_num=3, center=True, auto_param=False): super(GradientBlur).__init__() point = check_param_multi_types('point', point, [list, tuple]) self.auto_param = check_param_type('auto_param', auto_param, bool) self.point = tuple(point) self.kernel_num = check_int_positive('kernel_num', kernel_num) self.center = check_param_type('center', center, bool) def _auto_param(self, h, w): self.point = (int(np.random.uniform(0, h)), int(np.random.uniform(0, w))) self.kernel_num = np.random.randint(1, 6) self.center = np.random.choice([True, False]) def __call__(self, image): """ Args: image (numpy.ndarray): Original image. Returns: numpy.ndarray, gradient blurred image. """ ori_dtype = image.dtype _, chw, normalized, gray3dim, image = self._check(image) w, h = image.shape[:2] if self.auto_param: self._auto_param(h, w) mask = np.zeros(image.shape, dtype=np.uint8) masks = [] radius = max(w - self.point[0], self.point[0], h - self.point[1], self.point[1]) radius = int(radius / self.kernel_num) for i in range(self.kernel_num): circle = cv2.circle(mask.copy(), self.point, radius * (1 + i), (1, 1, 1), -1) masks.append(circle) blurs = [] for i in range(3, 3 + 2 * self.kernel_num, 2): ksize = (i, i) blur = cv2.GaussianBlur(image, ksize, 0) blurs.append(blur) dst = image.copy() if self.center: for i in range(self.kernel_num): dst = masks[i] * dst + (1 - masks[i]) * blurs[i] else: for i in range(self.kernel_num - 1, -1, -1): dst = masks[i] * blurs[self.kernel_num - 1 - i] + (1 - masks[i]) * dst dst = self._original_format(dst, chw, normalized, gray3dim) return dst.astype(ori_dtype)