본문 바로가기

IT/AI

[이미지] Numpy로 이미지 처리 기초 [Python]-cv2

728x90

고양이 사진을 여러 구간으로 나누어 224x224 크기로 10개의 이미지를 만드는 과정

$($하나의 함수로 길게 만들었어요$)$

# 마구잡이로 자르면 고양이의 특징이 없는 이미지가 나올 수 있음
# 전체 이미지 비율을 유지하기 위해서 padding을 하고
# 어떻게 자르든 고양이의 특징이 나오도록 전체 이미지를 축소하고
# 랜덤하게 224x224 크기로 10번 crop 진행

from matplotlib import pyplot as plt
import numpy as np
import random
import cv2

def pad_resize_crop(img, size):
    # 패딩할 상하/좌우 픽셀
    # 상하나 좌우 중 한 세트에만 패딩을 할 예정 -> 초기 값: 0 
    # 상하좌우 모두 패딩을 하고 싶다면
    # 0이 아닌 같은 값으로 넣은 후 
    # 이후 ud, lr 값을 업데이트할 때,
    # += 로 값을 더해주는 형식으로 하면 됨.
    ud, lr = (0, 0), (0, 0)
    
    # 이미지의 높이, 너비 중의 더 큰 값
    M = max(img.shape[:2])
    
    # s = 이미지의 높이와 너비의 차
    s = img.shape[0]-img.shape[1]
    
    # 높이가 너비보다 더 긴 경우(s>0)
    # -> 좌우로 s의 절반씩 패딩
    if M == img.shape[0]:
        lr = (s//2, s//2 + s%2) 
        # s%2는 s가 홀수 인 경우 나머지인 1을 더해주는 역할
        
    # 너비가 높이보다 더 길거나 같은 경우(s<=0)
    #-> 상하로 s의 절반씩 패딩
    else:
        ud = (-s//2, -s//2 + s%2)
    
    # 위에서 구한 값으로 패딩 
    # 3차원에 있는 BGR 정보에 대해서는 패딩 안 함 
    # 하지만 (0,0)으로 값을 지정을 해야, Error가 안 생김
    padded_img = np.pad(img, (ud, lr, (0, 0)))
    
    # size x size 크기로 resize한 이미지 출력
    resized_img = cv2.resize(padded_img, (size, size))
    plt.imshow(resized_img)
    plt.title("padded and resized Image")
    plt.show()
    
    # padding과 resizing후 crop해서 10개의 이미지 만들기
    # 가로 세로 길이 구하기
    height, width = resized_img.shape[:2]
    plt.figure(figsize=(10,5))
    cropped_images = []
    
    for i in range(10):
        # 가로, 세로의 crop할 시작점 
        crop_s_h = random.randint(0, height-224)
        crop_s_w = random.randint(0, width-224)
        
        # 시작점부터 가로, 세로가 224만큼 되도록 crop
        crop_img = resized_img[crop_s_h:crop_s_h+224, crop_s_w:crop_s_w+224, :]

        # 10개의 이미지를 2행 5열로 나열
        plt.subplot(2,5,i+1)
        plt.imshow(crop_img)
        plt.title(f"cropped image_{i+1}")
        
        # crop한 이미지 저장
        cropped_images.append(crop_img)
    plt.show()
    
    return np.array(cropped_images)

# 이미지 불러오기 RGB로 변환 후 출력
org_img = cv2.imread("./cat2.png")[:,:,::-1]
plt.imshow(org_img)
plt.title(f"original image")
plt.show()

pad_resize_crop_img = pad_resize_crop(org_img, 500)

 

Padding, Resizing, Cropping별로 함수를 따로 작성

더보기
from matplotlib import pyplot as plt
import numpy as np
import random
import cv2

def padding(img):
    # 패딩할 상하/좌우 픽셀
    # 상하나 좌우 중 한 세트에만 패딩을 할 예정 -> 초기 값: 0 
    # 상하좌우 모두 패딩을 하고 싶다면
    # 0이 아닌 같은 값으로 넣은 후 
    # 이후 ud, lr 값을 업데이트할 때,
    # += 로 값을 더해주는 형식으로 하면 됨.
    ud, lr = (0, 0), (0, 0)
    
    # 이미지의 높이, 너비 중의 더 큰 값
    M = max(img.shape[:2])
    
    # s = 이미지의 높이와 너비의 차
    s = img.shape[0]-img.shape[1]
    
    # 높이가 너비보다 더 긴 경우(s>0)
    # -> 좌우로 s의 절반씩 패딩
    if M == img.shape[0]:
        lr = (s//2, s//2 + s%2) 
        # s%2는 s가 홀수 인 경우 나머지인 1을 더해주는 역할
        
    # 너비가 높이보다 더 길거나 같은 경우(s<=0)
    #-> 상하로 s의 절반씩 패딩
    else:
        ud = (-s//2, -s//2 + s%2)
    
    # 위에서 구한 값으로 패딩 
    # 3차원에 있는 BGR 정보에 대해서는 패딩 안 함 
    # 하지만 (0,0)으로 값을 지정을 해야, Error가 안 생김
    padded_img = np.pad(img, (ud, lr, (0, 0)))
    
    # padding한 이미지 출력
    plt.imshow(padded_img)
    plt.title("Padded Image")
    plt.show()
    
    return padded_img

def resizing(img, size):
    # size x size 크기로 resize한 이미지 출력
    resized_img = cv2.resize(img, (size, size))
    plt.imshow(resized_img)
    plt.title("Resized Image")
    plt.show()
    
    return resized_img

def cropping(img):
    # crop해서 10개의 이미지 만들기
    # 가로 세로 길이 구하기
    height, width = img.shape[:2]
    plt.figure(figsize=(10,5))
    
    # crop한 이미지 저장할 리스트
    cropped_images = []
    
    for i in range(10):
        # 가로, 세로의 crop할 시작점 
        crop_s_h = random.randint(0, height-224)
        crop_s_w = random.randint(0, width-224)
        
        # 시작점부터 가로, 세로가 224만큼 되도록 crop
        crop_img = img[crop_s_h:crop_s_h+224, crop_s_w:crop_s_w+224, :]

        # 10개의 이미지를 2행 5열로 나열
        plt.subplot(2,5,i+1)
        plt.imshow(crop_img)
        plt.title(f"cropped image_{i+1}")
        
        # crop한 이미지 저장
        cropped_images.append(crop_img)
    plt.show()
    
    return np.array(cropped_images)

# 이미지 불러오기 RGB로 변환 후 출력
org_img = cv2.imread("./cat2.png")[:,:,::-1]
plt.imshow(org_img)
plt.title(f"original image")
plt.show()

pad_img = padding(org_img)
resize_img = resizing(pad_img, 500)
crop_img = cropping(resize_img)

 

pad_img = padding$($org_img$)$
resize_img = resizing$($pad_img, 500$)$
crop_img = cropping$($resize_img$)$

 

마지막에 이 과정은 각 함수 마지막에 넣어서 padding$()$을 실행하면 자동으로 resizing과 cropping도 실행되게 할 수도 있습니다.