Add Padding to Images to Get Them into the Same Shape

Add padding to images to get them into the same shape

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

Add padding to object in 4-channel image

The issue has been already addressed and solved here:

http://answers.opencv.org/question/90229/add-padding-to-object-in-4-channel-image/

python: Show numpy padded image by opencv

You can resolve the problem by reading with cv2.imread and then convert to the gray-scale (black-and-white) image to the cv2.COLOR_BGR2GRAY

import cv2
import numpy as np

img = cv2.imread("input.jpg")
gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
resized_digit = cv2.resize(gry, (18, 18))
padded_digit = np.pad(resized_digit, ((5, 5), (5, 5)), "constant", constant_values=0)
cv2.imshow("padded_digit", padded_digit)
cv2.waitKey(0)

imread loads the image in BGR fashion, then you can convert it to the gray-scale using COLOR_BGR2GRAY.

You can also use copyMakeBorder (source) instead of np.pad. Using np.pad is not wrong, but opencv is more suitable for image operations, since you are using opencv functions like imshow, waitKey etc.

For instance:

import cv2

img = cv2.imread("input.jpg")
gry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
resized_digit = cv2.resize(gry, (18, 18))
padded_digit = cv2.copyMakeBorder(resized_digit, 5, 5, 5, 5, cv2.BORDER_CONSTANT, value=0)
cv2.imshow("padded_digit", padded_digit)
cv2.waitKey(0)

You can check the two image equality by comparing their shapes. Both of them print(padded_digit.shape) will be (28, 28)

Add transparent padding to image [closed]

This code works for me:

for imagePath in os.listdir(inPath):

# imagePath contains name of the image
inputPath = os.path.join(inPath, imagePath)

# inputPath contains the full directory name
img = Image.open(inputPath)

# fullOutPath contains the path of the output
fullOutPath = os.path.join(outPath, imagePath)

# add padding
img = ImageOps.expand(img, border=(10,10,10,10), fill=(0,0,0,0) )

# image that needs to be generated
img.save(fullOutPath)

print(fullOutPath)

how to pad images of different sizes and making them of same size by putting the original image in the middle in matlab?

You can use padarray to specify how many black pixels you want to add around the edge of the image.

Resizing and Padding Image with specific height and width in python OpenCV gives errors and inaccurate results

As I wrote in my comment above, the indentation is wrong: the for image in images loop ends with the calculation of the ratio. Then you process just the last image in the images list. Last has nothing to do with the file order in your folder, as walk returns the files in arbitrary order.

Following is the code with correct indentation. It works perfectly:

import sys
import os
import numpy as np
from os import walk
import cv2

# width to resize
width = int(sys.argv[1])
# height to resize
height = int(sys.argv[2])
# location of the input dataset
input_dir = sys.argv[3]
# location of the output dataset
out_dir = sys.argv[4]

if len(sys.argv) != 5:
print("Please specify width, height, input directory and output directory.")
sys.exit(0)

print("Working...")

# get all the pictures in directory
images = []
ext = (".jpeg", ".jpg", ".png")

for (dirpath, dirnames, filenames) in walk(input_dir):
for filename in filenames:
if filename.endswith(ext):
images.append(os.path.join(dirpath, filename))
print(filename)

for image in images:
img = cv2.imread(image, cv2.IMREAD_UNCHANGED)

h, w = img.shape[:2]
pad_bottom, pad_right = 0, 0
ratio = w / h

if h > height or w > width:
# shrinking image algorithm
interp = cv2.INTER_AREA
else:
# stretching image algorithm
interp = cv2.INTER_CUBIC

w = width
h = round(w / ratio)
if h > height:
h = height
w = round(h * ratio)
pad_bottom = abs(height - h)
pad_right = abs(width - w)

scaled_img = cv2.resize(img, (w, h), interpolation=interp)
padded_img = cv2.copyMakeBorder(
scaled_img,0,pad_bottom,0,pad_right,borderType=cv2.BORDER_CONSTANT,value=[0,0,0])

cv2.imwrite(os.path.join(out_dir, os.path.basename(image)), padded_img)

print("Completed!")

How to automatically add zero padding in a image to expected shape?

For padding images to a target shape, you can use tf.image.resize_image_with_crop_or_pad(). This op crops the image if it is larger than target size, and pads (evenly on all sides) with zeros if it is smaller.

>>> a = tf.ones([3, 4, 3])
>>> tf.image.resize_image_with_crop_or_pad(a, 5, 5)
<tf.Tensor 'Squeeze:0' shape=(5, 5, 3) dtype=float32>

If you want to use padding, you can define a function to calculate padding amount using the difference between desired size and the shape of the tensor (tf.shape()) and pad the difference, check this answer for padding.

Create a padded image in python

From the plt.imshow docs:

X : array-like or PIL image

The image data. Supported array shapes are:

  • (M, N): an image with scalar data. The values are mapped to colors using normalization and a colormap. . . .

Normalization means that the colors are "spread out" so that the minimum is black and max is white. So those np.zeros are making the minimum 0 (and the border black) and making everything else lighter to compensate. This should work to fix it (I think)

padded = np.pad(input, 
pad_width = 1,
mode = 'minimum') # or mode = "maximum' for a white border

If you absolutely need a border of 0, you can do:

padded = np.pad(input - input.min(), 
pad_width = 1,
mode = 'constant')

That changes the range of your original picture to start a 0, so the normalization should be the same.



Related Topics



Leave a reply



Submit