PIL을 사용하여 이미지 크기를 조정하고 종횡비를 유지하려면 어떻게합니까?


437

내가 누락 된 확실한 방법이 있습니까? 미리보기 이미지를 만들려고합니다.


9
이 질문은 상당히 오래되었지만 유용하고 베개가 선호됩니다. 베개 기반 튜토리얼의 경우 다음을 살펴보십시오. pillow.readthedocs.org/en/latest/handbook/…
Wtower

3
이미지 크기 조정을위한 작은 라이브러리를 만들었습니다. github.com/charlesthk/python-resize-image
Charlesthk

PIL의 마지막 릴리스는 2006 년이었습니다. 필로우 팩지는 내가 아는 한 교체품입니다. Pillow의 최신 릴리스는 2020 년 4 월 2 일입니다.
David Medinets

답변:


477

최대 크기를 정의하십시오. 그런 다음을 사용하여 크기 조정 비율을 계산하십시오 min(maxwidth/width, maxheight/height).

적절한 크기는 oldsize*ratio입니다.

물론 이것을 수행하는 라이브러리 메소드가 있습니다 : method Image.thumbnail.
아래는 PIL 문서 의 (편집 된) 예입니다 .

import os, sys
import Image

size = 128, 128

for infile in sys.argv[1:]:
    outfile = os.path.splitext(infile)[0] + ".thumbnail"
    if infile != outfile:
        try:
            im = Image.open(infile)
            im.thumbnail(size, Image.ANTIALIAS)
            im.save(outfile, "JPEG")
        except IOError:
            print "cannot create thumbnail for '%s'" % infile

4
예와 같이 예제는 pil 문서에서 가져온 것이며 해당 예제 (여전히)는 앤티 앨리어스 플래그를 사용하지 않습니다. 그래도 대부분의 사람들이 원하는 것이므로 추가했습니다.
gnud

3
PIL은 새 이미지의 높이를 주어진 크기 (128)로 설정하고 가로 세로 비율을 유지하기 위해 너비를 계산합니다. 높이 대신 너비를 고정하는 방법이 있습니까? 어쩌면 나는 이것을 별도의 질문으로 물어볼 것입니다.
eugene

6
@ 유진 : 같은 것을 시도 s= img.size(); ratio = MAXWIDTH/s[0]; newimg = img.resize((s[0]*ratio, s[1]*ratio), Image.ANTIALIAS)? (그러나 그것은 부동 소수점 나누기입니다.)
gnud

48
참고 ANTIALIAS더 이상 PIL의 인기 베개 포크의 사용자 선호하지 않습니다. pillow.readthedocs.org/en/3.0.x/releasenotes/…
Joshmaker

8
PIL 의 Python 3 문서에 따르면 thumbnail결과 이미지가 원본 이미지보다 작은 경우에만 작동합니다. 그 때문에 사용 resize하는 것이 더 좋은 방법 이라고 생각합니다 .
그래서 S

253

이 스크립트는 PIL (Python Imaging Library)을 사용하여 이미지 (somepic.jpg)의 크기를 300 픽셀의 너비와 새 너비에 비례하는 높이로 조정합니다. 300 픽셀이 원래 너비 인 비율 (img.size [0])을 결정한 다음 원래 높이 (img.size [1])에 해당 백분율을 곱하면됩니다. 이미지의 기본 너비를 변경하려면 "기준 너비"를 다른 숫자로 변경하십시오.

from PIL import Image

basewidth = 300
img = Image.open('somepic.jpg')
wpercent = (basewidth/float(img.size[0]))
hsize = int((float(img.size[1])*float(wpercent)))
img = img.resize((basewidth,hsize), Image.ANTIALIAS)
img.save('sompic.jpg') 

2
Zope에서이 스크립트를 외부 방법으로 사용하는 경우 네임 스페이스가 Zope의 "Image"와 충돌하지 않도록하려면 "PIL import Image에서"행이 필요합니다.
tomvon

이 코드는 0 바이트 출력 파일을 얻습니다 sompic.jpg. 왜 이런 일이 발생합니까? 저는 Python 3.x를 사용하고 있습니다
imrek

– 업데이트 : Python 2.7에서도 마찬가지입니다.
imrek

알아 냈을 수도 있습니다. 를 저장하는 경우을 .jpeg사용하십시오 img.save('sompic.jpg', 'JPEG').
imrek

