- This repository implements image affine transformation using naive python.
- The use of NumPy, OpenCV, and Pillow in this code is very limited, and is used only for reading and saving image.
- It can be a good reference for you to study affine transform.
- Combines linear transformations, and translations.
- Origin does not necessarily map to origin.
- Lines map to lines.
- Parallel lines remain parallel.
- Ratios are preserved.
- Find hte current center (cx, cy) of the image and translate it so that the origin is at (-cx, -cy).
- Scale the image about the origin by scale factor (sx, sy).
- Rotate the image about the origin by angle theta.
- Find the new center (tx, ty) of the image and translate the image by (tx, ty) so the new center will end up in the center of the image canvas.
- Translate :
[[1, 0, tx], [0, 1, ty], [0, 0, 1]]
- Scaling :
[[sx, 0, 0], [0, sy, 0], [0, 0, 1]]
- Rotation :
[[cos(θ), -sin(θ), 0], [sin(θ), cos(θ), 0], [0, 0, 1]]
- Shear :
[[1, shx, 0], [shy, 1, 0], [0, 0, 1]]
- Shift Center :
[[1, 0, -cx], [0, 1, -cy], [0, 0, 1]]
- Coordinates :
[x, y, 1]
- Scaling → Rotate → Translate
- a :
sx * cos(θ)
- b :
sy * -sin(θ)
- c :
tx
- d :
sx * sin(θ)
- e :
sy * cos(θ)
- f :
ty
- Affine :
[[a, b, c], [d, e, f], [0, 0, 1]]
- Inverse Scaling :
[[1/sx, 0, 0], [0, 1/sy, 0], [0, 0, 1]]
- Inverse Rotation :
[[cos(-θ), -sin(-θ), 0], [sin(-θ), cos(-θ), 0], [0, 0, 1]]
- a :
cos(-θ) / sx
- b :
-sin(-θ) / sy
- c :
tx
- d :
sin(-θ) / sx
- e :
cos(-θ) / sy
- f :
ty
- Inverse Affine :
[[a, b, c], [d, e, f], [0, 0, 1]]
- As we perform scale or rotation transformations, many points are computed as floating-point numbers, resulting in the loss of pixel values.
- It can be seen that a lot of regular noises is generated.
- In such cases, the inverse operation of the target image can obtain the original position.
- However, the original image coordinates calculated after inverse operations are also floating point numbers.
- In such cases, the method used to obtain approximate values is
bilinear interpolation
. f(x + u, y + v) = (1 - s) * (1 - t) * f(x, y) + (1 - s) * t * f(x + 1, y) + (1 - t) * s * f(x, y + 1) + s * t * f(x + 1, y + 1)
├─config
├─image
├─output
└─src
├─transform
└─utils
- You can set various experimental environments in
configs/config.py
inverse:
mode: 'inverse' # You can choose 'inverse_affine' or 'base'. When 'inverse' mode is selected, scaling becomes bilinear interpolation.
image_path: './image/test.jpg' # Input image path
output_path: './output/output_inverse.png' # Path to save result image
is_save: True # Save option
translate:
tx: 30 # x coordinates to translate
ty: 30 # y coordinates to translate
rotate:
degree: 15 # Angle
scaling:
sx: 2 # x scale factor
sy: 2 # y scale factor
affine:
tx: 30
ty: 30
degree: 132
sx: 1.3
sy: 1.3
shear:
shx: -0.5 # shift x
shy: 0 # shift y
affine:
mode: 'affine'
image_path: './image/test.jpg'
output_path: './output/output_affine.png'
is_save: True
translate:
tx: 30
ty: 30
rotate:
degree: 15
scaling:
sx: 2
sy: 2
affine:
tx: 30
ty: 30
degree: 132
sx: 1.3
sy: 1.3
shear:
shx: -0.5
shy: 0
other:
mode: 'flip_shear'
image_path: './image/test.jpg'
output_path: './output/output_flip_shear.png'
is_save: True
translate:
tx: 30
ty: 30
rotate:
degree: 15
scaling:
sx: 2
sy: 2
affine:
tx: 30
ty: 30
degree: 132
sx: 1.3
sy: 1.3
shear:
shx: -0.5
shy: 0
python demo.py --config affine
python demo.py --config inverse
python demo.py --config other