Home > Net >  Using Python- How to resize a cropped image to meet an aspect ratio while not exceeding original ima
Using Python- How to resize a cropped image to meet an aspect ratio while not exceeding original ima

Time:12-24

Iam using an object detection algorithm to detect objects in an image. The code is as below. Image used is of a car as below.

I would like to crop the original image to keep only the object detected in the image PLUS whatever is necessary to maintain aspect ratio between 4/3 and 16/9.

The box around the car is already deduced from below algorithm [variable is box] and the image dimensions are [variable is height,width] in below code.

If we were to do this manually, it would be cumbersome due to the multiple iterations required, as an example: we have to ensure that resizing does not extend beyond the original image size.

There are 3 images included below, the original image, the modified image with car detected, and the resized image to meet a aspect ratio range.(4/3 to 16/9)

Is there an existing function within python to accomplish this task. Hence, resizing/increasing box dimensions from [91, 90, 226, 158] to the minimum necessary amount to be within the limits of original image size 183x275 while maintaining the aspect ratio

Thanks in advance.

CODE:

import cv2
import matplotlib.pyplot as plt
import cvlib as cv
from cvlib.object_detection import draw_bbox
imagepath='/home/usr/Desktop/car.jpeg'
img = cv2.imread(imagepath)


####STEP 1
img1 = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)

box, label, count = cv.detect_common_objects(img)
output = draw_bbox(img, box, label, count)    
output = cv2.cvtColor(output,cv2.COLOR_BGR2RGB)
plt.figure(figsize=(10,10))
plt.axis('off')
plt.imshow(output)
plt.show()

print("Number of objects in this image are "  str(len(label)))

height,width,_=img1.shape

print(height,width)

print(box)
#box size is [91, 90, 226, 158] (w1,h1,w2,h2)
#image size is 183x275 (heightxwidth)



#STEP2 (cropping original image to car dimensions as per box size)
crop_img = img[90:158, 91:226]
cv2.imshow("cropped", crop_img)
cv2.waitKey(0)

Image Example:

enter image description here

Detect Object (Step1)

enter image description here

Crop Image (Step2)

enter image description here

Expected Outcome(Step3)

enter image description here

CodePudding user response:

The below code crops the image to required coordinates, then increases its size to match the aspect ratio depending if its >16/9 or <4/3. Advantage of this method is that it will not crop the centre object (car) when it resizes the image and corrects aspect ratio, and will increase left side of image if there is no space to increase in right side (and viceversa,for height and width) to achieve the Aspect ratio

import cv2
import math
import sys
imagepath=('/home/usr/Desktop/filename.jpeg')
img=cv2.imread(imagepath)
h,w,_=img.shape#height and width of original image


#Dimensions of car or object you want to crop (See step 2 in question)
crop_dimensions=[96, 56, 602, 686] #w1,h1,w2,h2

def cropimage(crop_dimensions,imgx):
    crop_img = imgx[crop_dimensions[1]:crop_dimensions[3], crop_dimensions[0]:crop_dimensions[2]]
    return crop_img

crop_img=cropimage(crop_dimensions,img)
height,width,_=crop_img.shape #height and width of cropped image



if width/height>16/9 or width/height<4/3:
    crop_centrepoint = ((crop_dimensions[2] - crop_dimensions[0])/2, (crop_dimensions[3] - crop_dimensions[1])/2) 
    print(crop_centrepoint) #Centre point of cropped image 

    if width/height<4/3:
        print('<4/3')

        newwidth=4/3*height
        newheight=height

        additionalwidth=newwidth-width

        w1maxadditional = crop_dimensions[0] - 0 #distance from cropped image to left edge (0) 
        w2maxadditional=w-crop_dimensions[2]#distance between cropped image and right end

        if w2maxadditional > additionalwidth/2:
            correction2=0
            w2=(additionalwidth/2)
        else:
            correction2=abs(w2maxadditional-(additionalwidth/2))
            w2=w2maxadditional

        if w1maxadditional > additionalwidth/2:
            correction1=0
            w1=(additionalwidth/2) correction1
        else:
            correction1=abs(w2maxadditional-(additionalwidth/2))
            w1=w1maxadditional

        w1=w1 correction2
        w2 = w2 correction1
        if w1>w1maxadditional:
            w1=w1maxadditional
        if w2>w2maxadditional:
            w2=w2maxadditional

        w1 = crop_dimensions[0] - w1
        w2 = w2   crop_dimensions[2]
        h1=crop_dimensions[1]
        h2=crop_dimensions[3]

    if width / height > 16/9:
        print('>16/9')

        newheight = width * 9 / 16
        newwidth = width

        additionalheight = newheight - height

        h1maxadditional = crop_dimensions[1] - 0  # distance from cropped image to top edge

        h2maxadditional = h - crop_dimensions[3]  # distance between cropped image to bottom end

        if h2maxadditional > additionalheight / 2:
            correction2 = 0
            h2 = (additionalheight / 2)
        else:
            correction2 = abs(h2maxadditional - (additionalheight / 2))
            h2 = h2maxadditional

        if h1maxadditional > additionalheight / 2:
            correction1 = 0
            h1 = (additionalheight / 2)   correction1
        else:
            correction1 = abs(h2maxadditional - (additionalheight / 2))
            h1 = h1maxadditional

        h1 = h1   correction2
        h2 = h2   correction1
        if h1 > h1maxadditional:
            h1 = h1maxadditional
        if h2 > h2maxadditional:
            h2 = h2maxadditional


        h1 = crop_dimensions[1] - h1
        h2 = h2   crop_dimensions[3]

        w1 = crop_dimensions[0]
        w2 = crop_dimensions[2]

else:
    [w1,h1,w2,h2]=crop_dimensions 

#Rounding down because cropimage function takes integers
w1=math.trunc(w1)
h1=math.trunc(h1)
w2=math.trunc(w2)
h2=math.trunc(h2)




new_image=cropimage([w1,h1,w2,h2],img)

cv2.imshow('img',new_image)
cv2.waitKey(0)
  • Related