5
nit :에 대한 PIL.Image.ANTIALIAS옵션 이 없습니다. resize실제로 PIL.Image.LANCZOS둘 다 1가치 가 있지만 , pillow.readthedocs.io/en/3.1.x/reference/…
Fred Wu

66

또한 PIL의 썸네일 방법을 사용하는 것이 좋습니다. 왜냐하면 모든 비율 번거 로움을 제거하기 때문입니다.

그러나 한 가지 중요한 힌트 : 바꾸기

im.thumbnail(size)

im.thumbnail(size,Image.ANTIALIAS)

기본적으로 PIL은 크기 조정을 위해 Image.NEAREST 필터를 사용하여 성능은 좋지만 품질은 떨어집니다.


2
이를 통해 이미지 크기 만 줄일 수 있습니다. 로 크기를 늘릴 수 없습니다 Image.thumbnail.
burny

45

@tomvon을 기반으로 다음 사용을 마쳤습니다 (사례 선택).

a) 높이 조정 ( 새 너비를 알고 있으므로 새 높이가 필요합니다 )

new_width  = 680
new_height = new_width * height / width 

b) 너비 조정 크기 ( 새 높이를 알고 있으므로 새 너비가 필요합니다 )

new_height = 680
new_width  = new_height * width / height

그런 다음 :

img = img.resize((new_width, new_height), Image.ANTIALIAS)

6
변수가 모두 섞여 있습니다. 게시물에 너비 크기 조정이 표시된 다음 높이 크기가 조정됩니다. 그리고 resize전화에서 new_width높이와 너비 모두를 사용하고 있습니까?
Zachafer

@Zachafer에 대한 수정 제안
Mo Beigi

1
정수로 변환하는 것이
Black Thunder

18

PIL에는 이미 이미지를 자르는 옵션이 있습니다

img = ImageOps.fit(img, size, Image.ANTIALIAS)

20
이미지를 자르기 만하면 종횡비가 유지되지 않습니다.
Radu

2
이것은 어떤 식 으로든 질문에 대답하지 않습니다.
AMC

15
from PIL import Image

img = Image.open('/your image path/image.jpg') # image extension *.png,*.jpg
new_width  = 200
new_height = 300
img = img.resize((new_width, new_height), Image.ANTIALIAS)
img.save('output image name.png') # format may what you want *.png, *jpg, *.gif

8
소스 이미지의 종횡비를 유지하지 않습니다. 이미지를 200x300으로 강제하고 이미지를 압착하거나 늘릴 수 있습니다.
burny

이것은 어떤 식 으로든 질문에 대답하지 않습니다.
AMC

12

동일한 종횡비를 유지하려는 경우 원래 크기의 일정 비율로 크기를 조정하지 않습니까?

예를 들어, 원래 크기의 절반

half = 0.5
out = im.resize( [int(half * s) for s in im.size] )

13
이미지의 크기는 다양하고 크기 조정 결과는 균일 한 크기 여야합니다.
Steen

7
from PIL import Image
from resizeimage import resizeimage

def resize_file(in_file, out_file, size):
    with open(in_file) as fd:
        image = resizeimage.resize_thumbnail(Image.open(fd), size)
    image.save(out_file)
    image.close()

resize_file('foo.tif', 'foo_small.jpg', (256, 256))

이 라이브러리를 사용합니다 :

pip install python-resize-image

7

필로우로 이미지를 열 필요가 없거나 필요없는 경우 다음을 사용하십시오.

from PIL import Image

new_img_arr = numpy.array(Image.fromarray(img_arr).resize((new_width, new_height), Image.ANTIALIAS))

4

더 현대적인 래퍼 로이 질문을 업데이트하십시오.이 라이브러리는 필로우 (PIL 포크)를 래핑합니다 https://pypi.org/project/python-resize-image/

다음과 같이 할 수 있습니다 :-

from PIL import Image
from resizeimage import resizeimage

fd_img = open('test-image.jpeg', 'r')
img = Image.open(fd_img)
img = resizeimage.resize_width(img, 200)
img.save('test-image-width.jpeg', img.format)
fd_img.close()

위의 링크에서 더 많은 예제를 힙합니다.


3
resize_contain은 실제로 매우 유용합니다!
Anytoe

4

