In [1]:
%pylab inline
inline
옵션을 사용하면 ipython notebook 자체에 그랙픽이 보여진다.
사용하지 않을 경우 독립된 창이 사용된다.
ipython에서 2D 그래프를 그리려면 matplotlib.pyplot
모듈을 불러들여야 한다.
별칭은 plt
로 사용하는 게 관례이다.
In [2]:
import matplotlib.pyplot as plt
In [3]:
x = np.linspace(0, 3, 50)
x
Out[3]:
이번에는 구간 [0, 9]에서 50개을 점을 균등하게 뽑아서 어레이를 만든다.
In [4]:
y = np.linspace(0, 9, 50)
y
Out[4]:
이제 x
어레이에 할당된 점들을 x 축의 좌표값으로,
그리고 y
어레이에 할당된 점들을 y 축의 좌표값으로
각각 갖는 (x, y) 좌표들로 이루어진 그래프를 그려보도록 한다.
즉, 다음의 값들로 이루어진 점들의 그래프를 그려야 한다.
$$\{\, (x[i],\, y[i]) \,\,\,|\,\,\, i \in range(20) \,\}$$
In [5]:
plt.plot(x, y, 'o')
Out[5]:
plt.plot
함수의 세번 째 인자는 옵션으로 사용되며, 'o' 옵션은 점으로 좌표를 찍으라는 것을 나타낸다. 세번 째 인자를 사용하지 않으면 각 점을 선으로 이어서 보여준다.
In [6]:
plt.plot(x, y)
Out[6]:
두 경우를 합쳐서 그래프를 그려서 그래프가 어떻게 그려졌는지 쉽게 확인할 수도 있다.
In [7]:
plt.plot(x, y)
plt.plot(x, y, 'o')
Out[7]:
In [8]:
x = np.linspace(-1, 1, 20)
x
Out[8]:
이제 숫자를 제곱해서 리턴하는 함수의 이름을 정한다.
In [9]:
def square(x):
return x**2
numpy에서는 함수에 어레이를 적용할 경우 각 항목별로 적용한다.
즉, map
함수의 기능이 포함되어 있다.
In [10]:
y = square(x) # map(square, x) 와 동일한 기능을 수행한다.
y
Out[10]:
이제 x
와 y
이 좌표값들로 이루어진 그래프를 그릴 수 있다.
20개의 점을 예쁘게 곡선으로 연결해서 포물선을 그린다.
plt.plot
함수가 각 점을 통과하는 그래를 적당히 알아서 찾아준다.
이를 위해 보간법(interpolation) 기술을 활용한다.
보간법에 대해서는 추후에 다시 다룰 예정이다.
In [11]:
plt.plot(x, y)
Out[11]:
In [12]:
from IPython.display import Image
Image(filename='images/grasshopper.png', width=340)
Out[12]:
위 흑백 사진은 사람 눈에 보기 좋게 처리해서 보여지는 것이다. 반면에 컴퓨터에 저장될 때는 단순한 수치 데이터로 저장된다. 일상적으로 언급되는 픽셀(pixel)들의 집합으로 처리된다.
pixel의 어원은 그림을 나타내는 picture의 줄임말 'pix'와 구성요소를 의미하는 element의 줄임날 'el'을 합쳐서 만들어졌다. 픽셀을 우리말로 화소(畵素, 그림의 원소)라고 부르는 이유가 이때문이다.
하나의 픽셀은 보통 세 개 또는 네 개의 값들로 이루어진다. 각각의 픽셀값은 RGB color model을 구현하는 데에 필요한 세 개의 값으로 이루어지며 각각의 값은 red(빨강색), green(녹색), blue(파랑색) 색깔에 해당하는 숫자들이다. 따라서 RGB color model를 구성한다고 말한다. 경우에 따라 투명도를 나타내는 숫자가 네 번째 항목으로 추가되기도 한다. 이제 위 사진의 수치 데이터를 다음과 같이 확인해볼 수 있다.
위 사진의 데이터를 읽으려면 plt.imread
함수를 이용한다.
In [13]:
img = plt.imread('images/grasshopper.png')
img
Out[13]:
img
변수에 저장된 어레이의 모양(shape)은 다음과 같다.
In [14]:
img.shape
Out[14]:
즉, 3차원 어레이이다. 간단하게 설명한다면 다음과 같다.
읽어드린 정보를 이용하여 다시 이미지를 재생하려면 다음처럼 plt.imshow
함수를 이용하면 된다.
아래 그림에서 세로가 329개의 칸으로, 가로가 500개의 칸으로 구분되어 있음을 확인할 수 있다.
In [15]:
plt.imshow(img)
Out[15]:
앞서 본대로 이미지를 수치 데이터로 처리하면 (N1, N2, 4) 모양의 3차원 어레이가 된다. 즉, 세로에 N1개의 칸과, 가로에 N2개의 칸을 만든 후 생긴 격자모양의 각 칸에 들어갈 색깔의 R, G, B 및 투명도 정보가 길이가 4인 리스트 형식으로 표현된다.
그런데 이미지 색의 대비를 높이기 위해 수치데이터를 좀 더 단순화시켜서 볼 필요가 종종 있다. 그럴 때는 R, G, B의 정보 중에 하나만을 선택하여 사용하면 된다.
위 메뚜기 사진의 경우 R, G, B 정보가 각 화소에서 거의 비슷하다. 따라서 임의로 한 색깔, 즉 R(빨강색) 정보만을 이용해 본다. 그러기 위해서는 어레이 슬라이싱을 다음과 같이 사용한다.
img[:, :, 0]
어레이 슬라이싱은 리스트 슬라이싱을 일반화 시킨 것이다.
img
가 3차원 어레이이고, 1차원은 세로칸에 해당하고,
2차원은 가로칸에 해당하고,
3차운은 RGB 정보에 해당함을 다시 한 번 기억해야 한다.
따라서 빨강색(R) 정보만 끄집어 내려면, 가로와 세로는 건드리지 않으면서,
마지막 3차원에 해당하는 것은 R에 해당하는 첫 번째 값만 인덱싱으로 꺼내면 된다.
따라서 img[:, :, 0]
에서 첫째 :
은 세로 전체를,
두번 째 :
는 가로 전체를,
그리고 마지막 칸의 숫자 0
은 R의 정보만 인덱싱으로 꺼내는 것을 나타낸다.
따라서 다음이 성립한다.
In [44]: img.[:, :, 0].shape
Out[44]: (329, 500)
즉, "세로 329칸 x 가로 500칸" 의 격자모양의 각 칸에 빨강색 정보만을 갖고 있는 2차원 어레이가 생성되었다.
In [16]:
lum_img = img[:,:, 0]
lum_img
Out[16]:
In [17]:
lum_img.shape
Out[17]:
이제 lum_img
에 저장된 수치의 이미지를 확인해보면, 색 대비가 보다 명확함을
확인할 수 있다.
In [18]:
plt.imshow(lum_img)
Out[18]:
이와 같이 한 가지 색에 대한 정보만을 가진 이미지를 단일 채널(single-channel) 이미지, 그레이스케일(grayscale) 이미지, 또는 발광(luminosity) 이미지라 부른다. 스마트폰이나 컴퓨터에서 사용되는 사진조작 어플들이 위와 같은 기능을 이용하여 재밌는 사진을 연출해준다.
예를 들어, 그레이스케일 이미지를 좀 더 따뜻한 느낌으로 처리하려면 imshow
의 cmap
키워드 인자값을 다음과 같이 변경해 주면 된다.
color map 옵션을 정하는 cmap
키워드 인자값으로 사용될 수 색들은 매우 종류가 많다.
cmap
에 사용될 수 있는 인자값의 기본은 jet
이며,
hot
, gray
, spring
,
summber
, autumn
, winter
, spectral
등 다양하며,
아래 사이트에서 확인할 수 있다.
http://matplotlib.org/examples/color/colormaps_reference.html
In [19]:
plt.imshow(lum_img, cmap="hot")
Out[19]:
In [20]:
plt.imshow(lum_img, cmap="spectral")
Out[20]:
In [21]:
plt.imshow(lum_img, cmap="bone")
Out[21]:
plt.imshow
함수에는 cmap
이외에 다양한 키워드 인자들이 있으며 이미지를 섬세하게
변경하여 표현하는 데에 사용된다.
하지만 이 강의에서는 더 자세히는 다루지 않는다.
In [22]:
plt.imshow(lum_img)
plt.colorbar()
Out[22]:
In [23]:
lum_img_hist = lum_img.ravel()
lum_img.ravel()
의 총 길이는 329 * 500 = 164500
의 값과 동일하다.
In [24]:
lum_img_hist.shape
Out[24]:
이제 plt.hist
함수를 이용하여 히스토 그램을 그릴 수 있다.
plt.hist(lum_img_hist, bins=100, range=(0.0, 1.0), fc='k', ec='k')
range
키워드 인자는 구분하고자 하는 숫자들이 존재하는 구간을 값으로 갖는다.
위 그림에서 숫자들이 모두 0과 1 사이이기에 여기서는 (0.0, 1.0)
을 사용한다. bins
키워드 인자는 range
구간을 몇 개로 쪼갤 것인가를 정한다.
즉, 히스토그램에 사용될 막대들의 개수를 정한다.
숫자를 키울 수록 보다 세밀한 히스토그램을 얻게 된다.fc
키워드 인자는 히스토그램 막대들의 내부 색깔을 정한다. k
는 검정색을 나타낸다.
'k' 이외에 'r'(빨강색), 'y'(노랑색) 등 다양하게 색을 지정할 수 있다. ec
키워드 인자는 히스토그램 막대들의 모서리 색깔을 정한다. k
는 검정색을 나타낸다.
'k' 이외에 'r'(빨강색), 'y'(노랑색) 등 다양하게 색을 지정할 수 있다. plt.hist
의 리턴값은 튜플이다.
튜플의 첫째 항목은 각 구간에 나타나는 값들의 횟수를 담고 있는 1차원 어레이이며,
어레이의 길이는 bins
값이다.
튜플의 둘째 항목은 range
구간을 bins
값으로 균등하게 쪼갠 값들로 이루어진
1차원 어레이다. 역시 길이는 bins
값이다.
In [25]:
plt.hist(lum_img_hist, bins=100, range=(0.0, 1.0), fc='k', ec='k')
Out[25]:
위 히스토그램을 보면 0.2 이하와 0.5 이상의 값들은 그림에 별로 영향을 주지 않는 것으로
판단할 수 있다. 따라서 해당 [0.2, 0.5] 구간의 값들로만으로 그림을 확인하면
대비가 보다 강한 그림을 확인할 수 있다.
이를 위해 clim
값을 변경한다.
clim은 color limit의 줄임말이다.
아래 코드 설명:
plt.figure
함수는 그림을 보여주겠다고 선언하는 명령어임.2행과 6행: fig.add_subplot
함수는 보여줄 그림의 숫자와 배치도, 그리고 몇 번째 그림인지를 설명함.
인자로 사용된 (1, 2, 1)
과 (1, 2, 2)
에서 공통요소인 (1, 2)
은 1 x 2
행렬 형식으로
그림을 채우겠다. 즉, 두 장의 사진을 나란히 보여주겠다고 선언한 것임.
튜플의 마지막 값인 1
과 2
는 그림의 순서를 나타냄. 즉, 첫 번째, 두 번째 그림을 의미함.
따라서 네 장의 사진을 두 개씩 나란히 2줄로 보여주고 싶으면 (2, 2, n)
을 인자로 사용하면 된다.
n
은 1, ..., 4
값을 갖는다.
set_title
메소드는 각각의 그림에 소제목을 붙일 때 사용함.
set_clim
메소드는 특정 구간을 잘라서 사용할 때 이용함.
In [26]:
fig = plt.figure()
a=fig.add_subplot(1,2,1)
imgplot = plt.imshow(lum_img)
a.set_title('First')
plt.colorbar(ticks=[0.1,0.3,0.5,0.7], orientation ='horizontal')
a=fig.add_subplot(1,2,2)
imgplot = plt.imshow(lum_img)
imgplot.set_clim(0.3,0.7)
a.set_title('Second')
plt.colorbar(ticks=[0.1,0.3,0.5,0.7], orientation='horizontal')
Out[26]:
사진의 크기를 수정할 때 기본적으로 화소수를 줄인다. 그런데 화소수가 줄어들지만 전체 이미지는 유지해야 하기 때문에 줄어드는 화소들을 색 보간법을 이용하여 임의로 색 수치를 변경해야 한다.
사진 크기조정(resize)를 위해 Pillow 라이브러리의 Image
함수를 이용한다.
우선 색을 보간하지 않을 경우를 살펴본다. 그러면 마치 모자이크처리가 된 것처럼 보일 것이다.
아래 코드에서 thumnail
함수의 두 번째 인자로 사용된 Image.ANTIALIAS
는
키워드옵션 인자이며 그림을 처리하는 다양한 방법 중 하나이다.
여기서는 자세히 다루지 않는다.
In [27]:
from PIL import Image
img = Image.open('images/grasshopper.png')
resized = img.thumbnail((64, 64), Image.ANTIALIAS)
imgplot = plt.imshow(img)
위 그림은 픽셀수를 줄였음에도 불구하고 원본 그림과 동일한 크기로 확대해서 보인 결과물이다. 따라서 모자이크처리를 한 것처럼 흐리게 보인다.
이제 색 보간법을 활용해보자.
plt.imshow
함수의 키워드 인자인 interpolation
활용하면 된다.
interpolation
키워드 인자값으로 nearest
, bicubic
등이 있으며
bicubic
이 가장 선호되는 옵션이다.
In [28]:
imgplot = plt.imshow(img, interpolation="nearest")
In [29]:
imgplot = plt.imshow(img, interpolation="bicubic")
이미지와 관련해서 보다 많은 내용은 이후에 다룰 것이다.
In [30]:
image = np.random.rand(30, 30)
plt.imshow(image, cmap="gray")
plt.colorbar()
Out[30]: