자료 안내: 여기서 다루는 내용은 아래 사이트의 내용을 일부 참고하여 생성되었음.

http://www.scipy-lectures.org/

넘파이 활용 기초 2


In [1]:
import matplotlib.pyplot as plt
import numpy as np

In [2]:
%matplotlib inline

주요 내용

  • 이미지 데이터 다루기

  • 이미지 파일(png, jpg, pdf 등)을 다루는 방법을 예제를 이용하여 알아 본다.

이미지 데이터 불러오기 1

먼저 아래 코드는 너구리 사진 데이터를 불러온다. 코드에 사용된 이미지 데이터는 scipy.misc 모듈에 포함되어 있는 face() 함수의 리턴값이다.

주의: scipy 모듈에 대해서는 나중에 다룬다.


In [3]:
import scipy.misc

img = scipy.misc.face()

img에 저장된 데이터를 이미지로 보는 방법은 아래와 같다.


In [4]:
plt.imshow(img)


Out[4]:
<matplotlib.image.AxesImage at 0x180d758128>

img 변수에 저장된 값은 넘파이 어레이이다.


In [5]:
type(img)


Out[5]:
numpy.ndarray

실제로 아래의 값을 갖는다.


In [6]:
img


Out[6]:
array([[[121, 112, 131],
        [138, 129, 148],
        [153, 144, 165],
        ..., 
        [119, 126,  74],
        [131, 136,  82],
        [139, 144,  90]],

       [[ 89,  82, 100],
        [110, 103, 121],
        [130, 122, 143],
        ..., 
        [118, 125,  71],
        [134, 141,  87],
        [146, 153,  99]],

       [[ 73,  66,  84],
        [ 94,  87, 105],
        [115, 108, 126],
        ..., 
        [117, 126,  71],
        [133, 142,  87],
        [144, 153,  98]],

       ..., 
       [[ 87, 106,  76],
        [ 94, 110,  81],
        [107, 124,  92],
        ..., 
        [120, 158,  97],
        [119, 157,  96],
        [119, 158,  95]],

       [[ 85, 101,  72],
        [ 95, 111,  82],
        [112, 127,  96],
        ..., 
        [121, 157,  96],
        [120, 156,  94],
        [120, 156,  94]],

       [[ 85, 101,  74],
        [ 97, 113,  84],
        [111, 126,  97],
        ..., 
        [120, 156,  95],
        [119, 155,  93],
        [118, 154,  92]]], dtype=uint8)

즉, img는 3차원 어레이이며, 각 항목의 값은 uint8, 즉 8비트 값의 (부호없는) 정수들이다.


In [7]:
img.shape


Out[7]:
(768, 1024, 3)

In [8]:
img.dtype


Out[8]:
dtype('uint8')

이미지 데이터 어레이 자료형

8비트 값의 (부호없는) 정수형 이외에 이미지 데이터를 다루는 어레이에 사용되는 숫자들의 자료형은 아래와 같다.

이미지 데이터를 사진으로 저장하기

img에 저장된 데이터를 실제 이미지로 변형하여 저장할 수도 있다.

아래 코드는 img 변수에 저장된 넘파이 어레이를 사진으로 변경하여 images07 디렉토리 안에 raccoon.png 라는 파일명으로 저장하는 코드이다.


In [9]:
from PIL import Image

raccoon = Image.fromarray(img)
raccoon.save('images/raccoon.png')

raccoon.png 파일은 정말로 동일한 이미지를 저장하고 있다.

이미지 데이터 불러오기

이번엔 저장된 이미지 파일로부터 이미지 데이터를 불러오려면 예를 들어, plt.imread() 함수를 이용하면 된다.


In [10]:
img_raccoon = plt.imread('images/raccoon.png')
img_raccoon


Out[10]:
array([[[ 0.47450981,  0.43921569,  0.51372552],
        [ 0.5411765 ,  0.50588238,  0.58039218],
        [ 0.60000002,  0.56470591,  0.64705884],
        ..., 
        [ 0.46666667,  0.49411765,  0.29019609],
        [ 0.51372552,  0.53333336,  0.32156864],
        [ 0.54509807,  0.56470591,  0.35294119]],

       [[ 0.34901962,  0.32156864,  0.39215687],
        [ 0.43137255,  0.40392157,  0.47450981],
        [ 0.50980395,  0.47843137,  0.56078434],
        ..., 
        [ 0.4627451 ,  0.49019608,  0.27843139],
        [ 0.52549022,  0.5529412 ,  0.34117648],
        [ 0.57254905,  0.60000002,  0.3882353 ]],

       [[ 0.28627452,  0.25882354,  0.32941177],
        [ 0.36862746,  0.34117648,  0.41176471],
        [ 0.4509804 ,  0.42352942,  0.49411765],
        ..., 
        [ 0.45882353,  0.49411765,  0.27843139],
        [ 0.52156866,  0.55686277,  0.34117648],
        [ 0.56470591,  0.60000002,  0.38431373]],

       ..., 
       [[ 0.34117648,  0.41568628,  0.29803923],
        [ 0.36862746,  0.43137255,  0.31764707],
        [ 0.41960785,  0.48627451,  0.36078432],
        ..., 
        [ 0.47058824,  0.61960787,  0.38039216],
        [ 0.46666667,  0.6156863 ,  0.3764706 ],
        [ 0.46666667,  0.61960787,  0.37254903]],

       [[ 0.33333334,  0.39607844,  0.28235295],
        [ 0.37254903,  0.43529412,  0.32156864],
        [ 0.43921569,  0.49803922,  0.3764706 ],
        ..., 
        [ 0.47450981,  0.6156863 ,  0.3764706 ],
        [ 0.47058824,  0.61176473,  0.36862746],
        [ 0.47058824,  0.61176473,  0.36862746]],

       [[ 0.33333334,  0.39607844,  0.29019609],
        [ 0.38039216,  0.44313726,  0.32941177],
        [ 0.43529412,  0.49411765,  0.38039216],
        ..., 
        [ 0.47058824,  0.61176473,  0.37254903],
        [ 0.46666667,  0.60784316,  0.36470589],
        [ 0.4627451 ,  0.60392159,  0.36078432]]], dtype=float32)