슬라이드 쇼 비디오의 일부 이미지 크기를 조정하려고했기 때문에 최대 크기 하나가 아니라 최대 너비 최대 높이 (비디오 프레임 크기)를 원했습니다.
그리고 항상 인물 사진의 가능성이있었습니다 ...
Image.thumbnail방법은 유망했지만, 더 작은 이미지로 확대 할 수 없었습니다.

그래서 여기서 (또는 다른 곳에서) 그렇게 할 수있는 확실한 방법을 찾지 못하면이 기능을 작성하여 앞으로 올 기능을 제공했습니다.

from PIL import Image

def get_resized_img(img_path, video_size):
    img = Image.open(img_path)
    width, height = video_size  # these are the MAX dimensions
    video_ratio = width / height
    img_ratio = img.size[0] / img.size[1]
    if video_ratio >= 1:  # the video is wide
        if img_ratio <= video_ratio:  # image is not wide enough
            width_new = int(height * img_ratio)
            size_new = width_new, height
        else:  # image is wider than video
            height_new = int(width / img_ratio)
            size_new = width, height_new
    else:  # the video is tall
        if img_ratio >= video_ratio:  # image is not tall enough
            height_new = int(width / img_ratio)
            size_new = width, height_new
        else:  # image is taller than video
            width_new = int(height * img_ratio)
            size_new = width_new, height
    return img.resize(size_new, resample=Image.LANCZOS)

3

제한된 비율을 유지하고 최대 너비 / 높이를 전달하는 간단한 방법입니다. 가장 예쁘지는 않지만 일을 끝내고 이해하기 쉽습니다.

def resize(img_path, max_px_size, output_folder):
    with Image.open(img_path) as img:
        width_0, height_0 = img.size
        out_f_name = os.path.split(img_path)[-1]
        out_f_path = os.path.join(output_folder, out_f_name)

        if max((width_0, height_0)) <= max_px_size:
            print('writing {} to disk (no change from original)'.format(out_f_path))
            img.save(out_f_path)
            return

        if width_0 > height_0:
            wpercent = max_px_size / float(width_0)
            hsize = int(float(height_0) * float(wpercent))
            img = img.resize((max_px_size, hsize), Image.ANTIALIAS)
            print('writing {} to disk'.format(out_f_path))
            img.save(out_f_path)
            return

        if width_0 < height_0:
            hpercent = max_px_size / float(height_0)
            wsize = int(float(width_0) * float(hpercent))
            img = img.resize((max_px_size, wsize), Image.ANTIALIAS)
            print('writing {} to disk'.format(out_f_path))
            img.save(out_f_path)
            return

이 기능을 사용하여 배치 이미지 크기 조정을 실행 하는 Python 스크립트 가 있습니다.


3

"tomvon"으로 위의 답변을 업데이트했습니다

from PIL import Image

img = Image.open(image_path)

width, height = img.size[:2]

if height > width:
    baseheight = 64
    hpercent = (baseheight/float(img.size[1]))
    wsize = int((float(img.size[0])*float(hpercent)))
    img = img.resize((wsize, baseheight), Image.ANTIALIAS)
    img.save('resized.jpg')
else:
    basewidth = 64
    wpercent = (basewidth/float(img.size[0]))
    hsize = int((float(img.size[1])*float(wpercent)))
    img = img.resize((basewidth,hsize), Image.ANTIALIAS)
    img.save('resized.jpg')

매력처럼 일하십시오! 감사합니다!
Denis Savenko

2

내 추악한 예.

함수는 "pic [0-9a-z]. [extension]"과 같은 파일을 가져오고 120x120으로 크기를 조정하고 섹션을 가운데로 이동하고 "ico [0-9a-z]. [extension]"에 저장합니다. 그리고 풍경 :

def imageResize(filepath):
    from PIL import Image
    file_dir=os.path.split(filepath)
    img = Image.open(filepath)

    if img.size[0] > img.size[1]:
        aspect = img.size[1]/120
        new_size = (img.size[0]/aspect, 120)
    else:
        aspect = img.size[0]/120
        new_size = (120, img.size[1]/aspect)
    img.resize(new_size).save(file_dir[0]+'/ico'+file_dir[1][3:])
    img = Image.open(file_dir[0]+'/ico'+file_dir[1][3:])

    if img.size[0] > img.size[1]:
        new_img = img.crop( (
            (((img.size[0])-120)/2),
            0,
            120+(((img.size[0])-120)/2),
            120
        ) )
    else:
        new_img = img.crop( (
            0,
            (((img.size[1])-120)/2),
            120,
            120+(((img.size[1])-120)/2)
        ) )

    new_img.save(file_dir[0]+'/ico'+file_dir[1][3:])

