In this post, I will explain how to read multiple images from a folder, resize them, save them in a new folder (retaining the same names in the file) and display them one by one. All the images will be at first, cropped in centre and then will be placed in the centre of a canvas. The image background is removed using grayscale, Gaussian blur, Otsu’s threshold.

First, we will import the required libraries.

import cv2
import glob
import os
import numpy as np

Now to resize images, we will make a new output folder, read images from the input folder one by one using a for loop, resize the images, save them in the output folder and display resized images one by one.

import cv2
import glob
import os
import numpy as np

canvas = 256
inputFolder = 'images'
folderLen = len(inputFolder)

if not os.path.exists('Resized'):
   os.makedirs('Resized')
   
   
def image_resize(image, width = None, height = None, inter = cv2.INTER_AREA):
    dim = None
    (h, w) = image.shape[:2]
    if width is None and height is None:
        return image
    if width is None:
        r = height / float(h)
        dim = (int(w * r), height)
    else:
        r = width / float(w)
        dim = (width, int(h * r))
    # resize the image
    resized = cv2.resize(image, dim, interpolation = inter)
    return resized

i=0
for imgg in glob.glob(inputFolder + "/*.jpg"):
    
    # Load image, grayscale, Gaussian blur, Otsu's threshold
    image = cv2.imread(imgg)
    
    # Apply Binary Thresholding to remove background
    ret,image = cv2.threshold(image,200,255,cv2.THRESH_BINARY)
    
    original = image.copy()
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blur = cv2.GaussianBlur(gray, (25,25), 0)
    thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

    # Perform morph operations, first open to remove noise, then close to combine
    noise_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
    opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, noise_kernel, iterations=2)
    close_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7,7))
    close = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, close_kernel, iterations=3)

    # Find enclosing boundingbox and crop ROI
    coords = cv2.findNonZero(close)
    x,y,w,h = cv2.boundingRect(coords)
    cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 2)
    crop = original[y:y+h, x:x+w]
    cv2.imwrite('crop.png', crop)

    white_canvas = np.zeros([canvas,canvas,1],dtype=np.uint8)
    white_canvas.fill(255)
    cv2.imwrite('white.png', white_canvas)

    # load resized image as grayscale
    img = cv2.imread('crop.png', cv2.IMREAD_GRAYSCALE)
    img = image_resize(img, width = canvas)
    h, w = img.shape

    # load background image as grayscale
    back = cv2.imread('white.png', cv2.IMREAD_GRAYSCALE)
    hh, ww = back.shape

    # compute xoff and yoff for placement of upper left corner of resized image   
    yoff = round((hh-h)/2)
    xoff = round((ww-w)/2)

    # use numpy indexing to place the resized image in the center of background image
    result = back.copy()
    result[yoff:yoff+h, xoff:xoff+w] = img
    result = cv2.cvtColor(result,cv2.COLOR_GRAY2RGB)

    # save resulting centered image
    cv2.imwrite("Resized" + imgg[folderLen:], result)
    i += 1    

Now in this code, we are reading images form inputFolder, Creating a new folder Resized.

i = 0 will be used to rename images that we save in Resized folder.

In for loop, we are reading images one by one using cv2.imread

cv2.resize is used to resize the images.

cv2.imwrite is used to write the resized images to the output folder, i = 0 that we defined earlier is used here to rename the images.

image_resize function will be used to resize the image, keeping the aspect ratio.

When we will read the input images in ‘img’, it will also contain the name of the folder in which they are located, i.e, complete path of the image, and to get the name of image we have to remove the name of input folder from it so folderLen is length of the name of inputFolder, and in cv2.imwrite we are removing it and only getting the names of images at img[folderLen :].