snahl
snahl

Reputation: 503

How can an Image crop, resize be expressed as an affine transformation?

I've got an image that gets cropped and resized to the image input size. To my understanding this is the same as an affine transformation.

I am trying to simplify the code below so it does the same by using the function: (something like the example below at the end).

scipy.ndimage.affine_transform() 

The trouble is I don't really understand the parameters of that function, hence I am not able to achieve an elegant one-liner with the affine_transform() function. Providing and explaining the solution for the code might help me to better understand this affine_transform() function.

import numpy as npy
import PIL.Image
import scipy.misc as smc
import scipy.ndimage as snd

#crop factor
s = 1.045    

#input image
img2crop = npy.float32(PIL.Image.open("input_image.jpg)")
h, w = img2crop.shape[:2]    #get the dimensions of the input image

#Box-crop values: calculate new crop Dimensions based on 's'
wcrop =  float(w) / (s)
hcrop =  float(wcrop) / (float(w) / float(h))
hcrop = int(round(hcrop))
wcrop = int(round(wcrop))

#crop applied from top-left to right and bottom
b_left = 0
b_top = 0
b_width = wcrop
b_height = hcrop
b_box = (b_left, b_top, b_width, b_height)

#cropped region
region = img2crop.crop(b_box)

#resize cropped region back to input size
resized_region = smc.imresize(region, (h, w), interp='nearest', mode=None)
#save cropped and resized region as new file in output folder
PIL.Image.fromarray(np.uint8(resized_newregion)).save("output_image.jpg")

Question: How can the code above doing a crop and resize be expressed as an affine transformation?

This example crops evenly on all 4 sides, center oriented

s = 0.0065
cropped_and_resized_image = snd.affine_transform(input_image.jpg, [1-s,1-s,1], [h*s/2,w*s/2,0], order=1)
PIL.Image.fromarray(npy.uint8(cropped_and_resized_image)).save("output_image_at.jpg")

Thanks in advance for feedback.

Upvotes: 5

Views: 5164

Answers (2)

lzl jnu
lzl jnu

Reputation: 36

OpenCV implementation of crop image && resize to (des_width, des_height) using affine transform

import numpy as np
import cv2


def crop_resized_with_affine_transform(img_path, roi_xyxy, des_width, des_height):
    src_rgb = cv2.imread(img_path)

    '''
    image roi 
    (x0,y0)------------(x1,y1)
       |                  |
       |                  |
       |                  |
       |                  |
       |                  |
       |                  |
       |                  |
       |                  |
    (-,-)------------(x2, y2)
    '''
    src_points = [[roi_xyxy[0], roi_xyxy[1]], [roi_xyxy[2], roi_xyxy[1]], [roi_xyxy[2], roi_xyxy[3]]]
    src_points = np.array(src_points, dtype=np.float32)
                  
    des_points = [[0, 0], [des_width, 0], [des_width, des_height]]
    des_points = np.array(des_points, dtype=np.float32)

    M = cv2.getAffineTransform(src_points, des_points)
    crop_and_resized_with_affine_transform = cv2.warpAffine(src_rgb, M, (des_width, des_height))

    return crop_and_resized_with_affine_transform
    
    
def crop_resized(img_path, roi_xyxy, des_width, des_height):
    src_rgb = cv2.imread(img_path)    
    roi_img = src_rgb[roi_xyxy[1]:roi_xyxy[3], roi_xyxy[0]:roi_xyxy[2]]
    resized_roi_img = cv2.resize(roi_img, (des_width, des_height))
    
    return resized_roi_img

    

if __name__ == "__main__":
    '''
    Source image from 
    https://www.whitehouse.gov/wp-content/uploads/2021/04/P20210303AS-1901.jpg
    or
    https://en.wikipedia.org/wiki/Joe_Biden#/media/File:Joe_Biden_presidential_portrait.jpg
    '''
    img_path = "Joe_Biden_presidential_portrait.jpg"
    # xmin ymin xmax ymax
    roi_xyxy = [745, 265, 1675, 1520]
    des_width = 480
    des_height = 720
    crop_and_resized_with_affine_transform = crop_resized_with_affine_transform(img_path, roi_xyxy , des_width, des_height)
    resized_roi_img = crop_resized(img_path, roi_xyxy, des_width, des_height)
    cv2.imshow("crop_and_resized_with_affine_transform", crop_and_resized_with_affine_transform)
    cv2.imwrite("crop_and_resized_with_affine_transform.jpg", crop_and_resized_with_affine_transform)
    cv2.imshow("resized_roi_img", resized_roi_img)
    cv2.imwrite("resized_roi_img.jpg", resized_roi_img)
    cv2.waitKey(0)

Source image is Wiki:Joe_Biden_presidential_portrait.jpg

Upvotes: 0

Dmitriy R. Starson
Dmitriy R. Starson

Reputation: 1878

Here is OpenCV implementation

# OpenCV implementation of crop/resize using affine transform

import numpy as np
from matplotlib import pyplot as plt
%matplotlib inline
import cv2

src_rgb = cv2.imread('test_img.jpg')

# Source width and height in pixels
src_w_px = 640 
src_h_px = 480 

# Target width and height in pixels
res_w_px = 640
res_h_px = 480

# Scaling parameter
s = 2.0

Affine_Mat_w = [s, 0, res_w_px/2.0 - s*src_w_px/2.0]
Affine_Mat_h = [0, s, res_h_px/2.0 - s*src_h_px/2.0]

M = np.c_[ Affine_Mat_w, Affine_Mat_h].T 
res = cv2.warpAffine(src_rgb, M, (res_w_px, res_h_px))

# Showing the result
plt.figure(figsize=(15,6))
plt.subplot(121); plt.imshow(src_rgb); plt.title('Original image');
plt.subplot(122); plt.imshow(res); plt.title('Image warped Affine transform');

Upvotes: 1

Related Questions