이미지 처리로 시작하는 딥러닝 2주차

김서영·2022년 11월 20일
0

딥러닝

목록 보기
2/2

1. 딥러닝 모델과 이미지 다운로드

2. 이미지 출력

1. 패키지 불러오기

import cv2
import numpy as np

2. 다운로드 받은 딥러닝 모델 로드하기

net = cv2.dnn.readNetFromTorch('models/eccv16/starry_night.t7')

3. 이미지 출력하기

img = cv2.imread('imgs/01.jpg')

cv2.imshow('img', img)
cv2.waitKey(0)

3. 이미지 전처리 하기

모델의 성능을 높이기 위해 이미지 전처리라는 방법을 쓴다.
모델의 성능이라고 하면 일반적으로는 딥러닝 모델이 얼마나 정답을 잘 맞추는지를 가리키는 정확도를 말한다.

- 전처리 코드

h, w, c = img.shape

img = cv2.resize(img, dsize=(500, int(h / w * 500)))

MEAN_VALUE = [103.939, 116.779, 123.680]
blob = cv2.dnn.blobFromImage(img, mean=MEAN_VALUE)
  • img.shape : 이미지의 높이, 너비, 채널을 받을 수 있다. 우리는 이 이미지를 너비 500으로 이미지의 크기를 변형시켜서 아무리 큰 이미지를 사용해도 모델의 추론 속도가 비슷하도록 만들어야 한다. 왜냐하면 큰 이미지를 사용 할 수록 연산 속도가 느리기. 때문!!
  • MEAN_VALUE : 연구원들이 사용했던 전처리 방법
    이미지 각 픽셀에 [103.939, 116.779, 123.680] 이 값을 빼서 성능을 높인 것이다.
  • cv2.dnn.blobFromImage : 우리가 하기 귀찮은 작업들을 한꺼번에 할 수 있도록 도와준다.
    • MEAN_VALUE 빼기 연산
    • 딥러닝 모델에 넣기 위한 이미지 데이터 차원 변형

- 차원 변형이란?

딥러닝 모델에 넣기 위해선 이미지의 차원 변형이 필요하다.

print(img.shape) # 차원 변형 전 (325, 500, 3)

MEAN_VALUE = [103.939, 116.779, 123.680]
blob = cv2.dnn.blobFromImage(img, mean=MEAN_VALUE)

print(blob.shape) # 차원 변형 후 (1, 3, 325, 500)

(높이, 너비, 채널) 의 순서를 (1, 채널, 높이, 너비) 로 변형했다. 데이터의 형태만 변형된 것이지 값이 변형된 것은 아니다.

차원 변형 후 (1, 채널, 높이, 너비) 모양에서 1은 딥러닝에서 배치 사이즈를 의미한다. 딥러닝 모델을 학습시키는 과정에서 이미지를 한 장씩 학습시키지 않고 여러 이미지를 한꺼번에 학습시키는데 만약 이미지를 32개씩 묶어서 학습시킨다면 배치 사이즈는 32가 된다. (32, 채널, 높이, 너비)
우리는 이 모델을 연구한 연구원들이 어떤 배치 사이즈를 사용했는지는 관심이 없고, 1개의 테스트 이미지를 사용할 것이므로 배치 사이즈가 1이 된다.
따라서 (1, 채널, 높이, 너비) 형태가 되는 것!!

4. 추론 결과 보기

1. 결과 추론하기 (Inference)

net.setInput(blob)
output = net.forward()

전처리한 이미지(blob)를 모델에 넣고 추론(forward)한다.
output 변수에 추론한 결과가 저장된다.

2. 결과 후처리하기 (Post processing)

우리는 추론한 결과를 숫자로 볼 수도 있지만 이미지로 보기를 원하기 때문에 숫자 → 이미지 변환 과정을 거쳐야한다.
이미지를 전처리했듯이 결과값을 후처리하여 다시 이미지로 만드는 과정!!

- 후처리 코드

output = output.squeeze().transpose((1, 2, 0))
output += MEAN_VALUE

output = np.clip(output, 0, 255)
output = output.astype('uint8')

