Python

파이썬 이미지 처리 pillow(PIL) 설치 및 사용 예제 총정리

이미지 분석 및 처리를 쉽게 할 수 있는 라이브러리(Python Imaging Library : PIL)가 있습니다. 바로 pillow모듈입니다. 다양한 이미지 파일 형식을 지원하며, 강력한 이미지 처리와 그래픽 기능을 제공하는 이미지프로세싱 라이브러리의 한 종류입니다.

주요기능

PIL 이미지 작업을 위한 표준 절차를 제공하고 있으며, 다음과 같은 것이있다.(출처 :위키백과)

  • 픽셀 단위의 조작
  • 마스킹 및 투명도 제어
  • 흐림, 윤곽 보정 다듬어 윤곽 검출 등의 이미지 필터
  • 선명하게, 밝기 보정, 명암 보정, 색 보정 등의 화상 조정
  • 이미지에 텍스트 추가
  • 기타 여러가지

설치하는 방법

명령프롬프트(cmd)창을 열고 pip install pillow 명령어를 실행합니다. 파이참 IDE를 사용중이시면 툴 하단의 터미널(Terminal)창에서 명령어를 실행합니다.

설치과정 보기
C:\python\Workspace>pip install pillow
Collecting pillow
    Downloading Pillow-8.0.1-cp39-cp39-win_amd64.whl (2.1 MB)
      | ██████████████████| 2.1 MB 6.4 MB/s
Installing collected packages: pillow
Successfully installed pillow-8.0.1

C:\python\Workspace>

다른 모듈들과 다르게 모듈 설치는 pillow로 하였지만, import 하는 방법은 상당히 다르네요.

이미지 처리를 하기 위해서는 from PIL import Image 와 같이 모듈을 임포트해야 사용가능합니다.

이미지 불러오기 (이미지 출력)

Image클래스의 Image.open()함수를 사용하여 이미지를 쉽게 불러올 수 있습니다. 이미지를 불러온 후 변수의 타입을 확인해보면 <class ‘PIL.JpegImagePlugin.JpegImageFile’> 임을 알 수 있네요. bitmap 자료형을 예상했는데 아닙니다. show()함수를 사용하면 윈도우의 기본 이미지 보는 프로그램이 자동으로 실행되고 아래와 같이 볼 수 있네요.

from PIL import Image

img = Image.open("C:/Users/ilike/Pictures/IU_400x400.jpg")
print(type(img))

img.show()

이미지 속성 확인 방법

이미지의 크기, 이름, 모드, 가로 세로 길이 등의 정보를 확인 할 수 있습니다.

from PIL import Image 

img = Image.open("C:/Users/ilike/Pictures/IU_400x400.jpg")
print(f'이미지 파일 이름 : {img.filename}')
print(f'이미지 파일형식(format) : {img.format}')
print(f'이미지 용량(size) : {img.size}')
print(f'이미지 색상모드 : {img.mode}')
print(f'이미지 width : {img.width}')
print(f'이미지 height : {img.height}') 

실행결과
이미지 파일 이름 : C:/Users/ilike/Pictures/IU_400x400.jpg
이미지 파일형식(format) : JPEG
이미지 용량(size) : (400, 400)
이미지 색상모드 : RGB
이미지 width : 400
이미지 height : 400

이미지 크기 변경하기

이미지의 크기는 resize()함수를 사용하여 변경합니다. 인자값은 튜플자료형입니다.

from PIL import Image

img = Image.open("C:/Users/ilike/Pictures/IU_400x400.jpg")

resize_img = img.resize((800, 800))
resize_img.save("C:/Users/ilike/Pictures/IU_800x800.jpg")

원본이미지의 절반(50%) 사이즈로 변경

from PIL import Image

