2012-02-01 41 views
11

Hiện nay tôi đang sử dụng:Thay đổi kích thước hình ảnh duy trì tỷ lệ khung hình VÀ làm cho hình ảnh chân dung và phong cảnh chính xác cùng kích thước?

os.chdir(album.path) 
    images = glob.glob('*.*') 

    # thumbs size 
    size = 80,80 

    for image in images: 
     #create thumb 
     file, ext = os.path.splitext(image) 
     im = Image.open(os.path.join(album.path,image)) 
     im.thumbnail(size, Image.ANTIALIAS) 
     thumb_path = os.path.join(album.path, 'thumbs', file + ".thumb" + ".jpeg") 
     im.save(thumb_path) 

Mặc dù làm việc này, tôi kết thúc với kích thước hình ảnh khác nhau (một số là chân dung và một số cảnh quan), nhưng tôi muốn tất cả các hình ảnh có kích thước chính xác. Có lẽ một vụ cắt xén hợp lý?

UPDATE:

Tôi không quan tâm cắt xén một phần nhỏ của hình ảnh. Khi tôi nói cắt xén hợp lý, tôi có nghĩa là một cái gì đó như thế này algorythm:

if image is portrait: 
    make width 80px 
    crop the height (will be more than 80px) 
else if image is landscape: 
    make height 80px 
    crop the width to 80px (will be more than 80px) 
+0

Cân nhắc đọc hướng dẫn sử dụng. Phương thức 'thumnail' là * có nghĩa là * để bảo toàn khía cạnh của hình ảnh. Rõ ràng, bạn không thể có cả hai, vì không phải tất cả các hình ảnh đều có cùng tỷ lệ khung hình. Xem xét sử dụng 'thay đổi kích thước' nếu bạn muốn rescale mà không giữ tỷ lệ. –

+1

Ông có thể làm cho chúng có kích thước tương tự nếu ông muốn làm một phù hợp, mà sẽ pad ra khu vực thêm với một màu sắc liên tục. Điều đó sẽ cho phép hình ảnh 4x3 hoặc 16x9 hoặc bất kỳ hình ảnh nào phù hợp với một kích thước nhất định là 80x80 – jdi

+0

Thật không may là không có cách nào tiêu chuẩn để xác định "hợp lý" để cắt xén. Có vẻ như bạn muốn luôn cắt một hình vuông từ hình ảnh, điều đó có nghĩa là bạn có nguy cơ cắt bỏ các phần bạn thực sự muốn giữ lại. –

Trả lời

18

Đây là quan điểm của tôi về làm một sự phù hợp đệm cho một hình ảnh:

#!/usr/bin/env python 

from PIL import Image, ImageChops 

F_IN = "/path/to/image_in.jpg" 
F_OUT = "/path/to/image_out.jpg" 

size = (80,80) 

image = Image.open(F_IN) 
image.thumbnail(size, Image.ANTIALIAS) 
image_size = image.size 

thumb = image.crop((0, 0, size[0], size[1])) 

offset_x = max((size[0] - image_size[0])/2, 0) 
offset_y = max((size[1] - image_size[1])/2, 0) 

thumb = ImageChops.offset(thumb, offset_x, offset_y) 
thumb.save(F_OUT) 

Đầu tiên sử dụng thao tác thu nhỏ để đưa hình ảnh xuống trong giới hạn ban đầu của bạn và giữ nguyên khía cạnh. Sau đó, nó cắt nó ra để thực sự điền vào kích thước của giới hạn của bạn (kể từ khi trừ khi hình ảnh ban đầu là hình vuông, nó sẽ nhỏ hơn bây giờ), và chúng tôi tìm thấy sự bù đắp thích hợp để trung tâm hình ảnh. Hình ảnh được bù đắp cho trung tâm, vì vậy bạn kết thúc với đệm đen nhưng không cắt ảnh. Trừ khi bạn có thể thực hiện một dự đoán thực sự hợp lý tại một cây trồng trung tâm thích hợp mà không làm mất dữ liệu hình ảnh quan trọng có thể có trên các cạnh, một phương pháp tiếp cận phù hợp với đệm sẽ hoạt động tốt hơn. Page 5

Cập nhật

Đây là một phiên bản có thể làm một trong hai cắt chính giữa hoặc pad phù hợp.

#!/usr/bin/env python 

from PIL import Image, ImageChops, ImageOps 

def makeThumb(f_in, f_out, size=(80,80), pad=False): 

    image = Image.open(f_in) 
    image.thumbnail(size, Image.ANTIALIAS) 
    image_size = image.size 

    if pad: 
     thumb = image.crop((0, 0, size[0], size[1])) 

     offset_x = max((size[0] - image_size[0])/2, 0) 
     offset_y = max((size[1] - image_size[1])/2, 0) 

     thumb = ImageChops.offset(thumb, offset_x, offset_y) 

    else: 
     thumb = ImageOps.fit(image, size, Image.ANTIALIAS, (0.5, 0.5)) 

    thumb.save(f_out) 


source = "/path/to/source/image.JPG" 

makeThumb(source, "/path/to/source/image_padded.JPG", pad=True) 
makeThumb(source, "/path/to/source/image_centerCropped.JPG", pad=False) 
+0

Điều này thực sự gần với những gì tôi cần @ jdi, cảm ơn! Làm thế nào để tôi thay đổi nó để cắt và không chèn đệm? (thậm chí mất một phần của hình ảnh) – thyagx

+0

@thyagx - có ya đi! – jdi

+1

Hoàn hảo, chính xác những gì tôi cần! Cảm ơn @jdi! – thyagx

2

Rõ ràng, bạn sẽ cần phải cắt hoặc pad hình ảnh. Bạn có thể làm một cái gì đó giống như cây trồng bên dưới để một tối đa trung tâm theo tỉ lệ của hình thu nhỏ (chưa được kiểm tra):

aspect = lambda size: float(size[0])/float(size[1]) 
sa = aspect(size) 
if aspect(im.size) > sa: 
    width = int(sa * im.size[1]) 
    left = (im.size[0] - width)/2 
    im = im.crop((left, 0, left + width, im.size[1])) 
else: 
    height = int(im.size[0]/sa) 
    top = (im.size[1] - height)/2 
    im = im.crop((0, top, im.size[0], top + height)) 
im.thumbnail(size, Image.ANTIALIAS) 
+0

Ví dụ này có một vài lỗi trong đó. im.crop() không cắt tại chỗ.Nó cần trả lại đối tượng hình ảnh cho chính nó. Các đối số cho crop cần phải là một hộp tuple, vì vậy bạn cần bọc chúng vào(). Bạn đang truyền trôi nổi đến cây trồng. Cần làm int (width) và int (height). Ngoài ra, tất cả điều này là không cần thiết vì có một phương thức dựng sẵn: 'im = ImageOps.fit (im, size, Image.ANTIALIAS, (0.5, 0.5))' thực hiện điều tương tự. – jdi

0

Nếu bạn sử dụng dễ hình thu nhỏ bạn sẽ cần phải thiết lập crop để Trueupscale để True luôn lấp đầy không gian (có kích thước chính xác như nhau).

Ex: làm IMAGE_2 phù hợp kích thước IMAGE_1:

thumbnailer = get_thumbnailer(image_2) 
    thumbnail = thumbnailer.generate_thumbnail(thumbnail_options={ 
     'crop': True, 
     'upscale': True, 
     'size': image_1.size 
    }) 
    image_2 = thumbnail.image 
Các vấn đề liên quan