web-dev-qa-db-ja.com

pythonを使用して画像に境界線を追加する

固定サイズ(500 * 500など)の画像が多数あります。 python固定サイズ(たとえば800 * 800)にサイズを変更するスクリプトを記述したいが、元の画像を中央に保ち、余分な領域を固定色で塗りつぶす(たとえば黒)。

PILを使用しています。 resize関数を使用して画像のサイズを変更できますが、これによりアスペクト比が変更されます。これを行う方法はありますか?

31
Nihar Sarangi

目的の新しいサイズで新しい画像を作成し、古い画像を中央に貼り付けて保存できます。必要に応じて、元の画像を上書きできます(確かですか?; 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')
44
heltonbiker

はいあります。

次のようなものを作成します。

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

同じことをいくつかの行に書くことができます:

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')

そして、あなたはあなたが画像のリストを持っていると言います。次に、サイクルを使用してそれらすべてを処理する必要があります。

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)
35
Igor Chubin

また、 OpenCV を使用している場合、copyMakeBorderという関数があり、画像の任意の辺にパディングを追加できます。単色のほかに、画像の反射や拡大などの派手な境界線のクールなオプションもあります。

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

ソース: OpenCVボーダーチュートリアル および copyCakeBorderのOpenCV 3.1.0ドキュメント

9
pirt

PILのcropメソッドは、元の画像の境界ボックスの外側にある数字を使用することで、実際にこれを処理できますが、 ドキュメント には明示的に記載されていません。左と上の負の数値はそれらのエッジに黒のピクセルを追加し、右と下の元の幅と高さより大きい数値はそれらのエッジに黒のピクセルを追加します。

このコードは、奇数のピクセルサイズを考慮しています。

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))

4-Tupleの代わりに、2-Tupleを使用して同じ数のピクセルを左/右と上/下に追加するか、1-Tupleを使用してすべての辺に同じ数のピクセルを追加できます。

2
kevinmicke

Numpy配列として _scipy.misc.imread_ でイメージをロードできます。次に、 numpy.zeros((height, width, channels)) を使用して目的の背景を持つ配列を作成し、目的の場所に画像を貼り付けます。

_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.
_
2
Martin Thoma

ここで、古い次元、新しい次元、およびそれらの違いを考慮することが重要です。差が奇数(偶数ではない)の場合、左、上、右の境界にわずかに異なる値を指定する必要があります。

古い次元はow、ohで、新しい次元はnw、nhであると仮定します。したがって、これが答えになります。

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')
2
RF Vision