-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlensdistort.m
218 lines (192 loc) · 7.63 KB
/
lensdistort.m
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
function I2 = lensdistort(I, k, varargin)
%LENSDISTORT corrects for barrel and pincusion lens abberations
% I = LENSDISTORT(I, k)corrects for radially symmetric distortions, where
% I is the input image and k is the distortion parameter. lens distortion
% can be one of two types: barrel distortion and pincushion distortion.
% In "barrel distortion", image magnification decreases with
% distance from the optical axis. The apparent effect is that of an image
% which has been mapped around a sphere (or barrel). In "pincushion
% distortion", image magnification increases with the distance from the
% optical axis. The visible effect is that lines that do not go through the
% centre of the image are bowed inwards, towards the centre of the image,
% like a pincushion [1].
%
% I = LENSDISTORT(...,PARAM1,VAL1,PARAM2,VAL2,...) creates a new image image,
% specifying parameters and corresponding values that control various aspects
% of the image distortion correction. Parameter names case does not matter.
%
% Parameters include:
%
% 'bordertype' String that controls the treatment of the image
% edges. Valid strings are 'fit' and 'crop'. By
% default, 'bordertype' is set to 'crop'.
%
% 'interpolation' String that specifies the interpolating kernel
% that the separable resampler uses. Valid
% strings are 'cubic', 'linear' and 'nearest'. By
% default, the 'interpolation' is set to 'cubic'
%
% 'padmethod' string that controls how the resampler
% interpolates or assigns values to output elements
% that map close to or outside the edge of the input
% array. Valid strings are 'bound', circular',
% 'fill', 'replicate', and symmetric'. By
% default, the 'padmethod' is set to 'fill'
%
% 'ftype' Integer between 1 and 4 that specifies the
% distortion model to be used. The models
% available are
%
% 'ftype' = 1: s = r.*(1./(1+k.*r));
%
% 'ftype' = 2: s = r.*(1./(1+k.*(r.^2)));
%
% 'ftype' = 3: s = r.*(1+k.*r);
%
% 'ftype' = 4: s = r.*(1+k.*(r.^2));
%
% By default, the 'ftype' is set to 4.
%
% Class Support
% -------------
% An input intensity image can be uint8, int8, uint16, int16, uint32,
% int32, single, double, or logical. An input indexed image can be uint8,
% uint16, single, double, or logical.
%
% Examples
% --------
% % read image
% I = imread('cameraman.tif');
%
% % Distort Image
% I2 = lensdistort(I, 0.1);
%
% % Display both images
% imshow(I), figure, imshow(I2)
%
% References
% --------------
% [1] http://en.wikipedia.org/wiki/Distortion_(optics), August 2012.
%
% [2] Harri Ojanen, "Automatic Correction of Lens Distortion by Using
% Digital Image Processing," July 10, 1999.
%
% [3] G.Vassy and T.Perlaki, "Applying and removing lens distortion in post
% production," year???
%
% [4] http://www.mathworks.com/products/demos/image/...
% create_gallery/tform.html#34594, August 2012.
%
% Created by Jaap de Vries, 8/31/2012
%
%-----------------------------------------------------------------------%
%-------------------------------------------------------------------------
% This part of the codes creates variable input parameters using the input
% parser object
p = inputParser;
% Make input string case independant
p.CaseSensitive = false;
% Specifies the required inputs
addRequired(p,'I',@isnumeric);
addRequired(p,'k',@isnumeric);
% Sets the default values for the optional parameters
defaultFtype = 4;
defaultBorder = 'crop';
defaultInterpolation = 'cubic';
defaultPadmethod = 'fill';
% Specifies valid strings for the optional parameters
validBorder = {'fit','crop'};
validInterpolation = {'cubic','linear', 'nearest'};
validPadmethod = {'bound','circular', 'fill', 'replicate', 'symmetric'};
% Funtion handles to determine wheter a proper input string has been used
checkBorder = @(x) any(validatestring(x,validBorder));
checkInterpolation = @(x) any(validatestring(x,validInterpolation));
checkPadmethod = @(x) any(validatestring(x,validPadmethod));
% Create optional inputs
addParamValue(p,'bordertype',defaultBorder,checkBorder);
addParamValue(p,'interpolation',defaultInterpolation,checkInterpolation);
addParamValue(p,'padmethod',defaultPadmethod,checkPadmethod);
addParamValue(p,'ftype',defaultFtype,@isnumeric);
% Pass all parameters and input to the parse method
parse(p,I,k,varargin{:});
%-------------------------------------------------------------------------
% This determines wether its a color (M,N,3) or gray scale (M,N,1) image
if ndims(I) == 3
for i=1:3
I2(:,:,i) = imdistcorrect(I(:,:,i),k);
end
elseif ismatrix(I)
I2 = imdistcorrect(I,k);
else
error('Unknown image dimensions')
end
%-------------------------------------------------------------------------
% Nested function that perfoms the transformation
function I3 = imdistcorrect(I,k)
% Determine the size of the image to be distorted
[M N]=size(I);
center = [round(N/2) round(M/2)];
% Creates N x M (#pixels) x-y points
[xi,yi] = meshgrid(1:N,1:M);
% Creates converst the mesh into a colum vector of coordiantes relative to
% the center
xt = xi(:) - center(1);
yt = yi(:) - center(2);
% Converts the x-y coordinates to polar coordinates
[theta,r] = cart2pol(xt,yt);
% Calculate the maximum vector (image center to image corner) to be used
% for normalization
R = sqrt(center(1)^2 + center(2)^2);
% Normalize the polar coordinate r to range between 0 and 1
r = r/R;
% Aply the r-based transformation
s = distortfun(r,k,p.Results.ftype);
% un-normalize s
s2 = s * R;
% Find a scaling parameter based on selected border type
brcor = bordercorrect(r,s,k, center, R);
s2 = s2 * brcor;
% Convert back to cartesian coordinates
[ut,vt] = pol2cart(theta,s2);
u = reshape(ut,size(xi)) + center(1);
v = reshape(vt,size(yi)) + center(2);
tmap_B = cat(3,u,v);
resamp = makeresampler(p.Results.interpolation, p.Results.padmethod);
I3 = tformarray(I,[],resamp,[2 1],[1 2],[],tmap_B,255);
end
%-------------------------------------------------------------------------
% Nested function that creates a scaling parameter based on the
% 'bordertype' selected
function x = bordercorrect(r,s,k,center, R)
if k < 0
if strcmp(p.Results.bordertype, 'fit')
x = r(1)/s(1);
end
if strcmp(p.Results.bordertype,'crop')
x = 1/(1 + k*(min(center)/R)^2);
end
elseif k > 0
if strcmp(p.Results.bordertype, 'fit')
x = 1/(1 + k*(min(center)/R)^2);
end
if strcmp(p.Results.bordertype, 'crop')
x = r(1)/s(1);
end
end
end
%-------------------------------------------------------------------------
% Nested function that pics the model type to be used
function s = distortfun(r,k,fcnum)
switch fcnum
case(1)
s = r.*(1./(1+k.*r));
case(2)
s = r.*(1./(1+k.*(r.^2)));
case(3)
s = r.*(1+k.*r);
case(4)
s = r.*(1+k.*(r.^2));
end
end
end