전공 공부/데이터 분석

이미지 시각화 함수

상솜공방 2024. 2. 3. 15:12

필요한 라이브러리 임포트

import cv2
import torch
import numpy as np
from torch import nn
import torch.nn.functional as F
import matplotlib.pyplot as plt

 

 

이미지를 마스크 경부에 따라 넘파이 어레이로 읽어오기

def img_read(data_path, is_mask = False):
    if is_mask:
        img = cv2.imread(data_path, cv2.IMREAD_GRAYSCALE) # (256, 256)
    else:
        img = cv2.imread(data_path) # (256, 256, 3)
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # BGR -> RGB

    return img

 

 

넘파이 어레이를 텐서로 변환하기

def img_to_tensor(img):
    img= img.astype(np.float32) / 255.0 # 모델이 학습을 잘 할 수 있도록 [0, 1] 사이로 정규화
    # 텐서의 값이 [0, 1] 사이어도 plt 함수는 유동적으로 이를 [0, 255]로 확장하여 이미지를 보여준다
    
    if img.ndim == 3: # 색상 이미지라면
        img_t = torch.from_numpy(img).permute(2, 0, 1)
    else: # 흑백 마스크라면
        img_t = torch.from_numpy(img)
    return img_t

 

 

텐서를 이미지로 시각화하기

def tensor_imshow(tensor):
    if tensor.dim() == 3: # 컬러 사진
        image = tensor.permute(1, 2, 0).numpy()
        plt.figure(figsize=(2, 2))
        plt.imshow(image) # 텐서의 값이 [0, 1] 사이어도 plt 함수는 유동적으로 이를 [0, 255]로 확장하여 이미지를 보여준다

    elif tensor.dim() == 2: # 흑백 마스크
        image = tensor.numpy()
        plt.figure(figsize=(2, 2))
        plt.imshow(image, cmap = 'gray') # cmap = 'gray' 옵션을 주지 않으면 이미지가 이상하게 나옴.
    else:
        raise ValueError("텐서의 차원을 확인하세요.")

    plt.axis('off')  # 축을 보이지 않게 합니다. cmap='gray'
    plt.show()

 

 

질의사항

더보기

cv2_image_to_tensor() 함수에서 이미지를 np.float32 타입으로 변환하는 이유

1. 정규화를 위해
이미지 데이터는 일반적으로 0부터 255 사이의 정수 값을 가지는 uint8 타입으로 저장됩니다. 딥러닝 모델을 훈련시킬 때, 입력 데이터를 0과 1 사이의 값으로 정규화하는 것이 일반적인 관행입니다. 이는 모델의 수렴을 돕고, 다양한 가중치 초기화 기법과 잘 작동하도록 합니다. np.float32 타입으로 변환하는 과정에서 이미지 데이터를 255.0으로 나누어 정규화할 수 있으며, 이는 모델 학습에 더 적합한 데이터 형태를 만듭니다.

2. 연산 효율성 및 호환성
딥러닝 프레임워크는 부동소수점 연산에 최적화되어 있으며, 특히 GPU를 사용한 계산에서 float32 타입이 널리 사용됩니다. np.float32로 변환함으로써, 이미지 데이터를 PyTorch 텐서로 변환할 때 연산 효율성을 높이고, 다른 텐서 데이터 타입과의 호환성을 보장할 수 있습니다.

3. 더 넓은 연산 범위
uint8 타입은 0부터 255까지의 정수만을 표현할 수 있습니다. 이미지 처리나 딥러닝 모델에서는 종종 이 범위를 벗어나는 연산(예: 가중치 적용, 활성화 함수 계산 등)이 필요합니다. np.float32 타입으로 변환하면, 더 넓은 범위의 실수 연산을 수행할 수 있고, 연산 결과도 더 정밀하게 표현할 수 있습니다.

4. 손실 함수 및 그라디언트 계산
딥러닝 모델의 손실 함수와 그라디언트 계산은 실수 연산을 필요로 합니다. np.float32 타입은 이러한 계산을 위한 충분한 정밀도를 제공하며, 모델의 학습 과정에서 발생할 수 있는 수치적 불안정성을 줄여줍니다.

이러한 이유들로, 이미지 데이터를 np.float32 타입으로 변환하는 것은 딥러닝 모델을 훈련시키고, 이미지 처리 작업을 수행하는 데 있어서 중요한 단계입니다.

 

 

imshow() 함수가 [0, 1]로 정규화된 텐서를 [0, 255]로 스케일링할 필요 없이 이미지를 잘 보여주는 이유

 

Matplotlib의 imshow() 함수는 이미지 데이터를 시각화할 때 입력 데이터의 범위를 자동으로 해석합니다. 즉, 입력 데이터가 [0, 1] 범위에 있으면 이를 직접 이미지 픽셀 값으로 사용하고, [0, 255] 범위에 있으면 이를 255로 나누어 [0, 1] 범위로 정규화하지 않고도 올바르게 이미지로 표시할 수 있습니다. 이는 imshow() 함수가 다양한 데이터 형태와 범위를 유연하게 처리할 수 있도록 설계되었기 때문입니다.

[0, 1] 범위의 데이터
이 경우, imshow()는 입력된 데이터가 이미 [0, 1] 범위에 있다고 가정하고, 직접 이미지 픽셀 값으로 사용합니다. 이 범위는 부동소수점 데이터 타입에 대해 일반적으로 사용되며, 이미 정규화된 데이터로 간주됩니다.

[0, 255] 범위의 데이터
이 경우, imshow()는 입력 데이터가 8비트 정수형 데이터 타입(uint8)일 때, [0, 255] 범위의 값을 자동으로 [0, 1] 범위로 스케일링하지 않고 그대로 이미지 픽셀 값으로 사용합니다. 만약 데이터가 float 타입이고 [0, 255] 범위에 있다면, imshow()는 데이터의 범위를 자동으로 조정하지 않고, 데이터를 그대로 시각화하려고 시도할 수 있으며, 이는 예상치 못한 결과를 초래할 수 있습니다. 그러나 일반적으로 float 타입의 데이터는 [0, 1] 범위에 있을 것으로 예상됩니다.

따라서, PyTorch 텐서가 [0, 1] 또는 [0, 255] 범위의 값을 가지고 있을 때, imshow()를 사용하여 시각화하면 동일한 이미지가 표시될 수 있습니다. 그러나 이는 텐서의 데이터 타입과 imshow()가 데이터를 어떻게 해석하는지에 따라 달라질 수 있으므로, 일관된 결과를 얻기 위해서는 데이터를 명시적으로 [0, 1] 범위로 정규화하는 것이 좋습니다. 데이터가 float 타입이고 [0, 255] 범위에 있다면, 시각화 전에 명시적으로 255로 나누어 정규화하는 것이 안전합니다.

'전공 공부 > 데이터 분석' 카테고리의 다른 글

파이토치 기초  (0) 2024.02.03
유사한 이미지 삭제하기  (0) 2024.02.02
다양한 파일을 읽어와 이미지 분류하기  (0) 2024.02.02