Deep Learning #10 Pytorch 기초 3 (이미지 분류 모델 만들기)

김서영·2025년 5월 30일

딥러닝

목록 보기
10/13
post-thumbnail

이미지 처리

: 디지털 이미지를 분석하거나 수정하여 정보를 추출하거나 생성하는 기술

목적

  • 시각 정보 이해 : 객체 인식, 얼굴 인식 등
  • 시각적 품질 향상 : 노이즈 제거, 색 보정 등
  • 이미지 생성 및 변형 : 필터 적용, 합성 등

활용 사례

  • 의료 : CT, MRI
  • 보안 : 얼굴 인식 기반 출입 통제
  • 자율 주행 : 도로 및 사물 인식
  • SNS : 필터, 보정, 배경 제거

1. 픽셀(Pixel)

이미지를 구성하는 가장 작은 단위

Red, Green, Blue로 구성된 RGB 채널(3차원 행렬)로 나타낼 수 있음
(각 색상은 0~255(밝기)로 표현됨)

image=np.array([[[255,0,0], [0,255,0],
                 [0,0,0],[255,255,255]]])

plt.figure(figsize=(5,5))
plt.imshow(image)
plt.show()


실습 : 마리오 도트 캐릭터 만들기

RGB 색상 정의

import numpy as np
import matplotlib.pyplot as plt

# RGB 색상 정의
R = [1.0, 0.0, 0.0]  # Red
B = [0.0, 0.0, 1.0]  # Blue
S = [0.9, 0.8, 0.6]  # Skin
W = [1.0, 1.0, 1.0]  # White
K = [0.0, 0.0, 0.0]  # Black
Br = [0.5, 0.2, 0.0] # Brown

이미지 시각화

image1 = np.array([
    [K, K, R, R, R, R, K, K],
    [K, K, R, R, R, W, R, K],
    [K, K, S, B, S, B, K, K],
    [K, K, S, S, Br, Br, K, K],
    [S, R, B, R, R, B, R, S],
    [K, K, B, B, B, B, K, K],
    [K, K, B, B, B, B, K, K],
    [K, K, Br, K, K, Br, K, K]
])

# 시각화
plt.figure(figsize=(5, 5))
plt.imshow(image1)
plt.show()

2. Image Loader

Pillow를 이용한 이미지 불러오기

from PIL import Image

img_pil=Image.open(r'/content/sample.png')
img_pil.show()

plt.imshow(img_pil)
plt.show()

print(img_pil)

OpenCV를 이용한 이미지 불러오기

import cv2
from google.colab.patches import cv2_imshow

img_cv = cv2.imread('/content/sample.png')
cv2_imshow(img_cv)

print(img_cv)

3. Image 변형하기

  • resize : 크기 조절하기
  • cvtColor : Color Channel 바꾸기
h,w,c=img_cv.shape