2

그런 식으로 이미지 크기를 조정했으며 잘 작동합니다.

from io import BytesIO
from django.core.files.uploadedfile import InMemoryUploadedFile
import os, sys
from PIL import Image


def imageResize(image):
    outputIoStream = BytesIO()
    imageTemproaryResized = imageTemproary.resize( (1920,1080), Image.ANTIALIAS) 
    imageTemproaryResized.save(outputIoStream , format='PNG', quality='10') 
    outputIoStream.seek(0)
    uploadedImage = InMemoryUploadedFile(outputIoStream,'ImageField', "%s.jpg" % image.name.split('.')[0], 'image/jpeg', sys.getsizeof(outputIoStream), None)

    ## For upload local folder
    fs = FileSystemStorage()
    filename = fs.save(uploadedImage.name, uploadedImage)

2

또한 가로 세로 비율을 고정으로 유지하는 크기 조정 버전을 추가합니다. 이 경우, 초기의 종횡비에 기초하여, 새로운 화상의 폭과 일치하는 높이를 조절한다 asp_rat 이며, 플로트 (!)를. 그러나 너비를 높이로 조정하려면 대신 한 줄을 주석 처리하고 else 루프 에서 다른 줄을 주석 해제하면 됩니다. 당신은 어디에서 볼 수 있습니다.

세미콜론 (;)이 필요하지 않습니다. 더 자주 사용하는 언어의 구문을 상기시켜줍니다.

from PIL import Image

img_path = "filename.png";
img = Image.open(img_path);     # puts our image to the buffer of the PIL.Image object

width, height = img.size;
asp_rat = width/height;

# Enter new width (in pixels)
new_width = 50;

# Enter new height (in pixels)
new_height = 54;

new_rat = new_width/new_height;

if (new_rat == asp_rat):
    img = img.resize((new_width, new_height), Image.ANTIALIAS); 

# adjusts the height to match the width
# NOTE: if you want to adjust the width to the height, instead -> 
# uncomment the second line (new_width) and comment the first one (new_height)
else:
    new_height = round(new_width / asp_rat);
    #new_width = round(new_height * asp_rat);
    img = img.resize((new_width, new_height), Image.ANTIALIAS);

# usage: resize((x,y), resample)
# resample filter -> PIL.Image.BILINEAR, PIL.Image.NEAREST (default), PIL.Image.BICUBIC, etc..
# https://pillow.readthedocs.io/en/3.1.x/reference/Image.html#PIL.Image.Image.resize

# Enter the name under which you would like to save the new image
img.save("outputname.png");

그리고 그것은 끝났습니다. 가능한 한 많이 문서화하려고 했으므로 분명합니다.

나는 그것이 누군가에게 도움이되기를 바랍니다!


0

이미지 파일을여십시오

from PIL import Image
im = Image.open("image.png")

PIL Image.resize (size, resample = 0) 메소드를 사용하십시오 . 여기서 2 튜플 크기의 이미지를 (너비, 높이)로 대체하십시오.

이미지가 원래 크기로 표시됩니다.

display(im.resize((int(im.size[0]),int(im.size[1])), 0) )

이미지가 1/2 크기로 표시됩니다.

display(im.resize((int(im.size[0]/2),int(im.size[1]/2)), 0) )

이미지가 1/3 크기로 표시됩니다.

display(im.resize((int(im.size[0]/3),int(im.size[1]/3)), 0) )

이미지가 1/4 크기로 표시됩니다.

display(im.resize((int(im.size[0]/4),int(im.size[1]/4)), 0) )


무엇 display()이며 어디에 있습니까?
Anthony

0
from PIL import Image
from resizeimage import resizeimage

def resize_file(in_file, out_file, size):
    with open(in_file) as fd:
        image = resizeimage.resize_thumbnail(Image.open(fd), size)
    image.save(out_file)
    image.close()

resize_file('foo.tif', 'foo_small.jpg', (256, 256))

-1

아래 코드로 이미지 크기를 조정할 수 있습니다.

From PIL import Image
img=Image.open('Filename.jpg') # paste image in python folder
print(img.size())
new_img=img.resize((400,400))
new_img.save('new_filename.jpg')
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.