본문 바로가기

학습컨텐츠/이미지프로세싱

이미지프로세싱 시작하기 - (4) 파이썬 이미징 라이브러리 PIL의 사용

  PIL(Python Imaging Library)은 파이썬을 이용해서 쉽게 이미지 프로세싱을 할 수 있게 주는 라이브러리이다. PIL은 이미지 프로세싱에 관련된 다양한 모듈을 제공하고 있으나 여기서는 이미지 파일 열기나 생성하기, 저장하기 등 가장 기본적인 함수들만 알아보기로 한다. PIL의 핵심이라고 할 수 있는 이미지 프로세싱 기능들은 그것을 직접 구현할 것이기 때문에 미리 다루지 않는 것으로 한다. PIL에 대한 자세한 문서가 필요하면 PIL의 공식 Documentation 사이트(http://www.pythonware.com/library/pil/handbook/)를 이용하면 된다.


Image.new(mode, size) -> image
Image.new(mode, size, color) -> image

이 함수는 주어진 형식의 새로운 이미지를 생성한다. mode에는 "RGB", "CMYK", "L"(흑백 모드) 등이 사용될 수 있다. size에는 가로, 세로 크기가 정수로 주어진 튜플이 주어지며, color는 RGB 모드의 경우 0~255의 값을 가지는 R, G, B 성분으로 이루어진 튜플이 전달된다. color 인수가 주어지지 않으면 검정 바탕의 이미지가 생성되고, color 인수가 주어지면 주어진 색을 바탕색으로 하는 이미지가 생성된다. 리턴값으로는 image 객체의 인스턴스가 주어진다.

(예) 256x256사이즈의 파란 바탕의 이미지를 생성하는 코드

>>> import Image
>>> im=Image.new("RGB",(256,256),(102,153,255))
>>> im
<Image.Image instance at 0x01A345F8>

im.load() -> PixelAccess

Lazy Operation으로 인해 아직 이미지를 로드하지 않았다면 강제로 연다.

PixelAccess 클래스의 인스턴스를 반환하는데, 이것을 통해서 이미지의 각 픽셀에 접근할 수 있다. PixelAccess는 튜플의 2차원 배열처럼 다룰 수 있고, 튜플의 길이는 각 모드에 따라 결정된다.(RGB는 3개, CMYK는 4개, L은 1개)

(예) 이미지의 첫번째 픽셀을 흰색으로 바꾸는 코드

pix=im.load()
pix[0,0]=(255,255,255)

im.size

이미지의 사이즈를 읽을 수 있다. 가로, 세로 크기가 포함된 정수 튜플이다.

Image.eval(image,function) -> image

이미지의 각 픽셀에 function으로 주어진 함수를 적용한 이미지를 반환한다. function은 정수를 인자로 받아 정수를 반환하는 함수이고, RGB이미지처럼 image가 여러 성분으로 되어 있는 경우에는 각 성분에 함수를 적용시킨다. PixelAccess 객체를 이용해서 직접 값을 바꾸는것보다 빠르다.

(예) 이미지를 반전시키는 코드

im=Image.eval(im, lambda x : 256 – x)

ImageTk.PhotoImage(image) -> PhotoImage

image를 Tkinter를 이용한 GUI프로그램에서 사용가능한 PhotoImage 객체로 만들어준다.

(예) cat.bmp파일을 화면에 표시하는 Tkinter 프로그램

from Tkinter import *
import Image, ImageTk

root=Tk()
im=ImageTk.PhotoImage(Image.open("cat.bmp"))
label=Label()
label.image=im
Label.__init__(label,root,image=label.image,bd=0)
label.pack()
root.mainloop();

im.convert(mode) -> image

im을 다른 모드 변환한 이미지를 반환한다. 사용할 수 있는 모드로는 RGB, CMYK, L(256단계 흑백 이미지), 1(단색 이미지) 등이 있다.

(예) cat.bmp를 흑백으로 변환하여 graycat.bmp로 저장하는 코드

im=Image.open("cat.bmp")
im.convert("L").save("graycat.bmp")


  지금까지 소개한 함수들만을 이용해서도 충분히 이미지를 열거나 생성해서 이미지프로세싱을 할 수 있다. 다음 프로그램은 Tkinter를 그림 파일을 열고 색 반전 기능을 수행할 수 있도록 한 프로그램이다. Tkinter나 class사용에 익숙하지 않은 경우 관련 학습컨텐츠를 참고하도록 한다.

  아래 예제의 첫 줄은 소스 파일이 cp949인코딩으로 작성되었음을 뜻한다. 이것은 한글 윈도우의 기본 인코딩 방식이므로 소스를 복사해서 메모장으로 별다른 설정 없이 저장하면 실행이 될 것이다.


# -*- coding: cp949 -*-
# filename : paint.pyw
# 간단한 이미지 프로세싱 프로그램

from Tkinter import *
import tkFileDialog, tkMessageBox
import Image, ImageTk

class App:
        def __init__(self):
                self.root=Tk()
                self.menu=Menu(self.root)
                self.root.config(menu=self.menu);
                self.label=Label(self.root, text="", width=50, height=20)
                self.label.pack()

                self.filemenu=Menu(self.menu)
                self.menu.add_cascade(label=u"파일", menu=self.filemenu)
                self.filemenu.add_command(label=u"열기", command=self.OpenFile, accelerator="Ctrl+O")
                self.filemenu.add_separator()
                self.filemenu.add_command(label=u"종료", command=self.Quit, accelerator="Ctrl+Q")

                self.editmenu=Menu(self.menu)
                self.menu.add_cascade(label=u"편집", menu=self.editmenu)
                self.editmenu.add_command(label=u"색 반전", command=self.Inverse, accelerator="Ctrl+I")

                self.root.bind("<Control-o>",self.OpenFile)
                self.root.bind("<Control-q>",self.Quit)
                self.root.bind("<Control-i>",self.Inverse)
                self.root.bind("<Escape>",self.Quit)
                self.root.mainloop()

        def OpenFile(self,event=None):
                self.filename=tkFileDialog.askopenfilename()
                if(self.filename==""):
                        return
                try:
                        self.image=Image.open(self.filename)
                except:
                        tkMessageBox.showerror(u"오류 !","파일 열기에 실패했습니다")
                else:
                        self.pixel=self.image.load()
                        self.label.image=ImageTk.PhotoImage(self.image)
                        Label.__init__(self.label,self.root,image=self.label.image,bd=0)
                        self.label.pack()

        def Quit(self,event=None):
                self.root.destroy()

        def Inverse(self,event=None):
                if(self.filename==""):
                        return
                self.image=Image.eval(self.image,lambda x:256-x)
                self.label.image=ImageTk.PhotoImage(self.image)
                Label.__init__(self.label,self.root,image=self.label.image,bd=0)
                self.label.pack()

App();


이 소스코드가 잘 이해된다면 여러분은 이미지프로세싱 프로그래밍을 시작할 준비가 완료된 것이다. 각자 pyw파일로 저장하여 실행해보고 소스를 분석해보도록 하자.




[목차] 이미지프로세싱 - 시작
[이전] 이미지프로세싱 시작하기 - (3) 컬러 모델
[다음] 픽셀 기반 처리 - (1) 밝기/명암대비 조절