전처리했던 과정을 거꾸로 진행한다!!

  • 차원 줄이기
    차원 변형했던 것을 원래대로 (높이, 너비, 채널) 순으로 되돌려놓는다. squeeze() 를 사용하여 추가했던 첫 번째 차원을 삭제하여 (1, 채널, 높이, 너비)에서 (1, ) 부분을 없애고 (채널, 높이, 너비) 형태로 만든다.

  • 순서 바꾸기
    transpose()를 사용하여 (채널, 높이, 너비) → (높이, 너비, 채널) 형태로 변형한다.

  • MEAN_VALUE 더하기
    전처리 했을 때 MEAN_VALUE 를 뺐는데 후처리 할 때는 MEAN_VALUE를 다시 더해준다.

  • 범위 넘어가는 값 잘라내기
    이미지 픽셀 값은 0-255 범위 안에 들어와야하는데 계산 과정에서 간혹 픽셀 값이 0 미만이거나 255를 초과하는 픽셀이 생긴다. 이런 값들을 np.clip()을 사용하여 없애줄 수 있다.

  • 자료형 바꾸기
    마지막으로 이미지의 자료형을 일반 이미지에서 쓰이는 정수형(uint8)으로 바꿔준다.

3. 결과 이미지 출력하기

cv2.imshow('img', img)
cv2.imshow('output')
cv2.waitKey(0)

4. 완성코드

import cv2
import numpy as np

net = cv2.dnn.readNetFromTorch('models/eccv16/starry_night.t7')

img = cv2.imread('imgs/01.jpg')

h, w, c = img.shape

img = cv2.resize(img, dsize=(500, int(h / w * 500)))

MEAN_VALUE = [103.939, 116.779, 123.680]
blob = cv2.dnn.blobFromImage(img, mean=MEAN_VALUE)

net.setInput(blob)
output = net.forward()

output = output.squeeze().transpose((1, 2, 0))

output += MEAN_VALUE
output = np.clip(output, 0, 255)
output = output.astype('uint8')

cv2.imshow('img', img)
cv2.imshow('output', output)
cv2.waitKey(0)

5. 새로운 이미지로 다시 추론하기

1. 액자 이미지 다운받기

2. 액자 부분 잘라내기

img = cv2.imread('imgs/02.jpg')

h, w, c = img.shape

img = cv2.resize(img, dsize=(500, int(h / w * 500)))

img = img[162:513, 185:428]

3. 잘라낸 이미지만 추론하기

4. 완성 코드

import cv2
import numpy as np

net = cv2.dnn.readNetFromTorch('models/eccv16/la_muse.t7')

img = cv2.imread('imgs/02.jpg')
h, w, c = img.shape
img = cv2.resize(img, dsize=(500, int(h / w * 500)))
img = img[162:513, 185:428]

MEAN_VALUE = [103.939, 116.779, 123.680]
blob = cv2.dnn.blobFromImage(img, mean=MEAN_VALUE)

net.setInput(blob)
output = net.forward()

output = output.squeeze().transpose((1, 2, 0))

output += MEAN_VALUE
output = np.clip(output, 0, 255)
output = output.astype('uint8')

cv2.imshow('img', img)
cv2.imshow('output', output)
cv2.waitKey(0)

6. 반반 적용하기

1. 이미지 다운받기

2. 시작 코드

import cv2
import numpy as np

net = cv2.dnn.readNetFromTorch('models/instance_norm/mosaic.t7')

img = cv2.imread('imgs/03.jpg')

h, w, c = img.shape

img = cv2.resize(img, dsize=(500, int(h / w * 500)))

MEAN_VALUE = [103.939, 116.779, 123.680]
blob = cv2.dnn.blobFromImage(img, mean=MEAN_VALUE)

net.setInput(blob)
output = net.forward()

output = output.squeeze().transpose((1, 2, 0))

output += MEAN_VALUE
output = np.clip(output, 0, 255)
output = output.astype('uint8')

cv2.imshow('img', img)
cv2.imshow('result', output)
cv2.waitKey(0)

3. 두 번째 모델 로드하기

net2 = cv2.dnn.readNetFromTorch('models/instance_norm/the_scream.t7')

4. 두 번째 모델 추론하기

net2.setInput(blob)
output2 = net2.forward()

output2 = output2.squeeze().transpose((1, 2, 0))
output2 = output2 + MEAN_VALUE

output2 = np.clip(output2, 0, 255)
output2 = output2.astype('uint8')

5. 두 개의 결과를 절반으로 잘라 이어 붙이기

output3 = np.concatenate([output[:, :250], output2[:, 250:]], axis=1)

cv2.imshow('output3', output3)
profile
개발과 지식의 성장을 즐기는 개발자

0개의 댓글