728x90

albumentations.ai/docs/api_reference/augmentations/transforms/에 있는 API를 이용할 것이다.

 

1. 기하변환 

 

import cv2
import albumentations as A
class Geometry:
    bbox_rot90_isChecked = False
    bbox_rotate_isChecked = False
    keypoint_rot90_isChecked = False
    keypoint_rotate_isChecked = False
    keypoint_scale_isChecked = False
    LongestMaxSize_isChecked = False
    RandomScale_isChecked = False
    Resize_isChecked = False
    SmallestMaxSize_isChecked = False
    RandomRotate90_isChecked = True
    Rotate_isChecked = False
    Perspective_isChecked = False
    ShiftScaleRotate_isChecked = False

    #바운딩박스 90도 (다듬어야함)
    def bbox_rot90(Box, bbox, factor, rows, cols):
        """
        bbox   tuple    A bounding box tuple (x_min, y_min, x_max, y_max).
        factor   int        Number of CCW rotations. Must be in set {0, 1, 2, 3} See np.rot90.
        rows   int        Image rows.
        cols   int        Image cols.
        """
        transform = A.Compose([
            A.bbox_rot90(bbox, factor, rows, cols)
        ],p=1)
        bbox = transform(bbox=Box)['bbox']
        return bbox
    #바운딩박스 회전 (다듬어야함)
    def bbox_rotate(Box, bbox, angle, rows, cols):
        """
        bbox   tuple       A bounding box tuple (x_min, y_min, x_max, y_max).
        factor   int           Number of CCW rotations. Must be in set {0, 1, 2, 3} See np.rot90.
        rows   int           Image rows.
        cols   int           Image cols.
        """
        transform = A.Compose([
            A.bbox_rotate(bbox, angle, rows, cols)
        ],p=1)
        img = transform(image=image)['image']
        return img
    # 키포인트 90도 (다듬어야함)
    def keypoint_rot90(KeyPoint,keypoint, factor, rows, cols, **params):
        """
        keypoint   tuple       A keypoint (x, y, angle, scale).
        factor   int               Number of CCW rotations. Must be in range [0;3] See np.rot90.
        rows   int               Image height.
        cols   int               Image width.
        """
        transform = A.Compose([
            A.keypoint_rot90(keypoint, factor, rows, cols, **params)
        ],p=1)

        img = transform(keypoint=KeyPoint)['keypoint']
        return img
    # 키포인트 회전 (다듬어야함)
    def keypoint_rotate(KeyPoint, keypoint, angle, rows, cols, **params):
        """
        keypoint   tuple           A keypoint (x, y, angle, scale).
        angle      float           Rotation angle.
        rows       int               Image height.
        cols       int               Image width.
        """
        transform = A.Compose([
            A.keypoint_rotate(keypoint, angle, rows, cols, **params)
        ],p=1)

        img = transform(image=image)['image']
        return img
    # 키포인트 스케일링 (다듬어야함)
    def keypoint_scale(KeyPoint ,keypoint, scale_x, scale_y):
        """
        keypoint   tuple       A keypoint (x, y, angle, scale).
        scale_x       int           Scale coefficient x-axis.
        scale_y       int           Scale coefficient y-axis.
        """
        transform = A.Compose([
            A.keypoint_scale(keypoint, scale_x, scale_y)
        ],p=1)

        img = transform(image=image)['image']
        return img
    #초기 이미지의 가로 세로 비율을 유지하면서 최대면이 max_size와 같도록 이미지 크기를 조정합니다
    def LongestMaxSize (image, max_size=1024, interpolation=1, always_apply=False, p=1):
        """
        max_size	    int	              변환 후 이미지의 최대 크기.
        interpolation	OpenCV flag	      보간 방법. 기본값 : cv2.INTER_LINEAR.
        p	            float	          변환을 적용 할 확률. 기본값 : 1.
        """
        transform = A.Compose([
            A.LongestMaxSize(max_size, interpolation, always_apply, p)
        ],p=1)

        img = transform(image=image)['image']
        return img
    #입력 크기를 임의로 조정합니다. 출력 이미지 크기가 입력 이미지 크기와 다릅니다.
    def RandomScale(image, scale_limit=1.2,interpolation=1, always_apply=False, p=1):
        """
        scale_limit	    [float, float] or float	        배율 범위. scale_limit가 단일 부동 소수점 값이면 범위는 (1-scale_limit, 1 + scale_limit)입니다. 기본값 : (0.9, 1.1).
        interpolation	OpenCV flag	                    보간 알고리즘을 지정하는 데 사용되는 플래그입니다. cv2.INTER_NEAREST, cv2.INTER_LINEAR, cv2.INTER_CUBIC, cv2.INTER_AREA, cv2.INTER_LANCZOS4 중 하나 여야합니다. 기본값 : cv2.INTER_LINEAR.
        p	            float	                        변환을 적용 할 확률. 기본값 : 0.5.
        """
        transform = A.Compose([
            A.RandomScale(scale_limit, interpolation,always_apply,p)
        ],p=1)
        img = transform(image=image)['image']
        return img
    #입력 크기를 주어진 높이와 너비로 조정합니다.
    def Resize (image, height, width, interpolation=1, always_apply=False, p=1):
        """
        height	        int	          원하는 출력 높이.
        width	        int	          원하는 출력 너비.
        interpolation	OpenCV flag	  보간 알고리즘을 지정하는 데 사용되는 플래그입니다. cv2.INTER_NEAREST, cv2.INTER_LINEAR, cv2.INTER_CUBIC, cv2.INTER_AREA, cv2.INTER_LANCZOS4 중 하나 여야합니다. 기본값 : cv2.INTER_LINEAR.
        p	            float	      변환을 적용 할 확률. 기본값 : 1.
        """
        transform = A.Compose([
            A.Resize(height, width, interpolation=1, always_apply=False, p=1)
        ],p=1)

        img = transform(image=image)['image']
        return img
    #초기 이미지의 종횡비를 유지하면서 최소면이 max_size와 같도록 이미지 크기를 조정합니다.
    def SmallestMaxSize (image, max_size=1024, interpolation=1, always_apply=False, p=1):
        """
        max_size	    int	            변환 후 이미지의 가장 작은면의 최대 크기.
        interpolation	OpenCV flag	    보간 방법. 기본값 : cv2.INTER_LINEAR.
        p	            float	        변환을 적용 할 확률. 기본값 : 1.
        """
        transform = A.Compose([
            A.SmallestMaxSize(max_size, interpolation, always_apply, p)
        ],p=1)

        img = transform(image=image)['image']
        return img
    #입력을 0도 이상 90도 회전합니다.(손좀 봐야 할 것 같다)
    def RandomRotate90(image, p=1):
        """
        p	float	  변환을 적용 할 확률. 기본값 : 1
        """
        transform = A.Compose([
            A.RandomRotate90(p)
        ],p=1)

        img = transform(image=image)['image']
        return img
    #균등 분포에서 무작위로 선택한 각도로 입력을 회전합니다.
    def Rotate(image, limit=90, interpolation=1, border_mode=4, value=None, mask_value=None, always_apply=False, p=1):
        """
        limit	        [int, int] or int	    임의의 각도가 선택되는 범위. limit가 single int이면 각도는 (-limit, limit)에서 선택됩니다. 기본값 : (-90, 90)
        interpolation	OpenCV flag	    보간 알고리즘을 지정하는 데 사용되는 플래그입니다. cv2.INTER_NEAREST, cv2.INTER_LINEAR, cv2.INTER_CUBIC, cv2.INTER_AREA, cv2.INTER_LANCZOS4 중 하나 여야합니다. 기본값 : cv2.INTER_LINEAR.
        border_mode 	OpenCV flag	    픽셀 외삽 방법을 지정하는 데 사용되는 플래그입니다. cv2.BORDER_CONSTANT, cv2.BORDER_REPLICATE, cv2.BORDER_REFLECT, cv2.BORDER_WRAP, cv2.BORDER_REFLECT_101 중 하나 여야합니다. 기본값 : cv2.BORDER_REFLECT_101
        value	        int, float, list of ints, list of float	    border_mode가 cv2.BORDER_CONSTANT 인 경우 패딩 값입니다.
        mask_value  	int, float, list of ints, list of float	    border_mode가 cv2 인 경우 패딩 값 .BORDER_CONSTANT가 마스크에 적용됩니다.
        p	           float	    변환을 적용 할 확률. 기본값 : 1.
        """
        transform = A.Compose([
            A.Rotate (limit, interpolation, border_mode, value, mask_value, always_apply, p)
        ],p=1)

        img = transform(image=image)['image']
        return img
    #입력에 대해 임의의 4 점 투시 변환을 수행합니다.
    def Perspective (image, scale=(0.05, 0.1), keep_size=True, pad_mode=0, pad_val=0, mask_pad_val=0, fit_output=False, interpolation=1, always_apply=False, p=1):
        """
        scale	   float or [float, float]	
        정규 분포의 표준 편차입니다. 이것은 전체 이미지의 모서리에서 부분 이미지 모서리의 임의 거리를 샘플링하는 데 사용됩니다. scale이 단일 float 값이면 범위는 (0, scale)이됩니다. 기본값 : (0.05, 0.1).

        keep_size	bool	
        원근 변환을 적용한 후 이미지의 크기를 원래 크기로 다시 조정할지 여부입니다. False로 설정하면 결과 이미지가 다른 모양을 갖게 될 수 있으며 배열이 아닌 항상 목록이됩니다. 기본값 : True

        pad_mode	OpenCV flag	
        OpenCV 테두리 모드.

        pad_val	int, float, list of int, list of float	
        border_mode가 cv2.BORDER_CONSTANT 인 경우 패딩 값입니다. 기본값 : 0

        mask_pad_val	int, float, list of int, list of float	
        border_mode가 cv2.BORDER_CONSTANT 인 경우 마스크의 패딩 값입니다. 기본값 : 0

        fit_output	bool	
        True이면 원근 변환 후에도 전체 이미지를 캡처하도록 이미지 평면 크기와 위치가 조정됩니다. (keep_size가 True로 설정된 경우 이미지 크기 조정이 뒤 따릅니다.) 그렇지 않으면 변환 된 이미지의 일부가 이미지 평면 외부에있을 수 있습니다. 이 설정은 매우 큰 이미지로 이어질 수 있으므로 큰 배율 값을 사용하는 경우 True로 설정하면 안됩니다. 기본값 : False

        p	float	
        변환을 적용 할 확률. 기본값 : 1
        """
        transform = A.Compose([
            A.Perspective (scale, keep_size, pad_mode, pad_val, mask_pad_val, fit_output, interpolation, always_apply, p)
        ],p=1)

        img = transform(image=image)['image']
        return img
    #아핀 변환을 무작위로 적용 : 입력을 변환, 크기 조정 및 회전합니다. 
    def ShiftScaleRotate (image, shift_limit=0.0625, scale_limit=0.1, rotate_limit=45, interpolation=1, border_mode=4, value=None, mask_value=None, shift_limit_x=None, shift_limit_y=None, always_apply=False, p=1):
        """
        shift_limit	[float, float] or float	
        높이와 너비 모두에 대한 이동 계수 범위. shift_limit가 단일 부동 소수점 값이면 범위는 (-shift_limit, shift_limit)입니다. 하한 및 상한의 절대 값은 [0, 1] 범위에 있어야합니다. 기본값 : (-0.0625, 0.0625).

        scale_limit	[float, float] or float	
        배율 범위. scale_limit가 단일 부동 소수점 값이면 범위는 (-scale_limit, scale_limit)입니다. 기본값 : (-0.1, 0.1).

        rotate_limit	[int, int] or int	
        회전 범위. rotate_limit가 단일 int 값이면 범위는 (-rotate_limit, rotate_limit)입니다. 기본값 : (-45, 45).

        interpolation	OpenCV flag	
        보간 알고리즘을 지정하는 데 사용되는 플래그입니다. cv2.INTER_NEAREST, cv2.INTER_LINEAR, cv2.INTER_CUBIC, cv2.INTER_AREA, cv2.INTER_LANCZOS4 중 하나 여야합니다. 기본값 : cv2.INTER_LINEAR.

        border_mode	OpenCV flag	
        픽셀 외삽 방법을 지정하는 데 사용되는 플래그입니다. cv2.BORDER_CONSTANT, cv2.BORDER_REPLICATE, cv2.BORDER_REFLECT, cv2.BORDER_WRAP, cv2.BORDER_REFLECT_101 중 하나 여야합니다. 기본값 : cv2.BORDER_REFLECT_101

        value	int, float, list of int, list of float	
        border_mode가 cv2.BORDER_CONSTANT 인 경우 패딩 값입니다.

        mask_value	int, float, list of int, list of float	
        border_mode가 cv2 인 경우 패딩 값 .BORDER_CONSTANT가 마스크에 적용됩니다.

        shift_limit_x	[float, float] or float	
        폭에 대한 이동 계수 범위. 설정된 경우 shift_limit 대신이 값이 폭 이동에 사용됩니다. shift_limit_x가 단일 부동 값이면 범위는 (-shift_limit_x, shift_limit_x)가됩니다. 하한 및 상한의 절대 값은 [0, 1] 범위에 있어야합니다. 기본값 : 없음.

        shift_limit_y	[float, float] or float	
        높이에 대한 이동 계수 범위. 설정된 경우 shift_limit 대신이 값이 높이 이동에 사용됩니다. shift_limit_y가 단일 부동 소수점 값이면 범위는 (-shift_limit_y, shift_limit_y)입니다. 하한 및 상한의 절대 값은 [0, 1] 범위에 있어야합니다. 기본값 : 없음.

        p	float	
        변환을 적용 할 확률. 기본값 : 1
        """
        transform = A.Compose([
            A.ShiftScaleRotate (shift_limit, scale_limit, rotate_limit,
             interpolation, border_mode, value, mask_value, shift_limit_x, shift_limit_y, always_apply, p)
        ],p=1)

        img = transform(image=image)['image']
        return img

