opencv 为图像添加填充以使其形状相同

jmo0nnb3  于 2023-02-09  发布在  其他
关注(0)|答案(9)|浏览(159)

我有一组大小不同的图像(45,50,3), (69,34,3), (34,98,3)。我想按如下方式向这些图像添加填充:
取整个图像的最大宽度和长度,然后把图像的大小

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)

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

9jyewag0

9jyewag01#

下面是一个函数,它可以为您完成所有任务:

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
nqwrtyyt

nqwrtyyt2#

只需使用Pillow的crop_pad(),它会自动调整大小,并在需要的地方添加“零”填充(rgb=(0,0,0)/ black),而不会缩放图片。

from PIL import Image

img = Image.open(your_file_path)
img.crop_pad((width, height))
polkgigr

polkgigr3#

在这里,一行代码就可以完成

from PIL import Image
from PIL import ImageOps
image = Image.open("demo.jpg").convert("RGB")
ImageOps.pad(image,(100,100)).save('imaged-with-border.png')

这将使我的图像保持在100x100中,并使用zero填充保持其纵横比

ou6hu8tu

ou6hu8tu4#

这是我能做的最好的了,只适用于白色图像

def resize_with_padding(image, size=(224,224)):
    '''
    Resizes a black and white image to the specified size, 
    adding padding to preserve the aspect ratio.
    '''
    # Get the height and width of the image
    height, width = image.shape
    
    # Calculate the aspect ratio of the image
    aspect_ratio = height / width
    
    # Calculate the new height and width after resizing to (224,224)
    new_height, new_width = size
    if aspect_ratio > 1:
        new_width = int(new_height / aspect_ratio)
    else:
        new_height = int(new_width * aspect_ratio)
        
    # Resize the image
    resized_image = cv2.resize(image, (new_width, new_height), interpolation = cv2.INTER_NEAREST)
    
    # Create a black image with the target size
    padded_image = np.zeros((224,224), dtype=np.uint8)
    
    # Calculate the number of rows/columns to add as padding
    padding_rows = (224 - new_height) // 2
    padding_cols = (224 - new_width) // 2
    
    # Add the resized image to the padded image, with padding on the left and right sides
    padded_image[padding_rows:padding_rows+new_height, padding_cols:padding_cols+new_width] = resized_image
    
    return padded_image
yhived7q

yhived7q5#

您可以使用:

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

其中src是源图像,topbottomleftright是图像周围的填充。
您可以在while循环中使用图像的max(sizes)-size值来为每个图像添加填充。bordertype可以是以下类型之一:

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

cv2.copyMakeBorder教程

eagi6jfj

eagi6jfj6#

在Python/OpenCV/Numpy中还有另一种方法。它使用Numpy切片将输入图像复制到一个新的图像中,该图像具有所需的输出大小和给定的偏移量。这里我计算偏移量来进行中心填充。我认为使用宽度、高度、xoffset、yoffset比使用每侧填充多少更容易做到这一点。
输入:

import cv2
import numpy as np

# read image
img = cv2.imread('lena.jpg')
old_image_height, old_image_width, channels = img.shape

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

# compute center offset
x_center = (new_image_width - old_image_width) // 2
y_center = (new_image_height - old_image_height) // 2

# copy img image into center of result image
result[y_center:y_center+old_image_height, 
       x_center:x_center+old_image_width] = img

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

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

krcsximq

krcsximq7#

尝试使用此功能:

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

原始图像

使用填充调整大小后

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

moiiocjp

moiiocjp8#

如下所示(填充在openCV上称为边框):

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

蓝色甚至可以变成白色
来源:https://docs.opencv.org/3.4/da/d0c/tutorial_bounding_rects_circles.html

9vw9lbht

9vw9lbht9#

由于我没有看到一个公认的答案,也是一个事实,即必须确定顶部,底部,左侧,右侧的功能,我有below什么工作对我来说很容易。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()

相关问题