2 분 소요

이미지 열기

import PIL

(사용하고자하는 이미지변수) = PIL.Image.open('이미지위치')

img = PIL.Image.open('./images/image.jpg')

이미지 -> numpy

이미지를 불러온 다음 numpy형태로 변환한다.

import numpy as np 
from PIL import Image
img = Image.open("불러올사진.jpg")
img_np_array = np.array(img)
print(img_np_array.shape)

다른 방법으로는 asarray() 함수를 사용 가능하다.

import numpy as np 
from PIL import Image
img = Image.open("불러올사진.jpg")
Image_np_array = np.asarray(img)
print(Img_np_array.shape)

그러면 여기서 asarray와 array의 차이점은 뭐지?

이 둘은 기본적으로 수행하는 역할은 동일하다. 하지만 array의 copy 옵션은 default는 true이고 asarray의 copy 옵션은 default가 false이다. 즉 array는 개체의 복사본을 만드는 반면 asarray는 형변환이 필요한 경우가 아니라면 만들지 않는다.

>>> A = numpy.matrix(numpy.ones((3,3)))
>>> A
matrix([[ 1.,  1.,  1.],
        [ 1.,  1.,  1.],
        [ 1.,  1.,  1.]])

array는 복사를 한 후에 사용을 하기때문에 원본에주는 영향이 없다.

>>> numpy.array(A)[2]=2
>>> A
matrix([[ 1.,  1.,  1.],
        [ 1.,  1.,  1.],
        [ 1.,  1.,  1.]])

하지만 asarray는 필요한 경우가 아니라면 복사를 하지않고 사용하기 때문에 원본이 변화한다

>>> numpy.asarray(A)[2]=2
>>> A
matrix([[ 1.,  1.,  1.],
        [ 1.,  1.,  1.],
        [ 2.,  2.,  2.]])

딥러닝 학습을 할 때 이미지를 불러온 이후 형변환을 자주 한다.

PIL -> numpy -> tensor -> numpy …등등

import torch import numpy as np

예시로 1로 이루어진 3x3 크기의 numpy 행렬을 만들어본다.

A = np.matrix(np.ones((3,3)))

A

matrix([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]])

만든 numpy 행렬을 tensor로 형변환 해준다. tensorflow의 경우 자동으로 gpu에 할당이 되나 pytorch는 지정해주어야 할당이 된다. 고로 지금의 상태는 cpu에 담겨있다.

CPU_Tensor_A = torch.tensor(A)
CPU_Tensor_A
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]], dtype=torch.float64)

tensor에서 numpy로 다시한번 변환해준다. 잘 출력이 된다는 것을 알 수 있다.

NP_CPU_Tensor_A = np.array(CPU_Tensor_A)
NP_CPU_Tensor_A
array([[1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.]])

하지만

실제로 이미지를 이용한 딥러닝 학습을 진행을 하다보면 위의 경우처럼 잘 변환이 되지 않는데 이때 마주하는

TypeError: can't convert cuda:0 device type tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first.

error command가 있다.

NP_CPU_Tensor_A = np.array(CPU_Tensor_A)
NP_CPU_Tensor_A
array([[1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.]])

NP_GPU_Tensor_A = torch.tensor(NP_CPU_Tensor_A, device="cuda")
#TypeError: can't convert cuda:0 device type tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first.
    
#or 
NP_CPU_Tensor_A = NP_GPU_Tensor_A.numpy()
#TypeError: can't convert cuda:0 device type tensor to numpy. Use Tensor.cpu() to copy the tensor to host memory first.

이 error는 gpu에 할당되어있는 tensor를 numpy로 변환을 할 때 생기는 error이다.

how to solve it

NP_CPU_Tensor_A = NP_GPU_Tensor_A.cpu().numpy()
NP_CPU_Tensor_A
array([[1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.]])

gpu에 있는 tensor를 cpu() 로 옮기고 numpy로 변환해주면 잘 작동한다는 것을 알 수 있다.