- 먼저 image에 대한 증강만 고려해서 제작하였으므로 bbox나 keypoint는 코드를 손봐야한다.

 

- ㅇㅇㅇㅇ_isChecked는 나중에 GUI 프로그램을 활용해서 체크박스로  증강 기법을 선택해서 사용하기 위해 플래그를 만들어 둔 것이다.

 

- 각 증강 기법별로 API에 있는 매개변수의 Default값과 image 을 입력으로 받는 함수를 작성하였고,

  매개변수별 설명은 주석으로 달아두었다.

 

- 각 함수마다 입력받은 매개변수와 image를 이용하여  변환기능을 제공하는 Compose 객체를 생성하여 증강처리를 한다.

 

- 증강처리가 된 이미지는 다시 return하여 다음 증강, 및 저장에 쓰이게 된다.

 

2. Blur

import cv2
import albumentations as A
class Blur:
    GaussianBlur_isChecked = True
    GlassBlur_isChecked = True
    
    def GaussianBlur(image, blur_limit=(3,7), sigma_limit=0, always_apply=False, p=1):
        """
        blur_limit	int, [int, int]	
        입력 이미지를 흐리게하기위한 최대 가우스 커널 크기. 0 또는 홀수 여야하며 [0, inf) 범위 내에 있어야합니다. 0으로 설정하면 시그마에서로 계산됩니다 round(sigma * (3 if img.dtype == np.uint8 else 4) * 2 + 1) + 1. 단일 값 blur_limit을 설정하면 범위 (0, blur_limit)가됩니다. 기본값 : (3,7).

        sigma_limit	float, [float, float]	
        가우스 커널 표준 편차. 범위 [0, inf)에서 더 커야합니다. 설정된 경우 단일 값 sigma_limit은 범위 (0, sigma_limit)에 있습니다. 0으로 설정하면 시그마는로 계산됩니다 sigma = 0.3*((ksize-1)*0.5 - 1) + 0.8. 기본값 : 0.

        p	float	
        변환을 적용 할 확률. 기본값 : 1.
        """
        transform = A.Compose([
            A.GaussianBlur (blur_limit, sigma_limit, always_apply, p)
        ],p=1)
        img = transform(image=image)['image']
        return img

    def GlassBlur (image, sigma=0.7, max_delta=4, iterations=2, always_apply=False, mode='fast', p=1):
        """
        sigma	float	
        가우시안 커널의 표준 편차 기본값=0.7

        max_delta	int	
        스왑되는 픽셀 사이의 최대 거리.

        iterations	int	
        반복 횟수. 범위 [1, inf)에 있어야합니다. 기본값 : (2).

        mode	str	
        계산 모드 : 빠르거나 정확합니다. 기본값 : "빠름".

        p	float	
        변환을 적용 할 확률. 기본값 : 1.
        """
        transform = A.Compose([
            A.GlassBlur (sigma, max_delta, iterations, always_apply, mode, p)
        ],p=1)
        img = transform(image=image)['image']
        return img

