PILを使用して画像のサイズを変更し、そのアスペクト比を維持するにはどうすればよいですか?


435

これを行う明らかな方法はありますか?サムネイルを作ろうとしているだけです。


9
この質問はかなり古いが有用であり、枕はむしろ枕ベースのこのを見てみましょうチュートリアルについては、好まれているので:pillow.readthedocs.org/en/latest/handbook/...
Wtower

3
画像のサイズを変更するための小さなライブラリを作成しました。これは役に立ちます:github.com/charlesthk/python-resize-image
Charlesthk

PILの最後のリリースは2006年でした。枕カバーのパッケージは、私の知る限り、代替品です。枕の最新リリースは、4月2日、2020年だった
デビッドMedinets

回答:


477

最大サイズを定義します。次に、を使用してサイズ変更比率を計算しmin(maxwidth/width, maxheight/height)ます。

適正サイズはoldsize*ratioです。

もちろん、これを行うライブラリメソッドもあります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)に設定し、幅を計算して縦横比を維持します。高さの代わりに幅を修正する方法はありますか?多分私はこれを別の質問で尋ねます。
ユージーン

6
@Eugene:のようなものを試してくださいs= img.size(); ratio = MAXWIDTH/s[0]; newimg = img.resize((s[0]*ratio, s[1]*ratio), Image.ANTIALIAS)?(ただし、浮動小数点除算の場合:)
gnud

48
ANTIALIASは、PILの人気のあるPillowフォークのユーザーにはもはや推奨されないことに注意してください。pillow.readthedocs.org/en/3.0.x/releasenotes/...
Joshmaker

8
PILのPython 3 ドキュメントはthumbnail、結果の画像が元の画像よりも小さい場合にのみ機能することを述べています。そのため、使用resizeする方が良いと思います。
つまり

253

このスクリプトは、PIL(Python Imaging Library)を使用して画像(somepic.jpg)の幅を300ピクセルに変更し、高さを新しい幅に比例させます。これは、元の幅(img.size [0])の300ピクセルのパーセンテージを決定し、元の高さ(img.size [1])にそのパーセンテージを掛けることによって行われます。「basewidth」を他の数値に変更して、画像のデフォルトの幅を変更します。

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の「イメージ」と衝突しないように、「from PIL import Image」という行が必要になります。
トムボン、2009年

このコードは、0バイトの出力ファイルを取得しますsompic.jpg。なぜこれが起こるのですか?私はPython 3.xを使用しています
imrek

–更新:Python 2.7でも同じことが起こります。
imrek 2017年

私は理解したかもしれません。を保存する場合は.jpeg、を使用しますimg.save('sompic.jpg', 'JPEG')
imrek 2017年

5
nit:PIL.Image.ANTIALIASオプションはありません。resize実際にはですがPIL.Image.LANCZOS、どちらも1価値があります。pillow.readthedocs.io
Fred Wu

66

また、PILのサムネイル方式を使用することをお勧めします。これにより、比率の面倒がすべて解消されます。

ただし、1つの重要なヒント:置き換え

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 2016年

@Zachaferの修正を提案
Mo Beigi

1
それらを整数に変換する方が良い
Black Thunder

18

PILにはすでに画像をトリミングするオプションがあります

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

20
画像をトリミングするだけで、アスペクト比は維持されません。
ラドゥ

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にして、圧縮または拡大した画像を作成します。
10:07

これは決して質問に答えるものではありません。
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

Pillowで画像を開く必要がない、または必要がない場合は、次を使用します。

from PIL import Image

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

4

この質問をより最新のラッパーで更新するだけですこのライブラリはPillow(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

スライドショービデオの一部の画像のサイズを変更しようとしていたため、1つの最大寸法だけでなく、最大幅最大高さ(ビデオフレームのサイズ)も必要でした。
そして、常にポートレートビデオの可能性がありました...
その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の初期アスペクト比に基づいて、新しい画像の幅に合わせて高さが調整されます。ただし、幅を高さに調整するには、代わりに、1つの行をコメント化し、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()どこにありますか?
アンソニー

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.