Skip to content

Instantly share code, notes, and snippets.

@yunwoong7
Last active June 9, 2024 16:34
Show Gist options
  • Save yunwoong7/e61e9abb419f35d9ade8f95b3cc3e696 to your computer and use it in GitHub Desktop.
Save yunwoong7/e61e9abb419f35d9ade8f95b3cc3e696 to your computer and use it in GitHub Desktop.
Python Imaging Library(PIL) - Pillow 정리

Pillow

Python Imaging Library(PIL)은 파이썬 인터프리터에 다양한 이미지 파일 형식을 지원하고 강력한 이미지 처리와 그래픽 기능을 제공하는 Open Source Library 입니다.
줄여서 PIL 이라고 부릅니다. 2009년 9월 릴리즈 되었으며 파이썬 버전 1.5 ~ 2.7까지 지원합니다. PIL의 개발은 2011년에 중단되었으며 후속으로 Pillow라는 후속 프로젝트가
진행되어 파이서 3.x 버전을 지원하고 있습니다.

설치

pip를 통해 설치를 진행합니다.

pip install Pillow

Pillow는 이미 유명한 Python 이미지 분석 라이브러리입니다. resize, scale 등 다양한 작업이 가능합니다.
가장 좋은점은 Jupyter Notebook에서 이미지를 바로 확인 할 수 있어서 변경된 이미지 확인이 매우 쉽습니다.

지원하는 이미지 형식

PPM , PNG , JPEG , GIF , TIFF , BMP 등의 이미지 형식을 지원 하며 지원하지 않는 파일 형식은 라이브러리를 확장해서 새로운 파일 디코더를 만드는 것이 가능합니다.

기능

이미지 처리를 위해 아래와 같은 기능을 제공합니다.

  • 픽셀 단위 조직
  • 마스킹 및 투명도 제어
  • 흐림, 윤곽 보정, 윤곽 검출 등의 이미지 필터
  • 선명도 조절, 밝기 보정, 명암 보정, 색 보정 등의 화상 조정
  • 이미지에 텍스트 추가
  • 기타
import os
from PIL import Image

result_dir = 'result'

# Make Directory
if not os.path.exists(result_dir):
    os.makedirs(result_dir)

1. 이미지 열기

pil_image = Image.open('images/test_image/test_image.jpg')

show() 함수를 사용하면 윈도우에 설정된 이미지 기본 프로그램으로 자동 실행됩니다.

pil_image.show()

2. 이미지 속성

print('이미지 파일명 : {}'.format(pil_image.filename))
print('이미지 파일형식 : {}'.format(pil_image.format))
print('이미지 사이즈 : {}'.format(pil_image.size))
print('이미지 색상모드 : {}'.format(pil_image.mode))
print('이미지 Width : {}'.format(pil_image.width))
print('이미지 Height : {}'.format(pil_image.height))

이미지 파일명 : images/test_image/test_image.jpg 이미지 파일형식 : JPEG 이미지 사이즈 : (1024, 1028) 이미지 색상모드 : RGB 이미지 Width : 1024 이미지 Height : 1028

3. 이미지 크기 변경

# 크기를 1/6 size로 변경
pil_resize_image = pil_image.resize((int(pil_image.size[0]/6), int(pil_image.size[1]/6)))
pil_resize_image

4. 이미지 회전

# 180도 회전
pil_rotate_image = pil_resize_image.rotate(180)
pil_rotate_image

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

# 좌우대칭
pil_resize_image.transpose(Image.FLIP_LEFT_RIGHT)

# 상하반전
pil_resize_image.transpose(Image.FLIP_TOP_BOTTOM)

# 고정된 각도로 회전(90, 180, 270)
pil_resize_image.transpose(Image.ROTATE_90)

6. 이미지 자르기(Crop)

crop함수의 인자 값은 x1, y1, x2, y2 이며, 튜플 자료형입니다.

cropped_image = pil_image.crop((480, 520, 580, 580))
cropped_image

7. Draw Box

이미지 위에 원하는 좌표의 박스를 그릴 경우 ImageDraw.Draw.rectangle 함수를 사용합니다.

from PIL import Image, ImageDraw