- 카테고리와 기법만 다를 뿐 Geometry와 똑같이 구현했다 밑에 적힐 다른 클래스들도  마찬가지로 설명은 생략한다.

 

 

3. Contrast

import cv2
import albumentations as A

class Contrast:
    RandomBrightness_isChecked = True
    RandomContrast_isChecked = True
    RandomBrightnessContrast_isChecked = True
        
    #입력 이미지의 밝기를 임의로 변경합니다.
    def RandomBrightness (image, limit=0.2, always_apply=False, p=1):
        """
        limit	[float, float] or float	
        밝기 변경을위한 계수 범위. 한계가 단일 부동 인 경우 범위는 (-limit, limit)입니다. 기본값 : (-0.7,0.7).

        p	float	
        변환을 적용 할 확률. 기본값 : 1
        """
        transform = A.Compose([
            A.RandomBrightness (limit, always_apply, p)
        ],p=1)
        img = transform(image=image)['image']
        return img

    
    #입력 이미지의 대비를 임의로 변경합니다.
    def RandomContrast (image, limit=0.2, always_apply=False, p=1):
        """
        limit	[float, float] or float	
        대비 변경을위한 요인 범위. 한계가 단일 부동 인 경우 범위는 (-limit, limit)입니다. 기본값 : (-0.7, 0.7).

        p	float	
        변환을 적용 할 확률. 기본값 : 0.5.
        """
        transform = A.Compose([
            A.RandomContrast (limit, always_apply, p)
        ],p=1)
        img = transform(image=image)['image']
        return img

    #입력 이미지의 밝기와 대비를 임의로 변경합니다.
    def RandomBrightnessContrast(image, brightness_limit=0.2, contrast_limit=0.2, brightness_by_max=True, always_apply=False, p=1):
        """
        brightness_limit	[float, float] or float	
        밝기 변경을위한 계수 범위. 한계가 단일 부동 인 경우 범위는 (-limit, limit)입니다. 기본값 : (-0.2, 0.2).

        contrast_limit	[float, float] or float	
        대비 변경을위한 요인 범위. 한계가 단일 부동 인 경우 범위는 (-limit, limit)입니다. 기본값 : (-0.2, 0.2).

        brightness_by_max	Boolean	
        True면 이미지 dtype 최대로 대비를 조정하고 그렇지 않으면 이미지 평균으로 대비를 조정합니다.

        p	float	
        변환을 적용 할 확률. 기본값 : 1.
        """
        transform = A.Compose([
            A.RandomBrightnessContrast(brightness_limit, contrast_limit, brightness_by_max, always_apply, p)
        ],p=1)
        img = transform(image=image)['image']
        return img

 

