Introduction
A linear transformation is a function between vector spaces that preserves vector addition and scalar multiplication. Linear transformations are fundamental to understanding how matrices manipulate geometric objects and are essential in computer graphics, machine learning, and data science.
Setup
Import required packages:
import numpy as np
import cv2 # OpenCV for image transformations
import matplotlib.pyplot as plt
A transformation is a function from one vector space to another that respects the underlying linear structure.
Notation : T : R 2 → R 3 T: \mathbb{R}^2 \rightarrow \mathbb{R}^3 T : R 2 → R 3
T T T is the transformation
R 2 \mathbb{R}^2 R 2 is the input space
R 3 \mathbb{R}^3 R 3 is the output space
T ( v ) = w T(v) = w T ( v ) = w means ”w w w is the image of v v v under transformation T T T “
Consider T : R 2 → R 3 T: \mathbb{R}^2 \rightarrow \mathbb{R}^3 T : R 2 → R 3 defined by:
T ( [ v 1 v 2 ] ) = [ 3 v 1 0 − 2 v 2 ] T\begin{pmatrix}
\begin{bmatrix}
v_1 \\
v_2
\end{bmatrix}
\end{pmatrix}=
\begin{bmatrix}
3v_1 \\
0 \\
-2v_2
\end{bmatrix} T ( [ v 1 v 2 ] ) = 3 v 1 0 − 2 v 2
Implementation in Python:
def T ( v ):
w = np.zeros(( 3 , 1 ))
w[ 0 , 0 ] = 3 * v[ 0 , 0 ]
w[ 2 , 0 ] = - 2 * v[ 1 , 0 ]
return w
v = np.array([[ 3 ], [ 5 ]])
w = T(v)
print ( "Original vector: \n " , v)
print ( " \n Result of transformation: \n " , w)
# Output:
# Original vector:
# [[3]
# [5]]
# Result of transformation:
# [[ 9.]
# [ 0.]
# [-10.]]
Definition
A transformation T T T is linear if it satisfies two properties:
Scalar Multiplication Property
T ( k v ) = k T ( v ) T(kv) = kT(v) T ( k v ) = k T ( v ) for any scalar k k k and vector v v v
Addition Property
T ( u + v ) = T ( u ) + T ( v ) T(u+v) = T(u) + T(v) T ( u + v ) = T ( u ) + T ( v ) for any vectors u u u and v v v
Verification Example
Prove that the transformation T T T above is linear:
Property 1: Scalar Multiplication
T ( k v ) = T ( [ k v 1 k v 2 ] ) = [ 3 k v 1 0 − 2 k v 2 ] = k [ 3 v 1 0 − 2 v 2 ] = k T ( v ) T(kv) = T\begin{pmatrix}
\begin{bmatrix}
kv_1 \\
kv_2
\end{bmatrix}
\end{pmatrix} =
\begin{bmatrix}
3kv_1 \\
0 \\
-2kv_2
\end{bmatrix} =
k\begin{bmatrix}
3v_1 \\
0 \\
-2v_2
\end{bmatrix} = kT(v) T ( k v ) = T ( [ k v 1 k v 2 ] ) = 3 k v 1 0 − 2 k v 2 = k 3 v 1 0 − 2 v 2 = k T ( v )
Property 2: Vector Addition
T ( u + v ) = [ 3 ( u 1 + v 1 ) 0 − 2 ( u 2 + v 2 ) ] = [ 3 u 1 0 − 2 u 2 ] + [ 3 v 1 0 − 2 v 2 ] = T ( u ) + T ( v ) T(u+v) =
\begin{bmatrix}
3(u_1+v_1) \\
0 \\
-2(u_2+v_2)
\end{bmatrix} =
\begin{bmatrix}
3u_1 \\
0 \\
-2u_2
\end{bmatrix} +
\begin{bmatrix}
3v_1 \\
0 \\
-2v_2
\end{bmatrix} = T(u)+T(v) T ( u + v ) = 3 ( u 1 + v 1 ) 0 − 2 ( u 2 + v 2 ) = 3 u 1 0 − 2 u 2 + 3 v 1 0 − 2 v 2 = T ( u ) + T ( v )
Testing in Python
u = np.array([[ 1 ], [ - 2 ]])
v = np.array([[ 2 ], [ 4 ]])
k = 7
# Test property 1
print ( "T(k*v): \n " , T(k * v))
print ( "k*T(v): \n " , k * T(v))
# Test property 2
print ( " \n T(u+v): \n " , T(u + v))
print ( "T(u)+T(v): \n " , T(u) + T(v))
Common linear transformations include rotations, reflections, scaling (dilations), shearing, and projections.
Key Theorem
Every linear transformation L : R m → R n L: \mathbb{R}^m \rightarrow \mathbb{R}^n L : R m → R n can be represented as matrix multiplication:
L ( v ) = A v L(v) = Av L ( v ) = A v
where A A A is an n × m n \times m n × m matrix.
Finding the Matrix
For transformation:
L ( [ v 1 v 2 ] ) = [ 3 v 1 0 − 2 v 2 ] L\begin{pmatrix}
\begin{bmatrix}
v_1 \\
v_2
\end{bmatrix}
\end{pmatrix}=
\begin{bmatrix}
3v_1 \\
0 \\
-2v_2
\end{bmatrix} L ( [ v 1 v 2 ] ) = 3 v 1 0 − 2 v 2
Find matrix A A A such that A v Av A v produces this result:
[ a 1 , 1 a 1 , 2 a 2 , 1 a 2 , 2 a 3 , 1 a 3 , 2 ] [ v 1 v 2 ] = [ 3 v 1 0 − 2 v 2 ] \begin{bmatrix}
a_{1,1} & a_{1,2} \\
a_{2,1} & a_{2,2} \\
a_{3,1} & a_{3,2}
\end{bmatrix}
\begin{bmatrix}
v_1 \\
v_2
\end{bmatrix}=
\begin{bmatrix}
3v_1 \\
0 \\
-2v_2
\end{bmatrix} a 1 , 1 a 2 , 1 a 3 , 1 a 1 , 2 a 2 , 2 a 3 , 2 [ v 1 v 2 ] = 3 v 1 0 − 2 v 2
Solution:
A = [ 3 0 0 0 0 − 2 ] A = \begin{bmatrix}
3 & 0 \\
0 & 0 \\
0 & -2
\end{bmatrix} A = 3 0 0 0 0 − 2
Implementation
def L ( v ):
A = np.array([[ 3 , 0 ],
[ 0 , 0 ],
[ 0 , - 2 ]])
print ( "Transformation matrix: \n " , A, " \n " )
w = A @ v
return w
v = np.array([[ 3 ], [ 5 ]])
w = L(v)
print ( "Original vector: \n " , v)
print ( " \n Result of transformation: \n " , w)
Fundamental Insight : Every linear transformation can be represented as matrix multiplication, creating a powerful connection between linear algebra and geometric transformations.
Understanding Standard Basis
To visualize transformations, apply them to standard basis vectors:
e 1 = [ 1 0 ] e_1 = \begin{bmatrix}1 \\ 0\end{bmatrix} e 1 = [ 1 0 ]
e 2 = [ 0 1 ] e_2 = \begin{bmatrix}0 \\ 1\end{bmatrix} e 2 = [ 0 1 ]
The transformation matrix is:
A = [ L ( e 1 ) L ( e 2 ) ] A = \begin{bmatrix}L(e_1) & L(e_2)\end{bmatrix} A = [ L ( e 1 ) L ( e 2 ) ]
Example 1: Horizontal Scaling
Scale horizontally by factor of 2:
e 1 → [ 2 0 ] e_1 \rightarrow \begin{bmatrix}2 \\ 0\end{bmatrix} e 1 → [ 2 0 ]
e 2 → [ 0 1 ] e_2 \rightarrow \begin{bmatrix}0 \\ 1\end{bmatrix} e 2 → [ 0 1 ] (unchanged)
def T_hscaling ( v ):
A = np.array([[ 2 , 0 ],
[ 0 , 1 ]])
w = A @ v
return w
e1 = np.array([[ 1 ], [ 0 ]])
e2 = np.array([[ 0 ], [ 1 ]])
def transform_vectors ( T , v1 , v2 ):
V = np.hstack((v1, v2))
W = T(V)
return W
result = transform_vectors(T_hscaling, e1, e2)
print ( "Transformation result: \n " , result)
# Output:
# [[2 0]
# [0 1]]
The transformation matrix for horizontal scaling by factor k k k is:
[ k 0 0 1 ] \begin{bmatrix}k & 0 \\ 0 & 1\end{bmatrix} [ k 0 0 1 ]
Example 2: Reflection about Y-axis
Reflect across the vertical axis:
e 1 → [ − 1 0 ] e_1 \rightarrow \begin{bmatrix}-1 \\ 0\end{bmatrix} e 1 → [ − 1 0 ]
e 2 → [ 0 1 ] e_2 \rightarrow \begin{bmatrix}0 \\ 1\end{bmatrix} e 2 → [ 0 1 ]
def T_reflection_yaxis ( v ):
A = np.array([[ - 1 , 0 ],
[ 0 , 1 ]])
w = A @ v
return w
result = transform_vectors(T_reflection_yaxis, e1, e2)
print ( "Reflection result: \n " , result)
# Output:
# [[-1 0]
# [ 0 1]]
Example 3: Rotation
Rotate by 90 degrees clockwise:
def T_rotation_90 ( v ):
A = np.array([[ 0 , 1 ],
[ - 1 , 0 ]])
w = A @ v
return w
result = transform_vectors(T_rotation_90, e1, e2)
print ( "Rotation result: \n " , result)
Shear along x-axis:
def T_shear_x ( v ):
A = np.array([[ 1 , 0.5 ],
[ 0 , 1 ]])
w = A @ v
return w
result = transform_vectors(T_shear_x, e1, e2)
print ( "Shear result: \n " , result)
# Output:
# [[1. 0.5]
# [0. 1. ]]
Shear transformations displace points proportionally to their distance from a line, creating a “slanting” effect.
Scaling
Rotation
Reflection
Shear
# Scale by factors sx and sy
A_scale = np.array([[sx, 0 ],
[ 0 , sy]])
# Rotate by angle θ (counterclockwise)
A_rotate = np.array([[np.cos(θ), - np.sin(θ)],
[np.sin(θ), np.cos(θ)]])
# Reflect about x-axis
A_reflect_x = np.array([[ 1 , 0 ],
[ 0 , - 1 ]])
# Reflect about y-axis
A_reflect_y = np.array([[ - 1 , 0 ],
[ 0 , 1 ]])
# Shear in x-direction
A_shear_x = np.array([[ 1 , k],
[ 0 , 1 ]])
# Shear in y-direction
A_shear_y = np.array([[ 1 , 0 ],
[k, 1 ]])
Applications in Computer Graphics
Efficiency Generate complex shapes from basic ones through transformations
Performance GPUs are optimized for matrix operations, enabling real-time graphics
Composition Combine multiple transformations by multiplying their matrices
Scale Process millions of vertices simultaneously
Apply transformations to an actual image:
# Load image
img = cv2.imread( 'images/leaf_original.png' , 0 )
plt.imshow(img, cmap = 'gray' )
plt.title( 'Original Image' )
plt.show()
Rotate 90 degrees clockwise:
image_rotated = cv2.rotate(img, cv2. ROTATE_90_CLOCKWISE )
plt.imshow(image_rotated, cmap = 'gray' )
plt.title( 'Rotated Image' )
plt.show()
Apply shear transformation:
rows, cols = image_rotated.shape
# Shear transformation matrix
M = np.float32([[ 1 , 0.5 , 0 ],
[ 0 , 1 , 0 ],
[ 0 , 0 , 1 ]])
image_rotated_sheared = cv2.warpPerspective(
image_rotated, M, ( int (cols), int (rows))
)
plt.imshow(image_rotated_sheared, cmap = 'gray' )
plt.title( 'Rotated and Sheared Image' )
plt.show()
Critical Concept : The order of transformations matters! Applying rotation then shear produces different results than shear then rotation.
This is because matrix multiplication is not commutative: A B ≠ B A AB \neq BA A B = B A
# Define transformation matrices
M_rotation_90 = np.array([[ 0 , 1 ], [ - 1 , 0 ]])
M_shear_x = np.array([[ 1 , 0.5 ], [ 0 , 1 ]])
# Order 1: Rotation then Shear
result1 = M_shear_x @ M_rotation_90
print ( "Rotation then Shear: \n " , result1)
# Order 2: Shear then Rotation
result2 = M_rotation_90 @ M_shear_x
print ( " \n Shear then Rotation: \n " , result2)
# They are different!
print ( " \n Are they equal?" , np.array_equal(result1, result2))
# Output: False
Combine multiple transformations efficiently:
# Individual transformations
A_scale = np.array([[ 2 , 0 ], [ 0 , 2 ]])
A_rotate = np.array([[ 0 , - 1 ], [ 1 , 0 ]]) # 90° counterclockwise
A_translate = np.array([[ 1 , 0 ], [ 0 , 1 ]]) # (simplified)
# Composite transformation
A_composite = A_rotate @ A_scale
# Apply to vector
v = np.array([[ 1 ], [ 0 ]])
result = A_composite @ v
print ( "Result of composite transformation: \n " , result)
Compose transformations by multiplying their matrices in reverse order: to apply T 1 T_1 T 1 then T 2 T_2 T 2 then T 3 T_3 T 3 , compute A = A 3 ⋅ A 2 ⋅ A 1 A = A_3 \cdot A_2 \cdot A_1 A = A 3 ⋅ A 2 ⋅ A 1 .
Practical Exercise
Barnsley Fern Example
The famous Barnsley Fern fractal uses four affine transformations applied iteratively. Each subleaf is a linear transformation of the original:
# Transformation for main stem (example)
A_stem = np.array([[ 0 , 0 ],
[ 0 , 0.16 ]])
# Transformation for smaller leaflet (example)
A_leaflet = np.array([[ 0.85 , 0.04 ],
[ - 0.04 , 0.85 ]])
# Apply transformation
point = np.array([[ 0 ], [ 0 ]])
new_point = A_leaflet @ point
print ( "Transformed point: \n " , new_point)
Fractals like the Barnsley Fern demonstrate how simple linear transformations, when applied iteratively, can create complex natural patterns.
Summary
What is a Linear Transformation?
Linear transformation L : R m → R n L: \mathbb{R}^m \rightarrow \mathbb{R}^n L : R m → R n corresponds to n × m n \times m n × m matrix
Matrix columns are images of standard basis vectors
A = [ L ( e 1 ) L ( e 2 ) ⋯ L ( e m ) ] A = \begin{bmatrix}L(e_1) & L(e_2) & \cdots & L(e_m)\end{bmatrix} A = [ L ( e 1 ) L ( e 2 ) ⋯ L ( e m ) ]
Computer graphics and 3D rendering
Image processing and computer vision
Neural networks (layers as transformations)
Data science (PCA, dimensionality reduction)
Order of transformations matters (A B ≠ B A AB \neq BA A B = B A )
Compose transformations by multiplying matrices
GPUs optimize matrix operations for real-time graphics
Understanding transformations is crucial for ML and CV
Next: Eigenvalues & Eigenvectors Discover special vectors that maintain their direction under transformations