파이썬 이미지 처리 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()
![](https://playground.naragara.com/wp-content/uploads/2023/07/image-23.png)
이미지 속성 확인 방법
이미지의 크기, 이름, 모드, 가로 세로 길이 등의 정보를 확인 할 수 있습니다.
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.HAMMING | BILINEAR보다 선명한 이미지를 생성합니다. BOX처럼 로컬 수준의 전위가 없습니다. 이 필터는 resize() 및 thumbnail()메서드 에서만 사용할 수 있습니다 . |
PIL.Image.BICUBI | 크기 조정을 위해 출력 값에 기여할 수 있는 모든 픽셀에서 삼차 보간법을 사용하여 출력 픽셀 값을 계산합니다. 다른 변환의 경우 입력 이미지의 4×4 환경에 대한 큐빅 보간이 사용됩니다. |
PIL.Image.LANCZOS | 출력 값에 기여할 수있는 모든 픽셀에서 고품질 Lanczos 필터 (잘린 sinc)를 사용하여 출력 픽셀 값을 계산합니다. 이 필터는 resize() 및 thumbnail()메서드 에서만 사용할 수 있습니다 . |
눈으로 식별은 잘 안되는 것 같습니다. 아래 필터 비교표를 참고하세요.
![](https://playground.naragara.com/wp-content/uploads/2023/07/image-24-1024x488.png)
이미지 자르기(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()
![](https://playground.naragara.com/wp-content/uploads/2023/07/image-25.png)
이미지 회전
Image 클래스의 rotate()함수를 사용하면 이미지를 원하는 각도만 큼 회전 할 수 있습니다.
from PIL import Image img = Image.open("C:/Users/ilike/Pictures/IU_400x400.jpg") img.rotate(45).show()
![](https://playground.naragara.com/wp-content/uploads/2023/07/image-26-1024x1008.png)
이미지 상하, 좌우 대칭(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()
왼쪽부터 원본이미지, 좌우대칭, 상하 반전(뒤집기) 이미지입니다.
![](https://playground.naragara.com/wp-content/uploads/2023/07/image-27-1024x485.png)
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도 회전된 이미지 입니다.
![](https://playground.naragara.com/wp-content/uploads/2023/07/image-28-1024x257.png)
이미지 필터링
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로 처리한 이미지 입니다.
![](https://playground.naragara.com/wp-content/uploads/2023/07/image-29-1024x256.png)
하나씩 테스트 해보기에는 필터가 많아요. 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))
필터를 적용하여 새로운 이미지 파일로 모두 저장하였습니다.
![](https://playground.naragara.com/wp-content/uploads/2023/07/image-30-1024x236.png)
이미지 합치기
여러개의 이미지를 불러와서 합치는 방법에 대해 알아봅니다. 여러개의 이미지를 합치기 위해서는 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()
![](https://playground.naragara.com/wp-content/uploads/2023/07/image-31-1024x551.png)
이미지 저장
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))
![](https://playground.naragara.com/wp-content/uploads/2023/07/image-32-1024x152.png)
이미지 썸네일(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()
![](https://playground.naragara.com/wp-content/uploads/2023/07/image-33-1024x157.png)
현재 디렉토리의 모든 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