4. Color

import cv2
import albumentations as A

class Color:

    HueSaturationValue_isChecked = False
    RGBShift_isChecked = True

    #입력 이미지의 색조, 채도 및 값을 임의로 변경합니다.
    def HueSaturationValue (image, hue_shift_limit=30, sat_shift_limit=40, val_shift_limit=50, always_apply=False, p=1):
        """
       hue_shift_limit	[int, int] or int	
        색조 변경 범위. hue_shift_limit가 단일 int이면 범위는 (-hue_shift_limit, hue_shift_limit)입니다. 기본값 : (-20, 20).

        sat_shift_limit	[int, int] or int	
        채도 변경 범위. sat_shift_limit가 단일 정수이면 범위는 (-sat_shift_limit, sat_shift_limit)입니다. 기본값 : (-30, 30).

        val_shift_limit	[int, int] or int	
        값 변경 범위. val_shift_limit가 단일 정수이면 범위는 (-val_shift_limit, val_shift_limit)입니다. 기본값 : (-20, 20).

        p	float	
        변환을 적용 할 확률. 기본값 : 1
        """
        transform = A.Compose([
            A.HueSaturationValue (hue_shift_limit, sat_shift_limit, val_shift_limit, always_apply, p)
        ],p=1)
        img = transform(image=image)['image']
        return img
        
    #입력 RGB 이미지의 각 채널에 대한 값을 임의로 이동합니다.
    def RGBShift (image, r_shift_limit=20, g_shift_limit=20, b_shift_limit=20, always_apply=False, p=1):
        """
        r_shift_limit	[int, int] or int	
        적색 채널의 값을 변경하기위한 범위. r_shift_limit가 단일 int이면 범위는 (-r_shift_limit, r_shift_limit)입니다. 기본값 : (-20, 20).

        g_shift_limit	[int, int] or int	
        녹색 채널의 값을 변경하기위한 범위. g_shift_limit가 단일 int이면 범위는 (-g_shift_limit, g_shift_limit)입니다. 기본값 : (-20, 20).

        b_shift_limit	[int, int] or int	
        파란색 채널의 값을 변경하는 범위입니다. b_shift_limit가 단일 int이면 범위는 (-b_shift_limit, b_shift_limit)입니다. 기본값 : (-20, 20).

        p	float	
        변환을 적용 할 확률. 기본값 : 1
        """
        transform = A.Compose([
            A.RGBShift (r_shift_limit, g_shift_limit, b_shift_limit, always_apply, p)
        ],p=1)
        img = transform(image=image)['image']
        return img

 