주의: imgimg_raccoon 변수에 저장된 값들이 다르다. 하지만 두 데이터는 동일한 이미지를 다루는 데이터이며, 다만 사용되는 숫자들의 자료형이 다를 뿐이다.

주의: plt.imread() 함수는 임의의 이미지 파일을 넘파이 어레이 파일로 읽어서 리턴한다.


In [11]:
img_raccoon.dtype


Out[11]:
dtype('float32')

In [12]:
plt.imshow(img_raccoon)


Out[12]:
<matplotlib.image.AxesImage at 0x1811c210b8>

이미지 픽셀 정보와 3차원 어레이

img, img_raccoon 변수에 저장된 어레이의 모양(shape)은 다음과 같다.


In [13]:
img_raccoon.shape


Out[13]:
(768, 1024, 3)

즉, 3차원 어레이이다. 3차원 어레이는 일반적으로 상상하기가 매우 어렵다. 하지만 사진 데이터의 경우에는 다음처럼 이해하면 매우 쉽다.

  • 먼저, 해당 사진에 세로(row)를 균등하게 768개로 쪼개고, 가로(column)를 1024개로 쪼갠다. 그러면 768 x 1024 크기의 격자 모양으로 사진을 쪼개었다고 생각할 수 있다.

  • 이제 각각의 격자 칸에 픽셀(화소) 정보가 저장되며, 저장된 정보에 따라 다양한 색들이 보여진다. 픽셀 정보는 RGB 정보를 담고 있으며, R은 빨강색(Red), G는 녹색(Green), B는 파랑색(Blue)을 대표한다.

  • 각 칸에 들어 있는 픽셀 정보는 길이가 3 또는 4인 어레이로 표현되어 있으며, 위 너구리 사진은 아래 모양의 길이가 3인 픽셀 정보를 사용한다.

      [ 0.4627451 ,  0.60392159,  0.36078432]
    
    

    세 개 항목은 각각 R, G, B에 대한 정보이다. 만약에 아래 모양처럼 픽셀 정보가 길이가 4인 경우에는 마지막 항목은 색의 투명도를 나타낸다.

      [ 0.4627451 ,  0.60392159,  0.36078432, 1.0 ]

썸네일 이미지 만들기

웹에서 작동하는 갤러리 같은 애플리케이션를 사용하다 보면 이미지의 썸네일을 많이 접하게 된다. 여기서 썸네일을 만들기 위해 이미지를 어떻게 수정하는지 알아본다.

먼저, 어떤 이미지의 썸네일은 기존 이미지의 화소수, 즉 화소의 숫자를 조정해서 만들며, 일반적으로 매우 화소수를 크게 줄인다. 그런데 화소수를 줄이면서 전체 이미지를 유지하기 위해서는 없어진 화소들을 색 보간법을 이용하여 픽셀 정보를 보정해야 한다.

일반적으로 아래 과정을 따른다.

  • 사진 크기 조정: 사진 크기를 조정하기 위해 Pillow 팩키지에 포함된 Image 모듈의 open() 함수를 이용한다.

  • 색 보간법 사용: plt.imshow() 함수의 키워드 인자 중에서 interpolation 인자를 활용한다.

색 보정 미활용 경우

먼저 색을 보정하지 않을 경우를 살펴본다. 그러면 마치 모자이크처리가 된 것처럼 보일 것이다.

아래 코드에 사용딘 Image.open() 함수의 리턴값의 자료형은 이미지를 다루는 클래스이다. (여기서는 클래스 이름이 중요하지 않다.) 그리고 해당 클래스의 썸네일(thumnail) 메소드를 활용하여 이미지의 화소수를 조정하는 방식을 보여준다.

thumnail 메소드에 사용된 두 개의 인자는 다음과 같다.

  • 첫째 인자: 화소수 지정 (세로 x 가로)
  • 둘째 인자: Image.ANTIALIAS는 그림을 처리하는 다양한 방법 중 하나를 나타낸다. 여기서는 자세히 다루지 않는다.

In [14]:
from PIL import Image

img_raccoon_small = Image.open('images/raccoon.png')
resized = img_raccoon_small.thumbnail((77, 103), Image.ANTIALIAS)
imgplot = plt.imshow(img_raccoon_small)


위 그림은 픽셀수를 줄였음에도 불구하고 원본 그림과 동일한 크기로 확대해서 보인 결과물이다. 따라서 모자이크처리를 한 것처럼 흐리게 보인다. 조정된 사진의 실제 크기는 다음과 같다.


In [15]:
img_raccoon_small


Out[15]:

색 보정 활용 활용

색을 보정하는 색 보간법을 활용하려면 plt.imshow() 함수의 키워드 인자인 interpolation 인자를 활용한다. interpolation 키워드 인자값으로 nearest, bicubic 등이 있으며 bicubic이 가장 선호되는 옵션이다.


In [16]:
imgplot = plt.imshow(img_raccoon_small, interpolation="bicubic")


연습문제

연습

색 보간법에 사용되는 interpolation 키워드의 인자값들 모두 확인해 보아라.