Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add padding to images to get them into the same shape

l have a dataset of 100, 000 images of different sizes.

(36,77), (56,100), (89,14), (35,67), (78,34), (90,65),(96,38).......

l want to add padding to these images so that to get them into the same shape. To do so l loop over the whole dataset and take the max_width and max_height then make the images into this size. In this sample for instance max_height= 96 and max_width= 100. So my images will have all the shape of (96,100). However l get different shapes :

(96, 100, 3)
(97, 101, 3)
(97, 100, 3)
(96, 101, 3)
(96, 100, 3)
(97, 100, 3)
(97, 101, 3)
(97, 100, 3)
(97, 100, 3)
(96, 101, 3)
(97, 101, 3)
(96, 101, 3)
(96, 100, 3)
(97, 100, 3)
(96, 101, 3)

What's wrong with my code

from __future__ import division
import cv2
import numpy as np
import csv
import os
import pandas as pd
import glob
from matplotlib import pyplot as plt

def max_width_height(path):
    os.chdir(path)
    WIDTH=[]
    HEIGHT=[]

    images_name = glob.glob("*.png")
    set_img = set([x.rsplit('.', 1)[0] for x in images_name])
    for img in set_img:
        img_cv = cv2.imread(path+'/'+img+'.png')
        h=img_cv.shape[0]
        w=img_cv.shape[1]
        WIDTH.append(w)
        HEIGHT.append(h)
    max_width=max(WIDTH)
    max_height=max(HEIGHT)
    return max_height,max_width
def add_padding(max_height,max_width):

    path_char = '/cropped_images'
    output = 'dataset/'
    abby_label = []
    reference = []
    os.chdir(path_char)
    img_char= glob.glob("*.png")

    set_img_char = set([x.rsplit('.', 1)[0] for x in img_char])

    images = []
    size= []
    for img in img_char:
        img_cv = cv2.imread(path_char+'/'+img)
        h,w=img_cv.shape[0:2]

        width_diff=max_width-w
        height_diff=max_height-h

        left= width_diff/2
        right=width_diff/2
        top=height_diff/2
        bottom=height_diff/2
        if isinstance(left,float):
            left=int(left)
            right=left+1
        if isinstance(top,float):
            top=int(top)
            bottom=top+1

        white_pixels = [255, 255, 255]
        black_pixels = [0, 0, 0]


        constant = cv2.copyMakeBorder(img_cv,top,left,right,bottom, cv2.BORDER_CONSTANT, value=white_pixels)
        cv2.imwrite(output+img,constant)
        size.append(constant.shape)
        constant2 = cv2.copyMakeBorder(img_cv,top,left,right,bottom, cv2.BORDER_CONSTANT, value=black_pixels)
        cv2.imwrite(output+img,constant2)


        label, sep,rest = img.partition('_')
        abby_label.append(label)
        reference.append(rest)




    df = pd.DataFrame({'abby_label': abby_label, 'reference': reference})
    df.to_csv('abby_labels.csv')
    df2=pd.DataFrame({'dimension':size})
    df2.to_csv('dimension.csv')

    h,w=max_width_height(path)
    print(h,w)
    x=add_padding(h,w)
like image 807
vincent Avatar asked Apr 18 '17 11:04

vincent


People also ask

How do I resize an image using padding in Python?

If you want to resize an image but do not want to change the aspect ratio or trim it, you can adjust the size by adding padding to the top, bottom, left, and right of the image. You can pad an image by using new() and paste() of the Python image processing library Pillow (PIL).

How do I padding an image in CSS?

The CSS padding properties are used to generate space around an element's content, inside of any defined borders. With CSS, you have full control over the padding. There are properties for setting the padding for each side of an element (top, right, bottom, and left).


2 Answers

The problem is here:

left= width_diff/2
right=width_diff/2
top=height_diff/2
bottom=height_diff/2

This will lead to different final width or height depending if the width_diff or height_diff is divisible by 2. You have a workaround implemented, but that will only work for Python 3 while you are apparently using Python 2.

You can fix this in this way:

left=width_diff/2
right=width_diff - left
top=height_diff/2
bottom=height_diff - top

In this way you will make sure that

  • left + right = width_diff
  • top + bottom = height_diff

Note that this in particular applicable to Python 2, you might be interested to read Python integer division yields float. My suggestion is to use floor division, so that your code is less vulnerable to the Python 2 and Python 3 differences.

left=width_diff//2
right=width_diff - left
top=height_diff//2
bottom=height_diff - top
like image 65
Antonio Avatar answered Sep 24 '22 01:09

Antonio


It looks like a rounding error for images with an odd/even number of pixels.

If width_diff is an even number, it is ok to divide by 2 as you are doing it. But if it's odd, you need to add width_diff//2 to one side and (width_diff//2) + 1 to the other. The same applies to height.

Or just run the program in debug mode (since you have the images to be analyzed) and make sure images with odd/even dimensions are being handled the way you expect it.

like image 42
jberrio Avatar answered Sep 25 '22 01:09

jberrio