5. ImageCorruptlike

import cv2
import albumentations as A

class ImgCorruptlike:
    RandomFog_isChecked = False
    RandomRain_isChecked = False
    RandomShadow_isChecked = False
    RandomSnow_isChecked = False
    RandomSunFlare_isChecked = False

    #이미지의 안개를 시뮬레이션합니다.
    def RandomFog (image, fog_coef_lower=0.3, fog_coef_upper=1, alpha_coef=0.08, always_apply=False, p=1):
        """
        fog_coef_lower	float	
        안개 강도 계수의 하한. [0, 1] 범위에 있어야합니다.

        fog_coef_upper	float	
        안개 강도 계수의 상한. [0, 1] 범위에 있어야합니다.

        alpha_coef	float	
        포그 서클의 투명도. [0, 1] 범위에 있어야합니다.
        """
        transform = A.Compose([
            A.RandomFog (fog_coef_lower, fog_coef_upper, alpha_coef, always_apply, p)
        ],p=1)
        img = transform(image=image)['image']
        return img

    #이미지에 비가 오게 합니다
    def RandomRain (image, slant_lower=-10, slant_upper=10, drop_length=20, drop_width=1, drop_color=(200, 200, 200), blur_value=7, brightness_coefficient=0.7, rain_type=None, always_apply=False, p=1):
        """
        slant_lower		
        범위는 [-20, 20]이어야합니다.

        slant_upper		
        범위는 [-20, 20]이어야합니다.

        drop_length		
        범위는 [0, 100]이어야합니다.

        drop_width		
        범위 [1, 5]에 있어야합니다.

        drop_color	list of (r, g, b	
        비 라인 색상.

        blur_value	int	
        장보기가 흐릿하다

        brightness_coefficient	float	
        비오는 날은 보통 그늘진 날입니다. [0, 1] 범위에 있어야합니다.

        rain_type		
        [없음, "이슬비", "무거움", "torrestial"] 중 하나
        """
        transform = A.Compose([
            A.RandomRain (slant_lower, slant_upper, drop_length, drop_width, drop_color, blur_value, brightness_coefficient, rain_type, always_apply, p)
        ],p=1)
        img = transform(image=image)['image']
        return img
        
    #이미지의 그림자를 시뮬레이션 합니다
    def RandomShadow (image, shadow_roi=(0, 0.5, 1, 1), num_shadows_lower=1, num_shadows_upper=2, shadow_dimension=5, always_apply=False, p=1):
        """
        shadow_roi	float, float, float, float	
        그림자가 나타날 이미지 영역 (x_min, y_min, x_max, y_max). 모든 값은 [0, 1] 범위에 있어야합니다.

        num_shadows_lower	int	
        가능한 그림자 수에 대한 하한. [0, num_shadows_upper] 범위에 있어야합니다 .

        num_shadows_upper	int	
        가능한 그림자 수에 대한 하한. [ num_shadows_lower, inf] 범위에 있어야합니다 .

        shadow_dimension	int	
        그림자 다각형의 가장자리 수
        """
        transform = A.Compose([
            A.RandomShadow (shadow_roi, num_shadows_lower, num_shadows_upper, shadow_dimension, always_apply, p)
        ],p=1)
        img = transform(image=image)['image']
        return img

    # 일부 픽셀값을 수정해 눈이 오는 효과를 냅니다
    def RandomSnow (image, snow_point_lower=0.1, snow_point_upper=0.3, brightness_coeff=2.5, always_apply=False, p=1):
        """
        snow_point_lower	float	
        눈 양의 lower_bond. [0, 1] 범위에 있어야합니다.

        snow_point_upper	float	
        눈 양의 upper_bond. [0, 1] 범위에 있어야합니다.

        brightness_coeff	float	
        숫자가 클수록 이미지에 더 많은 눈이 생깁니다. > = 0이어야합니다.
        """
        transform = A.Compose([
            A.RandomSnow (snow_point_lower, snow_point_upper, brightness_coeff, always_apply, p)
        ],p=1)
        img = transform(image=image)['image']
        return img
    
    #SunFlare 기능을 추가합니다
    def RandomSunFlare (image, flare_roi=(0, 0, 1, 0.5), angle_lower=0, angle_upper=1, num_flare_circles_lower=6, num_flare_circles_upper=10, src_radius=400, src_color=(255, 255, 255), always_apply=False, p=1):
        """
        snow_point_lower	float	
        눈 양의 lower_bond. [0, 1] 범위에 있어야합니다.

        snow_point_upper	float	
        눈 양의 upper_bond. [0, 1] 범위에 있어야합니다.

        brightness_coeff	float	
        숫자가 클수록 이미지에 더 많은 눈이 생깁니다. > = 0이어야합니다.
        """
        transform = A.Compose([
            A.RandomSunFlare (flare_roi, angle_lower, angle_upper, num_flare_circles_lower, num_flare_circles_upper, src_radius, src_color, always_apply, p)
        ],p=1)
        img = transform(image=image)['image']
        return img

