Python 向图像添加填充以使它们具有相同的形状

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43391205/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 22:59:32  来源:igfitidea点击:

Add padding to images to get them into the same shape

pythonimageopencvpython-imaging-library

提问by vincent

l have a set of images of different sizes (45,50,3), (69,34,3), (34,98,3). l want to add padding to these images as follows:

我有一组不同大小的图像(45,50,3), (69,34,3), (34,98,3)。我想为这些图像添加填充,如下所示:

Take the max width and length of the whole images then put the image in that size

获取整个图像的最大宽度和长度,然后将图像放入该尺寸

import os
import glob
import cv2

input_path="/home/images"
os.chdir(indput_path)
images=glob.glob("*.png")
Length=[]
Width=[]
for img in images:
    img=cv2.imread(img)
    width,length=img.shape[0:2]
    Length.append(length)
    Width.append(width)
W=max(Width)
L=max(Length)

How can l add padding in opencv so that all the images will have the same size? In the example l gave the images will get the shape of (69,98,3)

我如何在 opencv 中添加填充以使所有图像都具有相同的大小?在我给出的例子中,图像将得到形状(69,98,3)

回答by Azade Farshad

You can use:

您可以使用:

image = cv2.copyMakeBorder( src, top, bottom, left, right, borderType)

where src is your source image and top, botto, left, right are paddings around the image.

其中 src 是您的源图像,顶部、底部、左侧、右侧是图像周围的填充。

You can use max(sizes) - size value of the image in a while loop to add the padding to each image. the bordertype can be one of these:

您可以在 while 循环中使用 max(sizes) - 图像的大小值将填充添加到每个图像。边界类型可以是以下之一:

  • cv2.BORDER_CONSTANT
  • cv2.BORDER_REFLECT
  • cv2.BORDER_REFLECT_101
  • cv2.BORDER_DEFAULT
  • cv2.BORDER_REPLICATE
  • cv2.BORDER_WRAP
  • cv2.BORDER_CONSTANT
  • cv2.BORDER_REFLECT
  • cv2.BORDER_REFLECT_101
  • cv2.BORDER_DEFAULT
  • cv2.BORDER_REPLICATE
  • cv2.BORDER_WRAP

copyMakeBorder tutorial

copyMakeBorder 教程

回答by fmw42

Here is another way to do that in Python/OpenCV/Numpy. It uses numpy slicing to copy the input image into a new image of the desired output size and a given offset. Here I compute the offset to do center padding. I think this is easier to do using width, height, xoffset, yoffset, rather than how much to pad on each side.

这是在 Python/OpenCV/Numpy 中执行此操作的另一种方法。它使用 numpy 切片将输入图像复制到具有所需输出大小和给定偏移量的新图像中。在这里,我计算偏移量以进行中心填充。我认为使用宽度、高度、xoffset、yoffset 更容易做到这一点,而不是每边填充多少。

Input:

输入:

enter image description here

在此处输入图片说明

import cv2
import numpy as np

# read image
img = cv2.imread('lena.jpg')
ht, wd, cc= img.shape

# create new image of desired size and color (blue) for padding
ww = 300
hh = 300
color = (255,0,0)
result = np.full((hh,ww,cc), color, dtype=np.uint8)

# compute center offset
xx = (ww - wd) // 2
yy = (hh - ht) // 2

# copy img image into center of result image
result[yy:yy+ht, xx:xx+wd] = img

# view result
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

# save result
cv2.imwrite("lena_centered.jpg", result)


enter image description here


在此处输入图片说明

回答by sivi

Like this (Padding is called borders on openCV):

像这样(填充在 openCV 上称为边框):

BLUE = [255,255,255]
constant= cv2.copyMakeBorder(image.copy(),10,10,10,10,cv2.BORDER_CONSTANT,value=BLUE)

And blue can become white even

蓝色甚至可以变成白色

source: https://docs.opencv.org/3.4/da/d0c/tutorial_bounding_rects_circles.html

来源:https: //docs.opencv.org/3.4/da/d0c/tutorial_bounding_rects_circles.html

回答by George Sotiropoulos

As I do not see an accepted answer, and also the fact that one has to determine the top, bottom, left, right of the function, I have bellow what worked for me easily. Taken from: https://jdhao.github.io/2017/11/06/resize-image-to-square-with-padding/

由于我没有看到可接受的答案,而且还必须确定函数的顶部、底部、左侧、右侧,因此我很容易找到对我有用的方法。摘自:https: //jdhao.github.io/2017/11/06/resize-image-to-square-with-padding/

import cv2

desired_size = 368
im_pth = "/home/jdhao/test.jpg"

im = cv2.imread(im_pth)
old_size = im.shape[:2] # old_size is in (height, width) format

ratio = float(desired_size)/max(old_size)
new_size = tuple([int(x*ratio) for x in old_size])

# new_size should be in (width, height) format

im = cv2.resize(im, (new_size[1], new_size[0]))

delta_w = desired_size - new_size[1]
delta_h = desired_size - new_size[0]
top, bottom = delta_h//2, delta_h-(delta_h//2)
left, right = delta_w//2, delta_w-(delta_w//2)

color = [0, 0, 0]
new_im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT,
    value=color)

cv2.imshow("image", new_im)
cv2.waitKey(0)
cv2.destroyAllWindows()

回答by Ismael EL ATIFI

Here is a function doing all for you :

这是一个为您完成所有工作的功能:

import cv2


def pad_images_to_same_size(images):
    """
    :param images: sequence of images
    :return: list of images padded so that all images have same width and height (max width and height are used)
    """
    width_max = 0
    height_max = 0
    for img in images:
        h, w = img.shape[:2]
        width_max = max(width_max, w)
        height_max = max(height_max, h)

    images_padded = []
    for img in images:
        h, w = img.shape[:2]
        diff_vert = height_max - h
        pad_top = diff_vert//2
        pad_bottom = diff_vert - pad_top
        diff_hori = width_max - w
        pad_left = diff_hori//2
        pad_right = diff_hori - pad_left
        img_padded = cv2.copyMakeBorder(img, pad_top, pad_bottom, pad_left, pad_right, cv2.BORDER_CONSTANT, value=0)
        assert img_padded.shape[:2] == (height_max, width_max)
        images_padded.append(img_padded)

    return images_padded

回答by Wei Li

try to use this function:

尝试使用此功能:

from PIL import Image, ImageOps


def padding(img, expected_size):
    desired_size = expected_size
    delta_width = desired_size - img.size[0]
    delta_height = desired_size - img.size[1]
    pad_width = delta_width // 2
    pad_height = delta_height // 2
    padding = (pad_width, pad_height, delta_width - pad_width, delta_height - pad_height)
    return ImageOps.expand(img, padding)


def resize_with_padding(img, expected_size):
    img.thumbnail((expected_size[0], expected_size[1]))
    # print(img.size)
    delta_width = expected_size[0] - img.size[0]
    delta_height = expected_size[1] - img.size[1]
    pad_width = delta_width // 2
    pad_height = delta_height // 2
    padding = (pad_width, pad_height, delta_width - pad_width, delta_height - pad_height)
    return ImageOps.expand(img, padding)


if __name__ == "__main__":
    img = Image.open("./demo.jpg")
    print(img)
    img = resize_with_padding(img, (500, 400))
    print(img.size)
    img.show()
    img.save("resized_img.jpg")

raw image

原始图像

after resizing with padding

使用填充调整大小后

see https://gist.github.com/BIGBALLON/cb6ab73f6aaaa068ab6756611bb324b2

https://gist.github.com/BIGBALLON/cb6ab73f6aaaa068ab6756611bb324b2