Add padding to images to get them into the same shape

前端 未结 6 1725
野趣味
野趣味 2020-12-31 04:21

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:

Take the max width and leng

相关标签:
6条回答
  • 2020-12-31 04:27

    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
    
    
    0 讨论(0)
  • 2020-12-31 04:38

    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.

    Input:

    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)
    


    0 讨论(0)
  • 2020-12-31 04:38

    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/

    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()
    
    0 讨论(0)
  • 2020-12-31 04:41

    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

    0 讨论(0)
  • 2020-12-31 04:42

    Like this (Padding is called borders on 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

    0 讨论(0)
  • 2020-12-31 04:50

    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.

    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:

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

    copyMakeBorder tutorial

    0 讨论(0)
提交回复
热议问题