- ImgCorruptlike는 써봤는데 눈, 비오는걸 묘사하는 기능은 신기하긴 한데 어떤 영상이냐에 따라서 원래의 object를 너무 손상시키는게 보여서 구현은 해놨지만 쓸일이 없을 것 같다고 느꼈다 왜그런지는 이따 결과 영상으로 설명하겠다

 

 

 

6. Save

import albumentations as A
import cv2
import os
import numpy as np
from Geometry import *
from Blur import *
from Contrast import *
from Geometry import *
from Color import *
from ImgCorruptlike import *

def createFolderSave(directory, category, image, idx):
    """
    directory : 증강된 이미지가 저장 될 장소, AugmentedIMG(category)이름의 폴더를 생성.
    category : 데이터셋의 클래스 이름, 해당 경로에 AugmentedIMG(category)폴더가 생성된 후 augmented_category+index 파일명으로 저장 됨.
    image : 경로에서 선택한 이미지들
    idx : 파일명에서 순서를 부여할 인덱스
    """
    try:
        if not os.path.exists(directory):
            os.makedirs(directory)
            cv2.imwrite(directory+'\\augmented_{}'.format(category)+str(idx)+'.jpg', image)
        else :
            cv2.imwrite(directory+'\\augmented_{}'.format(category)+str(idx)+'.jpg', image)
    except OSError:
        print('Error : Creating directoy.' + directory)



def Save(directory, category, image):
    idx = 1
    for i in image:
        aug_img = cv2.imread(i)
        src = np.copy(aug_img)
        #Geometry 변환
        if Geometry.bbox_rot90_isChecked : 
            aug_img = Geometry.bbox_rot90(aug_img)
        if Geometry.bbox_rotate_isChecked : 
            aug_img = Geometry.bbox_rotate(aug_img)
        if Geometry.keypoint_rot90_isChecked : 
            aug_img = Geometry.keypoint_rot90(aug_img)
        if Geometry.keypoint_rotate_isChecked : 
            aug_img = Geometry.keypoint_rotate(aug_img)
        if Geometry.keypoint_scale_isChecked : 
            aug_img = Geometry.keypoint_scale(aug_img)
        if Geometry.LongestMaxSize_isChecked : 
            aug_img = Geometry.LongestMaxSize(aug_img)
        if Geometry.RandomScale_isChecked : 
            aug_img = Geometry.RandomScale(aug_img)
        if Geometry.Resize_isChecked : 
            aug_img = Geometry.Resize(aug_img)
        if Geometry.SmallestMaxSize_isChecked : 
            aug_img = Geometry.SmallestMaxSize(aug_img)
        if Geometry.RandomRotate90_isChecked : 
            aug_img = Geometry.RandomRotate90(aug_img)
        if Geometry.Rotate_isChecked : 
            aug_img = Geometry.Rotate(aug_img)
        if Geometry.Perspective_isChecked : 
            aug_img = Geometry.Perspective(aug_img)
        if Geometry.ShiftScaleRotate_isChecked : 
            aug_img = Geometry.ShiftScaleRotate(aug_img)
        #Blur 변환
        if Blur.GaussianBlur_isChecked :
            aug_img = Blur.GaussianBlur(aug_img)
        if Blur.GlassBlur_isChecked :
            aug_img = Blur.GlassBlur(aug_img)
        #Contrast 변환
        if Contrast.RandomBrightness_isChecked : 
            aug_img = Contrast.RandomBrightness(aug_img)
        if Contrast.RandomContrast_isChecked : 
            aug_img = Contrast.RandomBrightnessContrast(aug_img)
        if Contrast.RandomBrightnessContrast_isChecked : 
            aug_img = Contrast.RandomBrightnessContrast(aug_img)
        #Color 변환
        if Color.HueSaturationValue_isChecked : 
            aug_img = Color.HueSaturationValue(aug_img)
        if Color.RGBShift_isChecked : 
            aug_img = Color.RGBShift(aug_img)
        #ImgCorruptlike 변환
        if ImgCorruptlike.RandomFog_isChecked : 
            aug_img = ImgCorruptlike.RandomFog(aug_img)
        if ImgCorruptlike.RandomRain_isChecked : 
            aug_img = ImgCorruptlike.RandomRain(aug_img)
        if ImgCorruptlike.RandomShadow_isChecked : 
            aug_img = ImgCorruptlike.RandomShadow(aug_img)
        if ImgCorruptlike.RandomSnow_isChecked : 
            aug_img = ImgCorruptlike.RandomSnow(aug_img)
        if ImgCorruptlike.RandomSunFlare_isChecked : 
            aug_img = ImgCorruptlike.RandomSunFlare(aug_img)

        
        createFolderSave(directory, category, aug_img, idx)
        cv2.imshow("src"+str(idx), src)
        cv2.imshow(str(idx),aug_img)
        idx += 1

directory = r"D:\Data Augmentation" # AugmentedIMG(카테고리명) 폴더가 생성되고 증강된 이미지가 저장 될 경로
category = "Image" #카테고리명 폴더명, 폴더 내 저장될 파일명에 쓰임
directory = "{}\AugmentedIMG({})".format(directory, category) 
image = ('1.jpg','2.jpg','3.jpg','4.jpg') # 이게 튜플형식 이미지명