pil_image = Image.open('images/test_image/test_image.jpg')
pil_resize_image = pil_image.resize((int(pil_image.size[0]/6), int(pil_image.size[1]/6)))

draw = ImageDraw.Draw(pil_resize_image)

# x1, y1, x2, y2
draw.rectangle([75, 80, 100, 100], outline="green")
pil_resize_image

8. 이미지 필터링

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

  • BLUR
  • CONTOUR
  • DETAIL
  • EDGE_ENHANCE
  • EDGE_ENHANCE_MORE
  • EMBOSS
  • FIND_EDGES
  • SHARPEN
  • SMOOTH
  • SMOOTH_MORE
from PIL import ImageFilter
pil_resize_image.filter(ImageFilter.BLUR)

pil_resize_image.filter(ImageFilter.BoxBlur(10))

pil_resize_image.filter(ImageFilter.GaussianBlur(10))

pil_resize_image.filter(ImageFilter.CONTOUR)

9. 이미지 합치기

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

pil_resize_image1 = pil_resize_image
pil_resize_image2 = pil_resize_image.filter(ImageFilter.CONTOUR)
new_image = Image.new("RGB", (370, 190), 600000)

new_image.paste(pil_resize_image1, (10, 10))
new_image.paste(pil_resize_image2, (pil_resize_image1.width + 20, 10))
new_image

10. 이미지 저장

Image.save()함수를 사용하여 이미지를 저장할 수 있습니다.

new_image.save(os.path.join(result_dir, "merge_image.jpg"))

11. 이미지 thumbnail

thumbnail()함수를 사용하여 썸네일을 쉽게 만들 수 있습니다.
사이즈 인자 값으로 튜플(tuple) 자료형으로 받아서 처리합니다.

pil_image = Image.open('images/test_image/image_1.jpg')
thumbnail_size = (40, 40)

pil_image.thumbnail(thumbnail_size)
pil_image.save(os.path.join(result_dir, "thumbnail_image.jpg"))
pil_image

12. 모든 Jpeg 이미지에 대해 thumbnail 생성

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

import glob
import os
from PIL import Image

thumbnail_size = (40, 40)
images = glob.glob("images/test_image/*.jpg")

for image_path in images:
    file, ext = os.path.splitext(image_path)
    image = Image.open(image_path)
    image.thumbnail(thumbnail_size)
    image.save(os.path.join(result_dir, os.path.basename(file)) + ".thumbnail", "JPEG")
    
print("Thumbnail image count : {}".format(len(images)))

Thumbnail image count : 2

13. 이미지를 바이트배열(bytearray)로 변환

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

from PIL import Image
import io

pil_image = Image.open('images/test_image/image_1.jpg')

byte_arr = io.BytesIO()
pil_image.save(byte_arr, format="JPEG")

byte_arr.getvalue()

b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x...

함수로 정의

def image_to_byte_array(image):
    '''
    PIL 이미지를 바이트배열(bytearray)로 변환
    :param image: (PIL.Image)
    :return: (bytes)
    '''
    byte_arr = io.BytesIO()
    pil_image.save(byte_arr, format=pil_image.format)
    image_byte_arr = byte_arr.getvalue()
    
    return image_byte_arr

image_to_byte_array(pil_image)

14. 이미지를 Numpy 배열로 변환

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

from PIL import Image
import numpy as np

pil_image = Image.open('images/test_image/test_image.jpg')
numpy_image = np.array(pil_image)
numpy_image

Numpy 배열을 이미지로 변환

pil_images_from_numpy = Image.fromarray(numpy_image, "RGB")

15. 이미지를 픽셀(Pixel) 값으로 변환

from PIL import Image
import numpy as np

pil_image = Image.open('images/test_image/test_image.jpg')
pixel_list = list(pil_image.getdata())
np.savetxt(os.path.join(result_dir, "pixel_type_data.txt"), pixel_list, fmt='%d', delimiter=" ")

16. 특정 픽셀의 RGB 색상값

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

from PIL import Image

pil_image = Image.open('images/test_image/test_image.jpg')
rgb_image = pil_image.convert("RGB")
pixel_color = rgb_image.getpixel((130, 490))
r, g, b = pixel_color
print('R : {}, G : {}, B: {}'.format(r, g, b))

R : 228, G : 0, B: 49

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment