2012-06-21 47 views
16

Tôi có một số lượng lớn hình ảnh có kích thước cố định (nói 500 * 500). Tôi muốn viết một kịch bản python mà sẽ thay đổi kích thước chúng thành một kích thước cố định (nói 800 * 800) nhưng sẽ giữ hình ảnh ban đầu ở trung tâm và điền vào khu vực dư thừa với một màu cố định (nói màu đen).Thêm đường viền vào ảnh bằng python

Tôi đang sử dụng PIL. Tôi có thể thay đổi kích thước hình ảnh bằng cách sử dụng chức năng resize ngay bây giờ, nhưng điều đó thay đổi tỷ lệ cỡ ảnh. Có cách nào để làm điều này không?

Trả lời

32

Bạn có thể tạo hình ảnh mới với kích thước mong muốn mới và dán hình ảnh cũ vào giữa, sau đó lưu hình ảnh đó. Nếu bạn muốn, bạn có thể ghi đè lên ảnh gốc (bạn có chắc;? O)

import Image 

old_im = Image.open('someimage.jpg') 
old_size = old_im.size 

new_size = (800, 800) 
new_im = Image.new("RGB", new_size) ## luckily, this is already black! 
new_im.paste(old_im, ((new_size[0]-old_size[0])/2, 
         (new_size[1]-old_size[1])/2)) 

new_im.show() 
# new_im.save('someimage.jpg') 
22

Có, có.

Make một cái gì đó như thế này:

import Image, ImageOps 
ImageOps.expand(Image.open('original-image.png'),border=300,fill='black').save('imaged-with-border.png') 

Bạn có thể viết cùng một lúc nhiều dòng:

import Image, ImageOps 
img = Image.open('original-image.png') 
img_with_border = ImageOps.expand(img,border=300,fill='black') 
img_with_border.save('imaged-with-border.png') 

Và bạn nói rằng bạn có một danh sách các hình ảnh. Sau đó, bạn phải sử dụng chu trình để xử lý tất cả chúng:

import Image, ImageOps 
for i in list-of-images: 
    img = Image.open(i) 
    img_with_border = ImageOps.expand(img,border=300,fill='black') 
    img_with_border.save('bordered-%s' % i) 
+2

Thú vị. Bạn có thể chọn các đường viền khác nhau cho trên cùng và dưới cùng bên phải, vì vậy kích thước hình ảnh mới có thể là thông số, thay vì kích thước đường viền không? – heltonbiker

+0

Cảm ơn, tôi có thể làm cho các giá trị x và y của biên giới khác nhau ... một cái gì đó giống như nói (100,50)? –

+4

okay tìm thấy một tác phẩm xung quanh, 'ImageOps.expand (Image.open ('original-image.png'), border = (300.500), fill = 'black'). ('Imaged-with-border.png')) ' –

1

Điều quan trọng là phải xem xét khía cạnh cũ, chiều hướng mới và khác biệt của họ vào đây. Nếu sự khác biệt là lẻ (thậm chí không), bạn sẽ cần chỉ định các giá trị hơi khác nhau cho các đường viền bên trái, trên cùng, bên phảiở dưới cùng.

Giả sử kích thước cũ là ow, oh và thứ nguyên mới là nw, nh. Vì vậy, đây sẽ là câu trả lời:

import Image, ImageOps 
img = Image.open('original-image.png') 
deltaw=nw-ow 
deltah=nh-oh 
ltrb_border=(deltaw/2,deltah/2,deltaw-(deltaw/2),deltah-(deltah/2)) 
img_with_border = ImageOps.expand(img,border=ltrb_border,fill='black') 
img_with_border.save('imaged-with-border.png') 
4

Ngoài ra, nếu bạn đang sử dụng OpenCV, họ có một chức năng gọi là copyMakeBorder cho phép bạn thêm padding để bất kỳ bên của một hình ảnh. Ngoài màu sắc chắc chắn, họ cũng có một số tùy chọn thú vị cho các đường viền lạ mắt như phản xạ hoặc mở rộng hình ảnh.

import cv2 

img = cv2.imread('image.jpg') 

color = [101, 52, 152] # 'cause purple! 

# border widths; I set them all to 150 
top, bottom, left, right = [150]*4 

img_with_border = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color) 

Example results of cv2.copyMakeBorder function

Nguồn: OpenCV border tutorialOpenCV 3.1.0 Docs for copyMakeBorder

+3

Tôi nghĩ bạn nên thêm 'cv2.BORDER_CONSTANT' trước khi xác định' value = color' như trong http://docs.opencv.org/3.1.0/d3/df2/tutorial_py_basic_ops.html – gcucurull

1

phương pháp crop PIL của thực sự có thể xử lý việc này cho bạn bằng cách sử dụng con số nằm ngoài khung giới hạn của hình ảnh ban đầu, mặc dù nó không được quy định rõ ràng trong the documentation. Các số âm cho trái và trên sẽ thêm các pixel đen vào các cạnh đó, trong khi số lớn hơn chiều rộng và chiều cao ban đầu cho bên phải và phía dưới sẽ thêm các pixel đen vào các cạnh đó.

Mã này chiếm kích thước điểm ảnh lẻ:

from PIL import Image 

with Image.open('/path/to/image.gif') as im: 
    old_size = im.size 
    new_size = (800, 800) 

    if new_size > old_size: 
     # Set number of pixels to expand to the left, top, right, 
     # and bottom, making sure to account for even or odd numbers 
     if old_size[0] % 2 == 0: 
      add_left = add_right = (new_size[0] - old_size[0]) // 2 
     else: 
      add_left = (new_size[0] - old_size[0]) // 2 
      add_right = ((new_size[0] - old_size[0]) // 2) + 1 

     if old_size[1] % 2 == 0: 
      add_top = add_bottom = (new_size[1] - old_size[1]) // 2 
     else: 
      add_top = (new_size[1] - old_size[1]) // 2 
      add_bottom = ((new_size[1] - old_size[1]) // 2) + 1 

     left = 0 - add_left 
     top = 0 - add_top 
     right = old_size[0] + add_right 
     bottom = old_size[1] + add_bottom 

     # By default, the added pixels are black 
     im = im.crop((left, top, right, bottom)) 

Thay vì 4-tuple, bạn thay vì có thể sử dụng 2-tuple thêm cùng một số điểm ảnh trên trái/phải và trên/dưới hoặc 1-tuple để thêm cùng số pixel vào tất cả các cạnh.

1

Bạn có thể tải hình ảnh với scipy.misc.imread làm mảng có nhiều mảng.Sau đó, tạo một mảng với nền mong muốn bằng numpy.zeros((height, width, channels)) và dán hình ảnh vào vị trí mong muốn:

import numpy as np 
import scipy.misc 

im = scipy.misc.imread('foo.jpg', mode='RGB') 
height, width, channels = im.shape 

# make canvas 
im_bg = np.zeros((height, width, channels)) 
im_bg = (im_bg + 1) * 255 # e.g., make it white 

# Your work: Compute where it should be 
pad_left = ... 
pad_top = ... 

im_bg[pad_top:pad_top + height, 
     pad_left:pad_left + width, 
     :] = im 
# im_bg is now the image with the background. 
Các vấn đề liên quan