Skillversitas

Geometric Transformations

Geometric transforms warp an image's geometry - resizing, rotating, flipping, and the general affine and perspective mappings. The two workhorses are warpAffine (rotations, translations, scaling, shears described by a 2x3 matrix) and warpPerspective (the full 3x3 homography that can "flatten" a photo of a document). Getting the transformation matrix right is the skill; the warp call itself is one line.

Resizing

import cv2

img = cv2.imread("photo.jpg")
print(img.shape)                  # e.g. (1080, 1920, 3)

# explicit size
small = cv2.resize(img, (480, 270))

# scale factor instead of size
half = cv2.resize(img, None, fx=0.5, fy=0.5)

# the interpolation flag matters
nearest = cv2.resize(img, (480, 270), interpolation=cv2.INTER_NEAREST)
linear = cv2.resize(img, (480, 270), interpolation=cv2.INTER_LINEAR)
area = cv2.resize(img, (480, 270), interpolation=cv2.INTER_AREA)
cubic = cv2.resize(img, (480, 270), interpolation=cv2.INTER_CUBIC)

cv2.imwrite("resized.jpg", area)

Pass a size tuple, or None with fx/fy scale factors. The interpolation choice is a real decision: INTER_AREA is the right default for downsampling (it averages, avoiding aliasing), INTER_LINEAR is the general default for upsampling, INTER_CUBIC is smoother for large upscales, and INTER_NEAREST is fast and preserves exact values - the only right choice for masks and label maps, where bilinear would invent intermediate values.

Flip and Transpose

import cv2

img = cv2.imread("photo.jpg")

fl = cv2.flip(img, 1)      # horizontal (left-right) - the "mirror selfie"
fr = cv2.flip(img, 0)      # vertical (top-bottom)
both = cv2.flip(img, -1)   # both axes

# transpose is a matrix transpose - for 2-D it is a flip over the main diagonal
t = cv2.transpose(img)
# transpose + horizontal flip == 90-degree rotation
rot90 = cv2.flip(cv2.transpose(img), 1)

flip with axis 1 mirrors horizontally - the standard "undo the selfie camera" fix, and the right move when a face model was trained on non-mirrored faces. transpose swaps the matrix axes, and the transpose-plus-flip combination is a free 90-degree rotation when you need one without building a matrix.

Affine: Rotation, Translation, Scale

import cv2
import numpy as np

img = cv2.imread("photo.jpg")
h, w = img.shape[:2]

# rotate 30 degrees around the image center
M = cv2.getRotationMatrix2D((w / 2, h / 2), 30, 1.0)
rotated = cv2.warpAffine(img, M, (w, h))

# the scale parameter > 1 zooms in, < 1 zooms out
zoom = cv2.warpAffine(img, cv2.getRotationMatrix2D((w/2, h/2), 0, 1.5), (w, h))

# translation + shear is just a different 2x3 matrix
M2 = np.float32([[1, 0.3, 20],   # shear x by 0.3, shift right 20 px
                 [0, 1, 0]])
sheared = cv2.warpAffine(img, M2, (w, h))

cv2.imwrite("rotated.jpg", rotated)

getRotationMatrix2D(center, angle, scale) builds the 2x3 affine matrix for a rotation (counter-clockwise for positive angles) about an arbitrary center, with an optional uniform scale. warpAffine applies it to the whole image, producing a new canvas of the size you specify - the corners of a rotated image fall outside the canvas unless you recompute the new bounds, which is the classic "rotated image loses its corners" fix.

Perspective: The Document Flatten

import cv2
import numpy as np

img = cv2.imread("doc_photo.jpg")

# the four corners of the document AS SEEN in the photo
src = np.float32([[180, 200], [720, 160], [760, 820], [140, 860]])
# where you want them: a clean rectangle
dst = np.float32([[0, 0], [600, 0], [600, 800], [0, 800]])

M = cv2.getPerspectiveTransform(src, dst)
flat = cv2.warpPerspective(img, M, (600, 800))
cv2.imwrite("doc_flat.jpg", flat)

A perspective transform is a 3x3 homography - it can model the camera looking at a plane at an angle, so it "undoes" the trapezoid and flattens a photographed document, license plate, or whiteboard into a front-on rectangle. The recipe: locate the four corners of the plane in the image (manually, with the mouse-callback chapter's click tool, or by detecting the largest contour), pick the destination rectangle, and let getPerspectiveTransform solve for the matrix. Corner order matters - opposite corners must stay opposite, or the result is twisted.

Summary

Resize with cv2.resize - INTER_AREA down, INTER_LINEAR up, INTER_NEAREST for masks. Mirror with flip, rotate and scale with getRotationMatrix2D plus warpAffine (any 2x3 affine: rotation, translation, scale, shear), and flatten planar objects with getPerspectiveTransform plus warpPerspective from four source corners to a destination rectangle. The skill is matrix construction - knowing which transform class your geometry needs and getting the corners or center right - because the warp call itself is one line.