img_resized=cv2.resize(img_cv, (w//10, h//10))
img_resized=cv2.cvtColor(img_resized, cv2.COLOR_BGR2RGB)

plt.figure(figsize=(5,5))
plt.imshow(img_resized)
plt.axis('off')
plt.show()

Gray Scale

흑백 이미지로 변환하는 것으로, 0~255(밝기 정보)를 가지는 채널 하나로만 구성됨

RGB -> Gray 변환

  • Gray=0.299R+0.587G+0.114BGray=0.299R + 0.587G + 0.114B
    (사람 눈의 민감도에 따라 가중치 다르게 부여함, 녹색에 가장 민감)

Gray Scale의 장점

  • 연산량 감소
  • 윤곽선, 경계 탐지 등 단순한 특징 추출시 유용
import cv2
from google.colab.patches import cv2_imshow
import numpy as np

img_cv = cv2.imread('/content/sample.png')

B, G, R = cv2.split(img_cv)
gray = 0.299 * R + 0.587 * G + 0.114 * B
gray = gray.astype(np.uint8) 

cv2_imshow(gray)

4. 이미지와 신경망

이미지를 신경망으로 표현하는데 있어서, 문제점 존재

  • Problem : 이미지는 2차원(or 3차원) 신경망의 입력은 1차원이므로 바로 넣어서 처리 불가
  • Solution : 이미지를 1차원으로 바꾸는 과정 필요

Pixel의 위치는 [x,y][ x,y ] ( or [x,y,z][x,y,z])로 표현됨
(일반적으로 [0,0][0,0]은 왼쪽 위를 표현)

사진 출처

이미지 전처리

신경망과 이미지가 1:1로 mapping 되려면 이미지를 1차원 배열로 전처리 필요

  • Numpy, OpenCV에서 reshape(크기) 사용하기
  • Pytorch에서 view(크기) 사용하기

5. DataLoader 만들기

Step1. 이미지 불러오기

ImageFolder

torchvision.datasets.ImageFolder 는 이미지 데이터셋을 손쉽게 불러올 수 있도록 도와주는 클래스

ImageFolder 목적

  • 이미지를 폴더 구조에 따라 자동으로 레이블링

  • 향후 transforms를 이용한 전처리 및 데이터 증강 가능

  • Pytorch 학습을 위한 Dataset 객체 반환

from torchvision.datasets import ImageFolder
from sklearn.model_selection import train_test_split

dataset = ImageFolder(train_test_set_small)
train_data, test_data = train_test_split(dataset.imgs, test_size=0.2, random_state=42)

print(train_data)

Step2. GrayScale 변환

Step3. 사이즈 변환(28X28)

Step4. 1차원 배열로 shape 변환

class ImageLoader(Dataset):
  def __init__(self, dataset):
    self.dataset=dataset

  def __len__(self):
    return len(self.dataset)
  
  def __getitem__(self, item):
    image=cv2.imread(self.dataset[item][0])
    image=cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    image=cv2.resize(image,(28,28))
    image=image.reshape(28*28)
    label=self.dataset[item][1]
    return image, label

6. 신경망 학습하기

이미지 전처리

class ImageLoader(Dataset):
    def __init__(self, dataset):
        self.dataset = dataset
        self.imgs = dataset

    def __len__(self):
        return len(self.dataset)

    def __getitem__(self, index):
        image_path, label = self.dataset[index]
        image = cv2.imread(image_path)
        image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        image = cv2.resize(image, (28, 28))
        image = image.astype(np.float32) / 255.0  # 정규화
        image = image.reshape(1, 28, 28)           # 채널 차원 추가
        return torch.tensor(image), torch.tensor(label)

신경망 구조

class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.flatten = nn.Flatten()
        self.fc1 = nn.Linear(28 * 28, 512)
        self.relu1 = nn.ReLU()
        self.fc2 = nn.Linear(512, 256)
        self.relu2 = nn.ReLU()
        self.fc3 = nn.Linear(256, 2)

    def forward(self, x):
        x = self.flatten(x)
        x = self.relu1(self.fc1(x))
        x = self.relu2(self.fc2(x))
        x = self.fc3(x)  
        return x

Hyperparameter, DataLoader 설정

batch_size = 64

train_dataset = ImageLoader(train_data)
test_dataset = ImageLoader(test_data)

train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size)

Model 학습

model = SimpleNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

num_epochs = 10
for epoch in range(num_epochs):
    model.train()
    total_loss = 0
    for images, labels in train_loader:
        optimizer.zero_grad()
        outputs = model(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        total_loss += loss.item()
    print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {total_loss:.4f}")

Model 평가하기

import matplotlib.pyplot as plt
import torch

target_img = 4

plt.figure(figsize=(2, 2))
plt.imshow(images[target_img].view(28, 28).cpu().numpy(), cmap='gray')
plt.axis('off')
plt.show()

with torch.no_grad():
    pred = model(images[target_img].view(1, 28*28))  # 배치 차원 추가
    pred = torch.argmax(pred)

# 예측 결과 출력
if pred == 0:
    print("예측한 이미지는 고양이 입니다.")
else:
    print("예측한 이미지는 강아지 입니다.")

# 정답과 비교
if pred == labels[target_img]:
    print("정답입니다!")
else:
    print("오답입니다!")

profile
안녕하세요 :)

0개의 댓글