-
Notifications
You must be signed in to change notification settings - Fork 11
/
48_Image_Alignment_using_ECC_Homography.py
110 lines (85 loc) · 3.91 KB
/
48_Image_Alignment_using_ECC_Homography.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
"""
Image alignment using Enhanced Correlation Coefficient (ECC) Maximization: Homography
Original url:
https://www.learnopencv.com/image-alignment-ecc-in-opencv-c-python/
Motion models:
- Translation
- Euclidean
- Affine
- Homography
cv2.findTransformECC():
- Read the images.
- Convert them to grayscale.
- Pick a motion model you want to estimate.
- Allocate space (warp_matrix) to store the motion model.
- Define a termination criteria that tells the algorithm when to stop.
- Estimate the warp matrix using findTransformECC.
- Apply the warp matrix to one of the images to align it with the other image.
"""
# Import the packages
import cv2
import numpy as np
"""
The problem is that the red, green, and blue channels in an image are not as strongly correlated if in pixel intensities as you might guess.
It turns out that the three channels of the image are more strongly correlated in the gradient domain. This is not surprising because even though the intensities may be different in the three channels, the edge map generated by object and color boundaries are consistent.
"""
# Get the gradient of the image
def get_gradient(im):
# Calculate the x and y gradients using Sobel operator
grad_x = cv2.Sobel(im, cv2.CV_32F, 1, 0, ksize=3)
grad_y = cv2.Sobel(im, cv2.CV_32F, 0, 1, ksize=3)
# Combine the two gradients
grad = cv2.addWeighted(np.absolute(grad_x), 0.5,
np.absolute(grad_y), 0.5, 0)
return grad
if __name__ == '__main__':
# Read 8-bit color image.
# This is an image in which the three channels are
# concatenated vertically.
# im = cv2.imread("images/alignment/emir.jpg", cv2.IMREAD_GRAYSCALE)
im = cv2.imread("images/alignment/bridge.jpg", cv2.IMREAD_GRAYSCALE)
# im = cv2.imread("images/alignment/girls.jpg", cv2.IMREAD_GRAYSCALE)
# Find the width and height of the color image
sz = im.shape
print(sz)
height = int(sz[0] / 3)
width = sz[1]
# Extract the three channels from the gray scale image
# and merge the three channels into one color image
im_color = np.zeros((height, width, 3), dtype=np.uint8)
for i in range(0, 3):
im_color[:, :, i] = im[i * height:(i+1) * height, :]
# Allocate space for aligned image
im_aligned = np.zeros((height, width, 3), dtype=np.uint8)
# The blue and green channels will be aligned to the red channel.
# So copy the red channel
im_aligned[:, :, 2] = im_color[:, :, 2]
# Define motion model
warp_mode = cv2.MOTION_HOMOGRAPHY
# Set the warp matrix to identity.
if warp_mode == cv2.MOTION_HOMOGRAPHY:
warp_matrix = np.eye(3, 3, dtype=np.float32)
else:
warp_matrix = np.eye(2, 3, dtype=np.float32)
# Set the stopping criteria for the algorithm.
criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 5000, 1e-10)
# Warp the blue and green channels to the red channel
for i in range(0, 2):
(cc, warp_matrix) = cv2.findTransformECC(get_gradient(im_color[:, :, 2]), get_gradient(
im_color[:, :, i]), warp_matrix, warp_mode, criteria, inputMask=None, gaussFiltSize=5)
if warp_mode == cv2.MOTION_HOMOGRAPHY:
# Use Perspective warp when the transformation is a Homography
im_aligned[:, :, i] = cv2.warpPerspective(
im_color[:, :, i], warp_matrix, (width, height), flags=cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP)
else:
# Use Affine warp when the transformation is not a Homography
im_aligned[:, :, i] = cv2.warpAffine(im_color[:, :, i], warp_matrix, (
width, height), flags=cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP)
print(warp_matrix)
# Show the image
cv2.imshow("Color Image", im_color)
cv2.imshow("Aligned Image", im_aligned)
# Wait until a key pressed
cv2.waitKey(0)
# Destroy all the windows opened before
cv2.destroyAllWindows()