img = Image.open("C:/Users/ilike/Pictures/IU_400x400.jpg")
(width, height) = (img.width // 2, img.height // 2)

resize_img = img.resize((width, height))
resize_img.save("C:/Users/ilike/Pictures/IU_200x200.jpg")

이미지 사이즈를 변경할때, 내부적으로 리샘플링을 합니다. 리샘플링 옵션으로 여러가지를 지원합니다. 

resize_img = img.resize((800, 800), Image.HAMMING)
필터내용
PIL.Image.NEAREST입력 이미지에서 가장 가까운 픽셀 하나를 선택합니다. 다른 모든 입력 픽셀은 무시합니다.
PIL.Image.BOX소스 이미지의 각 픽셀은 동일한 가중치를 가진 대상 이미지의 한 픽셀에 기여합니다. 업 스케일링의 경우 NEAREST. 이 필터는 resize() 및 thumbnail()메서드 에서만 사용할 수 있습니다 .
PIL.Image.BILINEAR크기 조정을 위해 출력 값에 기여할 수있는 모든 픽셀에서 선형 보간법을 사용하여 출력 픽셀 값을 계산합니다. 다른 변환의 경우 입력 이미지의 2×2 환경에 대한 선형 보간이 사용됩니다.
PIL.Image.HAMMINGBILINEAR보다 선명한 이미지를 생성합니다. BOX처럼 로컬 수준의 전위가 없습니다. 이 필터는 resize() 및 thumbnail()메서드 에서만 사용할 수 있습니다 .
PIL.Image.BICUBI크기 조정을 위해 출력 값에 기여할 수 있는 모든 픽셀에서 삼차 보간법을 사용하여 출력 픽셀 값을 계산합니다. 다른 변환의 경우 입력 이미지의 4×4 환경에 대한 큐빅 보간이 사용됩니다.
PIL.Image.LANCZOS출력 값에 기여할 수있는 모든 픽셀에서 고품질 Lanczos 필터 (잘린 sinc)를 사용하여 출력 픽셀 값을 계산합니다. 이 필터는 resize() 및 thumbnail()메서드 에서만 사용할 수 있습니다 .

눈으로 식별은 잘 안되는 것 같습니다. 아래 필터 비교표를 참고하세요.

이미지 자르기(Crop)

이미지를 crop하는 방법은 crop()함수를 사용합니다.

crop함수의 인자 값은 4개이며 왼쪽, 위, 오른쪽, 아래 순으로 값을 대입합니다. 튜플 자료형입니다.

crop((left, upper, right, lower))

from PIL import Image

img = Image.open("C:/Users/ilike/Pictures/IU_400x400.jpg")
cropped_img = img.crop((100, 100, 200, 200))
cropped_img.show()


이미지 회전

Image 클래스의 rotate()함수를 사용하면 이미지를 원하는 각도만 큼 회전 할 수 있습니다.

from PIL import Image

img = Image.open("C:/Users/ilike/Pictures/IU_400x400.jpg")
img.rotate(45).show()

이미지 상하, 좌우 대칭(Flip)

transpose()함수를 사용하여 대칭 작업이 가능합니다. 2개의 옵션을 제공합니다.

Image.FLIP_LEFT_RIGHT 필터는 좌우 대칭처리를 할때 ,  Image.FLIP_TOP_BOTTOM 필터는 이미지를 뒤집을 때 (상하 대칭) 사용합니다. 

from PIL import Image

img = Image.open("C:/Users/ilike/Pictures/IU_400x400.jpg")
img.show()

flip_img = img.transpose(Image.FLIP_LEFT_RIGHT)
flip_img.show()

flip_img2 = img.transpose(Image.FLIP_TOP_BOTTOM)
flip_img2.show()

왼쪽부터 원본이미지, 좌우대칭, 상하 반전(뒤집기) 이미지입니다.

transpose()함수를 사용하여 이미지 회전도 가능합니다. 단 3개의 고정된 각도만 제공합니다. Image.ROTATE_90 은 좌측으로 90도 회전시킵니다. Image.ROTATE_180은 좌측으로 180도 회전시키며, Image.ROTATE_270은 좌측으로 270도 회전 시킵니다. 이것이 의미하는 바는 이미지를 90도 단위로 뒤집기 또는 회전을 의미합니다.

from PIL import Image

img = Image.open("C:/Users/ilike/Pictures/IU_400x400.jpg")
img.show()

flip_img = img.transpose(Image.ROTATE_90)
flip_img.show()

flip_img2 = img.transpose(Image.ROTATE_180)
flip_img2.show()

flip_img3 = img.transpose(Image.ROTATE_270)
flip_img3.show()

왼쪽부터, 원본사진, 90도 회전, 180도 회전, 270도 회전된 이미지 입니다.

이미지 필터링

ImageFilter모듈에 정의된 필터를 사용하여 Image.filter()함수에서 사용하여 이미지에 필터를 적용할 수 있습니다. 제공되는 필터는 다음과 같습니다.

  • BLUR
  • CONTOUR
  • DETAIL
  • EDGE_ENHANCE
  • EDGE_ENHANCE_MORE
  • EMBOSS
  • FIND_EDGES
  • SHARPEN
  • SMOOTH
  • SMOOTH_MORE

필터를 사용하기 위해서는 ImageFilter모듈을 임포트합니다. 아래 스크립트는 이미지를 흐리게(Blur) 처리한 예제입니다. DSLR 카메라로 사진을 찍을 때 수동으로 초점을 흐려서 찍은 효과가 나타납니다.  ImageFilter는 3개의 Blur함수를 제공합니다. 첫번째는 ImageFilter.BLUR입니다. 이 녀석은 고정된 값으로 Blur처리를 합니다. 개발자가 임의로 변경할 수 없어요. 하지만 ImageFiler.BoxBlur()함수와 ImageFilter.GaussianBlur()함수는 개발자가 임의의 값을 적용할 수 있습니다.

from PIL import Image
from PIL import ImageFilter

img = Image.open("C:/Users/ilike/Pictures/IU_400x400.jpg")
blur_img = img.filter(ImageFilter.BLUR)
blur_img2 = img.filter(ImageFilter.BoxBlur(10))
blur_img3 = img.filter(ImageFilter.GaussianBlur(10))

img.show()
blur_img.show()
blur_img2.show()
blur_img3.show()

왼쪽부터 원본, BLUR, BoxBlur, GaussianBlur로 처리한 이미지 입니다.

하나씩 테스트 해보기에는 필터가 많아요. for문을 사용하여 모든 필터 효과를 살펴봅니다.

from PIL import Image
from PIL import ImageFilter

img = Image.open("C:/Users/ilike/Pictures/IU_400x400.jpg")

filter_list = [ImageFilter.BLUR, ImageFilter.CONTOUR, ImageFilter.DETAIL,
               ImageFilter.EDGE_ENHANCE, ImageFilter.EDGE_ENHANCE_MORE, ImageFilter.EMBOSS, ImageFilter.FIND_EDGES,
               ImageFilter.SHARPEN, ImageFilter.SMOOTH, ImageFilter.SMOOTH_MORE]

for i in range(len(filter_list)):
    filter_img = img.filter(filter_list[i])
    #filter_img.show()
    filter_img.save("C:/Users/ilike/Pictures/filter_img_{}.jpg".format(i))    

필터를 적용하여 새로운 이미지 파일로 모두 저장하였습니다.

이미지 합치기

여러개의 이미지를 불러와서 합치는 방법에 대해 알아봅니다.  여러개의 이미지를 합치기 위해서는 paste()함수를 사용합니다. 첫번째 이미지에 두번째 이미지를 붙이는 개념은 아닙니다.  3개의 이미지를 합쳐볼 건데요.  이미지를 합치기(붙이기)를 할 경우 new()함수를 사용하여 새로운 이미지를 생성해야합니다. 그리고 새로운 이미지에 여러개의 이미지를 붙여 넣을 수 있습니다. new()함수의 첫번째 인자는 mode입니다. 어떤 모드를 적용할지 설정하고, 두번째 인자는 이미지 사이즈입니다. 그리고 마지막으로 3번째 인자는 새로 만든 이미지의 백그라운드 색상을 지정합니다. 3번째 인자는 생략가능합니다.

from PIL import Image 

img = Image.open("C:/Users/ilike/Pictures/IU_400x400.jpg")
img2 = Image.open("C:/Users/ilike/Pictures/xbox_logo.png")
img3 = Image.open("C:/Users/ilike/Pictures/python_logo.png")


print(img.size)
print(img2.size)
print(img3.size)
new_img = Image.new("RGB", (830, 800), 300000)
new_img.paste(img, (10, 10))
new_img.paste(img2, (img.width + 10, 10))
new_img.paste(img3, (10, img.height + 10))

new_img.show()

이미지 저장

Image.save()함수를 사용하여 불러온 이미지를 저장할 수 있습니다. 45도 회전한 이미지를 png 확장자를 주고 저장하였습니다. 혹시나 저장하면서 이미지 정보를 new_img 변수에 담아주나 궁금하여 변수 타입을 찍어보았으나 NoneType이네요. 이미지를 저장할 경우 변수 없이 사용하시면 됩니다.

from PIL import Image

img = Image.open("C:/Users/ilike/Pictures/IU_400x400.jpg")
rotate_img = img.rotate(45)
rotate_img.save("C:/Users/ilike/Pictures/blur_IU.png")


#new_img = rotate_img.save("C:/Users/ilike/Pictures/blur_IU.png")
#print(type(new_img))

이미지 썸네일(thumbnail) 쉽게 만드는 방법(Create thumbnails)

thumbnail()함수를 사용하여 썸네일을 쉽게 만들 수 있습니다. 사이즈 인자 값으로 튜플(tuple) 자료형으로 받아서 처리합니다. img.thumbnail(40, 40) 처럼 정수(int)를 입력하면 TypeError:’int’ object is not iterable오류가 발생됩니다.

from PIL import Image
size = 40, 40  #튜플자료형으로 괄호 생략 가능(#<class 'tuple'>)

img = Image.open("C:/Users/ilike/Pictures/IU_400x400.jpg")
img.thumbnail(size)

img.save("C:/Users/ilike/Pictures/IU_thumbnail_40x40.jpg")
thumbnail_img = Image.open("C:/Users/ilike/Pictures/IU_thumbnail_40x40.jpg")
thumbnail_img.show()

현재 디렉토리의 모든 JPEG 이미지에 대해 썸네일 만드는 방법

glob모듈을 임포트한 후 for문을 사용하시면 간단하게 처리됩니다. 물론 파일에 접근해야하니 , os모듈도 필요합니다.

import glob
import os

from PIL import Image

size = (128, 128)

count = 0
for infile in glob.glob("C:/Users/ilike/Pictures/*.jpg"):
    file, ext = os.path.splitext(infile)
    im = Image.open(infile)
    im.thumbnail(size)
    im.save(file + ".thumbnail", "JPEG")
    count += 1
    
print("썸내일로 생성한 이미지 개수 :", count)

이미지를 바이트배열(bytearray)로 변환하는 방법

io.BytesIO()를 사용하여 save()함수에서 저장위치를 로컬이 아닌 io.BytesIO() 변수에 담은후 getvalue()함수를 사용하여 바이트 어레이 값을 가져올 수 있습니다.

from PIL import Image
import io

img = Image.open("C:/Users/ilike/Pictures/IU_400x400.jpg")
bytearr = io.BytesIO()
img.save(bytearr, format="JPEG")
print(bytearr.getvalue())

함수로도 만들어서 상요하면 편리하겠죠?

from PIL import Image
import io


def image_to_byte_array(image):
    imgbytearr = io.BytesIO()
    image.save(imgbytearr, format=image.format)
    imgbytearr = imgbytearr.getvalue()
    return imgbytearr

img = Image.open("C:/Users/ilike/Pictures/IU_400x400.jpg")

print(image_to_byte_array(img))

이미지를 넘파이 배열로 변환하는 방법 

numpy.array()함수를 사용하여 이미지를 배열 객체로 반환할 수 있습니다.

from PIL import Image
import numpy as np
img = Image.open("C:/Users/ilike/Pictures/IU_400x400.jpg")

numpy_img = np.array(img)
print(type(numpy_img))
print(numpy_img)


#실행결과
<class 'numpy.ndarray'>
[[[246 246 248]
  [246 246 248]
  [246 246 248]
  ...
  [242 241 246]
  [242 241 246]
  [242 241 246]]
  .....이하생략

넘파이(numpy) 배열을 이미지로 변환하는 방법

from PIL import Image
import numpy as np
img = Image.open("C:/Users/ilike/Pictures/IU_400x400.jpg")

#numpy_array = np.array(img, dtype="uint8")
numpy_array = np.array(img)
   
image2 = Image.fromarray(numpy_array, 'RGB')
image2.show() 

이미지를 픽셀 값으로 변환하는 방법

from PIL import Image
import numpy as np
img = Image.open("C:/Users/ilike/Pictures/IU_400x400.jpg")

pixel_list = list(img.getdata())
print(pixel_list)
np.savetxt("pixel_type_data.txt", pixel_list, fmt='%d', delimiter=" ")

이미지의 특정 픽셀의 RGB 색상 구하는 방법

convert()함수를 사용하여 RGB 데이터를 가져옵니다. 그런 다음, getpixel()함수를 사용하여 특정 픽셀의  x, y  좌표값을 지정하면 픽셀값을 튜플자료형으로 반환합니다.

from PIL import Image
img = Image.open("C:/Users/ilike/Pictures/IU_400x400.jpg")

rgb_img = img.convert("RGB")

#지정한 좌표값의 픽셀값 튜플자료형으로 반환
tuple_item = rgb_img.getpixel((1, 100))
print(tuple_item) 

r, g, b = tuple_item
print(r)
print(g)
print(b)





#실행결과
(244, 245, 249)
244
245
249

[REFERENCE]

pillow.readthedocs.io/en/stable/installation.htmlInstallation — Pillow (PIL Fork) 8.0.1 documentationBuild flags: –disable-zlib, –disable-jpeg, –disable-tiff, –disable-freetype, –disable-lcms, –disable-webp, –disable-webpmux, –disable-jpeg2000, –disable-imagequant, –disable-xcb. Disable building the corresponding feature even if the developmentpillow.readthedocs.io

pillow.readthedocs.io/en/stable/reference/Image.htmlImage Module — Pillow (PIL Fork) 8.0.1 documentationAttaches a palette to this image. The image must be a “P”, “PA”, “L” or “LA” image, and the palette sequence must contain 768 integer values, where each group of three values represent the red, green, and blue values for the corresponding ppillow.readthedocs.io

pillow.readthedocs.io/en/stable/reference/ImageFilter.html

stackoverflow.com/questions/33101935/convert-pil-image-to-byte-array

stackoverrun.com/ko/q/11936598

아이유 사진 출처 : twitter.com/IUsFairyTale

Leave a Reply

error: Content is protected !!