forked from spmallick/learnopencv
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathimage_alignment.cpp
131 lines (97 loc) · 3.75 KB
/
image_alignment.cpp
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/**
* OpenCV Image Alignment Example
*
* Copyright 2015 by Satya Mallick <[email protected]>
*
*/
#include "opencv2/opencv.hpp"
using namespace cv;
using namespace std;
Mat GetGradient(Mat src_gray)
{
Mat grad_x, grad_y;
Mat abs_grad_x, abs_grad_y;
int scale = 1;
int delta = 0;
int ddepth = CV_32FC1; ;
// Calculate the x and y gradients using Sobel operator
Sobel( src_gray, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT );
convertScaleAbs( grad_x, abs_grad_x );
Sobel( src_gray, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT );
convertScaleAbs( grad_y, abs_grad_y );
// Combine the two gradients
Mat grad;
addWeighted( abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad );
return grad;
}
int main( int argc, char** argv )
{
// Read 8-bit color image.
// This is an image in which the three channels are
// concatenated vertically.
Mat im = imread("images/cathedral.jpg", IMREAD_GRAYSCALE);
// Find the width and height of the color image
Size sz = im.size();
int height = sz.height / 3;
int width = sz.width;
// Extract the three channels from the gray scale image
vector<Mat>channels;
channels.push_back(im( Rect(0, 0, width, height)));
channels.push_back(im( Rect(0, height, width, height)));
channels.push_back(im( Rect(0, 2*height, width, height)));
// Merge the three channels into one color image
Mat im_color;
merge(channels,im_color);
// Set space for aligned image.
vector<Mat> aligned_channels;
aligned_channels.push_back(Mat(height, width, CV_8UC1));
aligned_channels.push_back(Mat(height, width, CV_8UC1));
// The blue and green channels will be aligned to the red channel.
// So copy the red channel
aligned_channels.push_back(channels[2].clone());
// Define motion model
const int warp_mode = MOTION_AFFINE;
// Set space for warp matrix.
Mat warp_matrix;
// Set the warp matrix to identity.
if ( warp_mode == MOTION_HOMOGRAPHY )
warp_matrix = Mat::eye(3, 3, CV_32F);
else
warp_matrix = Mat::eye(2, 3, CV_32F);
// Set the stopping criteria for the algorithm.
int number_of_iterations = 5000;
double termination_eps = 1e-10;
TermCriteria criteria(TermCriteria::COUNT+TermCriteria::EPS,
number_of_iterations, termination_eps);
// Warp the blue and green channels to the red channel
for ( int i = 0; i < 2; i++)
{
double cc = findTransformECC (
GetGradient(channels[2]),
GetGradient(channels[i]),
warp_matrix,
warp_mode,
criteria
);
cout << "warp_matrix : " << warp_matrix << endl;
cout << "CC " << cc << endl;
if (cc == -1)
{
cerr << "The execution was interrupted. The correlation value is going to be minimized." << endl;
cerr << "Check the warp initialization and/or the size of images." << endl << flush;
}
if (warp_mode == MOTION_HOMOGRAPHY)
// Use Perspective warp when the transformation is a Homography
warpPerspective (channels[i], aligned_channels[i], warp_matrix, aligned_channels[0].size(), INTER_LINEAR + WARP_INVERSE_MAP);
else
// Use Affine warp when the transformation is not a Homography
warpAffine(channels[i], aligned_channels[i], warp_matrix, aligned_channels[0].size(), INTER_LINEAR + WARP_INVERSE_MAP);
}
// Merge the three channels
Mat im_aligned;
merge(aligned_channels, im_aligned);
// Show final output
imshow("Color Image", im_color);
imshow("Aligned Image", im_aligned);
waitKey(0);
}