if __name__ == '__main__':
    Save(directory, category, image)


cv2.waitKey()
cv2.destroyAllWindows()

- createFolderSave(경로, 카테고리, 이미지, 인덱스)를 받는 함수를 정의했다.

- 이 함수는 입력받은 경로가 없다면 폴더를 생성하여 augmented_카테고리+인덱스 파일명으로 증강된 이미지들을 저장한다. 경로가 이미 있다면 그 경로에다가 이미지들을 저장만 한다

 

-Save(경로, 카테고리 ,이미지) 를 받는 함수를 정의했고

여기서 각 증강 기법 클래스별로 flag의 True/False 여부에 따라 증강이 적용된다

 

-directory = r"경로" 에서  r을 써둔 이유는 경로명에 \User 이런게 있으면 유니코드 에러가 나기 때문에 에러를 안나게 하고자 추가하였다.

 


실행 결과는 다음과 같다. (RandomSnow 기법만 걸어준 결과)

좌측 4개가 원본이고 우측4개가 증강된 이미지다 왜 ImgCorruptlike를 안쓴다고 했는지 그 이유가 여기 적혀있다  오브젝트 훼손이 심하다

 


정상적으로 augmentation을 시켜보겠다.

 

RandomRotate, GaussianBlur, RGBShift, RandomBrightnessContrast 를 Dafault값만 가지고 다 적용시켜본 결과  영상이 이렇게 나왔다.

 

이정도면 나름 의미있는 augmentation 결과라고 생각한다.

+++Data augmentation Project 중인데 UI 구현은 옆자리 석사과정 친구가 맡기로 해서 블로그에는 완성된 프로토타입의 프로그램이 올라갈 것 같은데 시간이 난다면 pyqt5를 이용한 GUI 연동까지 해보도록 하겠다.

728x90
728x90

이번 글에서는 albumentations.ai/docs/examples/example_bboxes/ 에 있는

object detection용 바운딩박스 증강 예제를 연습해본다.

 

1. 먼저 필요한 라이브러리들을 import 해준다.

import cv2
import albumentations as A
import matplotlib.pyplot as plt
import numpy as np
import random

2. 이미지에서 경계상자 및 클래스 레이블을 시각화 하는 함수를 정의한다

OX_COLOR = (255, 0, 0) # Red
TEXT_COLOR = (255, 255, 255) # White

def visualize_bbox(img, bbox, class_name, color=BOX_COLOR, thickness=2):
    """Visualizes a single bounding box on the image"""
    x_min, y_min, w, h = bbox
    x_min, x_max, y_min, y_max = int(x_min), int(x_min + w), int(y_min), int(y_min + h)

    cv2.rectangle(img, (x_min, y_min), (x_max, y_max), color=color, thickness=thickness) 
	
    #이부분 이해하기
    ((text_width, text_height), _) = cv2.getTextSize(class_name, cv2.FONT_HERSHEY_SIMPLEX, 0.35, 1)
    
    cv2.rectangle(img, (x_min, y_min - int(1.3 * text_height)), (x_min + text_width, y_min), BOX_COLOR, -1)
    cv2.putText(
        img,
        text=class_name,
        org=(x_min, y_min - int(0.3 * text_height)),
        fontFace=cv2.FONT_HERSHEY_SIMPLEX,
        fontScale=0.35, 
        color=TEXT_COLOR, 
        lineType=cv2.LINE_AA,
    )
    return img
 
def visualize(image, bboxes, category_ids, category_id_to_name):
    img = image.copy()
    for bbox, category_id in zip(bboxes, category_ids):
        class_name = category_id_to_name[category_id]
        img = visualize_bbox(img, bbox, class_name)
    plt.figure(figsize=(12, 12))
    plt.axis('off')
    plt.imshow(img)
    plt.show()

visualize_bbox:

- 함수의 인자로 이미지,  바운딩박스(1차원배열), 클래스명(문자열), 색상(튜플)을 받는다.

- 2차원 배열 내  원소마다 [x_min, y_min, x_max, y_max]가 담겨있다. 이를 통해서 바운딩박스의 시작과 끝점 좌표를정의한다.

- cv2.getTextSize(텍스트, 폰트, 폰트 크기, 두께)를 입력해서  폰트size(x,y) 튜플,

베이스라인(맨아래 텍스트 지점을 기준으로 한 기준선의 y좌표)을 ( (w,h), _)로 리턴받는다.  

 

- cv2.putText로( 클래스명, 문자열을 출력할 위치의 좌측 하단 좌표(x,y)좌표, 폰트 종류, 폰트크기 ,색, 두께, 라인 타입)을 받아 작성한다.

 

