# Scaling (stretching / enlarging / shrinking)
# PIL
from PIL import Image
image_pil = Image.open("image.png")
width, height = image_pil.size
scaled_image = image_pil.resize((new_width, new_hight))
#OpenCV
import cv2
image_cv = cv2.imread("image.png")
scaled_image = cv2.resize(image_cv,None,fx=2, fy=1, interpolation = cv2.INTER_NEAREST )
# Translation (Shifting image horizontally / vertically / diagnally)
# PIL
tx = 100 # 100 pixels right horizontally
ty = 0
translated_image_cutoff = image_pil.transform(image_pil.size, Image.AFFINE, (1, 0, tx, 0, 1, ty), resample=Image.BICUBIC, fill=1)
translated_image_whole = image_pil.transform((image_pil.width + tx, image_pil.height + ty), Image.AFFINE, (1, 0, tx, 0, 1, ty), resample=Image.BICUBIC, fill=1)
# OpenCV
tx = 100 # 100 pixel right horizontally
ty = 0
M = np.float32([[1, 0, tx], [0, 1, ty]])
rows, cols, _ = image_cv.shape
translated_image_cutoff = cv2.warpAffine(image_cv, M, (cols, rows))
translated_image_whole = cv2.warpAffine(image_cv, M, (cols + tx, rows + ty))
# Rotation
# PIL
theta = 45
rotated_image = image_pil.rotate(theta)
# OpenCV
theta = 45.0
M = cv2.getRotationMatrix2D(center=(3, 3), angle=theta, scale=1)
rotated_image = cv2.warpAffine(image_cv, M, (6, 6))
# Adding gaussian noise
# only convert PIL image to numpy array. OpenCV image is by default in numpy
Noise = np.random.normal(0, 20, (height, width, 3)).astype(np.uint8)
image_pil = = np.array(image_pil)
additive_noisy_image = image_pil[:,:,:3] + Noise
multiplicative_noisy_image = image_pil[:,:,:3] * Noise