# 이미지 및 주석 얻기
image = cv2.imread('coco.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
bboxes = [[5.66, 138.95, 147.09, 164.88], [366.7, 80.84, 132.8, 181.84]]
category_ids = [17, 18]
category_id_to_name = {17: 'cat', 18: 'dog'}

visualize:

- 함수의 인자로 이미지, 바운딩박스(2차원배열),  클래스아이디(1차원배열) , 클래스아이디(딕셔너리) 를 받는다

- bboxes(2차원배열), category_dis(1차원배열)의 각 원소마다

class name는  category_id_to_name의 category_ids의 원소에 해당하는 키값을 가진 value의 문자열이 되고

이미지에는 각 바운딩박스에 각 클래스명에 해당하는 레이블과 바운딩박스를 그린다.

- plt로 영상을 출력한다.

 


3. 정의한 변수들과 함수들을 가지고 바운딩박스 처리된 이미지를 출력한다.

visualize(image, bboxes, category_ids, category_id_to_name)

이렇게 바운딩 박스가 처리된 영상이 출력된다.


 

4. Albumentations로 증강 파이프라인을 작성한다

#증강 파이프라인 정의
transform = A.Compose([
    A.HorizontalFlip(p=0.5),
    A.RandomContrast(limit=0.5,p=1)
    ],
    bbox_params=A.BboxParams(format='coco', label_fields=['category_ids']),
)
#시각화 목적으로 랜덤 시드를 수정해서 증강된 화면이 일정하게 나오도록 설정
random.seed(7)
transformed = transform(image=image, bboxes=bboxes, category_ids=category_ids)
visualize(
    transformed['image'],
    transformed['bboxes'],
    transformed['category_ids'],
    category_id_to_name,
)

- Compose안에 배열로 여러 증강 방법들을 넣는건 해봤지만 그 외의 매개변수가 들어가는것을 처음봐서  API를 다시 뜯어봤다. 

- bbox_params(format=" 'coco', 'pascal_voc', 'albumentations'또는 'yolo' ", label_field=[바운딩박스의 라벨링 키값 배열]

을 추가해주므로써 바운딩박스를 함께 증강시켜준다.

 

- transformed는 transform(Compose클래스 객체를 ( image = coco사진, bbox= bboex배열, 라벨 키= cotegort_ids)로 생성 한 후에 

- visualize() 함수에 compose객체의 (이미지, 바운딩박스 , 라벨배열, 라벨 대응텍스트 딕셔너리)를 넣어줘서 이미지를 출력한다

 


4. 증강절차를 거친 이미지다.  HorizontalFlip과 RandomContrast가 잘 적용된 모습이고 바운딩박스가 유지되었다.

728x90
728x90

 

저번 포스팅에 설치를 완료했으니 이제 라이브러리를 이용해서 이미지에 적용시켜 볼 예정이다.

코드는 다음과 같다.

import albumentations as A
import cv2
import matplotlib.pyplot as plt

#Lambda function 전용 메소드
def cusmtom_fn(image, **kwargs):
    rose = cv2.imread('rose.bmp')
    h, w = image.shape[:2]
    rose = cv2.resize(rose, (h,w), interpolation=cv2.INTER_CUBIC)

    image = cv2.addWeighted(image,0.5, rose,0.5, 0)
    print('Lambda function Seuccess!')
    print(kwargs)
    return image

#증강 파이프라인 구축
transform = A.Compose([
    A.GaussianBlur(blur_limit=(3,7), sigma_limit=4, p=1),
    A.RandomRotate90(p=1),
    A.RandomGridShuffle(grid=(2,2), p=1),
    A.Lambda(name='Lambda', image = cusmtom_fn, p=1)

])

src = cv2.imread('lenna.bmp')
#augmentation
dst = transform(image= src)['image']
#출력
cv2.imshow('src', src)
cv2.imshow('dst', dst)

cv2.waitKey()
cv2.destroyAllWindows()

1. Albumentation을 import 해준다.

 

2. albumentations의 lambda 함수를 쓰기 위해 개인이 직접 메소드를 만들어서 정의한다. API는 다음과 같다.

- 이미지를 증강시킬 메소드를 만들었다면 image = 메소드명 을 하면 된다.

 

3. A.Compose() 안에 증강 파이프라인을 구축한다  API 상에 있는 transforms 인자에 배열형태로 집어넣는다.

 

4. 결과는 다음과 같다.  람다함수가 정상적으로 적용된걸 알 수 있다.

+ 추가적으로 def custom_fn에서 **kwargs인자에 뭐가 들어오나 궁금해서

print(kwargs)코드를 추가해봤는데 결과는 다음과 같이 영상의 크기를 딕셔너리 형태로 터미널에 출력해준다.

 

 

이상으로 다음엔 데이터셋에 적용시켜보기를 해보겠다.

728x90
728x90

Object Detection 학습을 위한  Data Augmentation을 공부하는 중에 

- tensorflow.keras

- imgaug

- openCV

- torchvision

- Albumentations  

 

등등 여러가지 Libarary가 있는 것을 알게 되었고,

Albumentations이  torchvision과 방식은 유사하지만 imgaug만큼 다양한 augmentation 방법을 제공하며 연산속도도 더욱 빠른것을 밑에 블로그를 통해 알게되었다.

 

 

albumentations - fast image augmentation library 소개 및 사용법 Tutorial

image augmentation library인 albumentations에 대한 소개와 사용 방법을 Tutorial로 정리해보았습니다.

hoya012.github.io

공식 사이트에 들어가면 설치 방법이 나와있다.

 

Albumentations Documentation - Installation

Albumentations: fast and flexible image augmentations

albumentations.ai

 

나는 anaconda 가상환경을 구축한 다음 해당 명령어를 사용해서  Albumentations를 설치해줬다.

 

 

그다음 import 시킨 후 컴파일 했더니 문제없이 잘 실행되었다.

 

 

 

 

 

 

 

 

 

 

다음 글에선 Albumentation을 이용한 실습을 해볼 예정이다.

728x90

+ Recent posts