Commit 47ace8279f01f3e057f7c8e0390d728939ef3758

Authored by Daniel Bourgault
1 parent 13a4218a
Exists in master

The cdoe can now deal with GCPs with eleation. Plus the code now comes with m_map.

Showing 85 changed files with 15687 additions and 282 deletions   Show diff stats
Examples/Field/parameters.dat
... ... @@ -33,20 +33,18 @@ dH = 0.0;
33 33 dtheta = 20.0;
34 34  
35 35 % Order of the polynomial correction (0, 1 or 2)
36   -polyOrder = 1;
37   -
  36 +polyOrder = 0;
38 37  
39 38 % To save memory calculation can be done in single precision.
40 39 % For higher precision set the variable 'precision' to 'double';
41 40 precision = 'double';
42 41  
43   -
44 42 % Ground Control Points (GCP).
45 43 % The data must come right after the gcpData = true
46 44 gcpData = true;
47   - 360 829 -70.561367 47.303783
48   - 54 719 -70.54500 47.335
49   - 99 661 -70.505 47.375
50   - 452 641 -70.435 47.389
51   - 429 633 -70.418 47.408
52   - 816 644 -70.393 47.368
53 45 \ No newline at end of file
  46 + 360 829 -70.561367 47.303783 0
  47 + 54 719 -70.54500 47.335 0
  48 + 99 661 -70.505 47.375 0
  49 + 452 641 -70.435 47.389 0
  50 + 429 633 -70.418 47.408 0
  51 + 816 644 -70.393 47.368 0
54 52 \ No newline at end of file
... ...
Examples/Lab/parameters.dat
... ... @@ -45,18 +45,18 @@ precision = 'double';
45 45  
46 46 % Ground Control Points (GCP).
47 47 gcpData = true;
48   -2999 226 0.500 0.00
49   -1694 220 1.500 0.00
50   - 528 677 2.290 0.50
51   - 289 1231 2.290 1.00
52   -3819 686 0.000 0.50
53   -4018 1266 0.000 1.00
54   -2566 1235 0.890 0.99
55   -3806 2118 0.255 1.56
56   -4131 1580 0.000 1.23
57   - 521 2548 1.910 1.82
58   - 248 2328 2.060 1.71
59   - 14 1868 2.290 1.46
  48 +2999 226 0.500 0.00 0
  49 +1694 220 1.500 0.00 0
  50 + 528 677 2.290 0.50 0
  51 + 289 1231 2.290 1.00 0
  52 +3819 686 0.000 0.50 0
  53 +4018 1266 0.000 1.00 0
  54 +2566 1235 0.890 0.99 0
  55 +3806 2118 0.255 1.56 0
  56 +4131 1580 0.000 1.23 0
  57 + 521 2548 1.910 1.82 0
  58 + 248 2328 2.060 1.71 0
  59 + 14 1868 2.290 1.46 0
60 60  
61 61  
62 62  
... ...
src/g_rect/g_error_geofit.m
... ... @@ -4,7 +4,7 @@ function errGeoFit = g_error_geofit(cv,imgWidth,imgHeight,xp,yp,ic,jc,...
4 4 hfovGuess,lambdaGuess,phiGuess,HGuess,thetaGuess,...
5 5 dhfov,dlambda,dphi,dH,dtheta,...
6 6 LON0,LAT0,...
7   - i_gcp,j_gcp,lon_gcp,lat_gcp,...
  7 + i_gcp,j_gcp,lon_gcp0,lat_gcp0,h_gcp,...
8 8 theOrder,field);
9 9  
10 10  
... ... @@ -20,7 +20,6 @@ end
20 20 [LON LAT] = g_pix2ll(xp,yp,imgWidth,imgHeight,ic,jc,...
21 21 hfov,lambda,phi,theta,H,LON0,LAT0,field);
22 22  
23   -
24 23 % Calculate the error between ground control points (GCPs)
25 24 % and image control points once georectified.
26 25 %
... ... @@ -35,8 +34,11 @@ ngcp = length(i_gcp);
35 34 ngcpFinite = 0;
36 35 errGeoFit = 0.0;
37 36  
38   -for k = 1:ngcp
  37 +% Project the GCPs onto the water surface given their elevation
  38 +[lon_gcp,lat_gcp] = g_proj_GCP(LON0,LAT0,H,lon_gcp0,lat_gcp0,h_gcp,field);
39 39  
  40 +for k = 1:ngcp
  41 +
40 42 % Calculate the distance (i.e. error) between GCP and rectificed ICPs.
41 43 distance = g_dist(lon_gcp(k),lat_gcp(k),LON(k),LAT(k),field);
42 44  
... ... @@ -63,17 +65,3 @@ if abs(phi - phiGuess) > dphi; errGeoFit = inf; end
63 65 if abs(H - HGuess) > dH; errGeoFit = inf; end
64 66 if abs(theta - thetaGuess) > dtheta; errGeoFit = inf; end
65 67  
66   -
67   -%fprintf('\n')
68   -%fprintf('Field of view (fov): %f\n',hfov)
69   -%fprintf('Dip angle (lambda): %f\n',lambda)
70   -%fprintf('Tilt angle (phi): %f\n',phi)
71   -%fprintf('Camera altitude (H): %f\n',H)
72   -%fprintf('View angle from North (theta): %f\n',theta)
73   -%fprintf('RMS error (m): %f\n',errGeoFit)
74   -%fprintf('\n')
75   -
76   -%figure(100)
77   -%hold on;
78   -%plot(errGeoFit);
79   -
... ...
src/g_rect/g_pix2ll.m
... ... @@ -61,7 +61,6 @@ vfov = 2*atand(tand(hfov/2)/aspectRatio);
61 61 fx = (imgWidth/2)/tand(hfov/2);
62 62 fy = (imgHeight/2)/tand(vfov/2);
63 63  
64   -
65 64 % Subtract the principal point
66 65 x_p = xp - x_c + (jc);
67 66 y_p = yp - y_c + (ic);
... ...
src/g_rect/g_proj_GCP.m 0 → 100644
... ... @@ -0,0 +1,66 @@
  1 +function [lon_gcp,lat_gcp] = g_proj_GCP(LON0,LAT0,H,lon_gcp0,lat_gcp0,h_gcp,field)
  2 +%G_PROJ_GCP
  3 +%
  4 +% This function projects the GCPs that have an elevation greater than 0
  5 +% onto the water level of zero elevation. This is a trick in order to be
  6 +% able to deal with GCPs that have elevation. The principle can be
  7 +% illustrated in 1D like this. Consider the position x of a GCP that has an
  8 +% elevation h. Then, the projection (xp) of this GCP onto the plane that has
  9 +% zero elevation and along a line that joins the camera position of elevation
  10 +% H and the GCP is given by:
  11 +%
  12 +% xp = x * (H - h)/H
  13 +%
  14 +% INPUTS:
  15 +%
  16 +% LON0: The longitiude of the camera
  17 +% LAT0: The latitude of the camera
  18 +% H: The elevation of the camera
  19 +% lon_gcp0: The longitudes of the GCPs
  20 +% lat_gcp0: The latitudes of the GCPs
  21 +% h_gcp: The elevations of the GCPs
  22 +%
  23 +% OUTPUTS:
  24 +% lon_gcp: The projected longitudes of the GCPs
  25 +% lat_gcp: The projected latitudes of the GCPs
  26 +%
  27 +
  28 +n_gcp = length(h_gcp);
  29 +
  30 +for i = 1:n_gcp
  31 +
  32 + if field == true
  33 +
  34 + % The calculation for the distance between the GCPs and the camera
  35 + % is done on an elliptical earth and this takes a long calculation
  36 + % with the command m_idist from the m_map package. Therefore, the
  37 + % calculation is done only on the GCPs with no elevation, hence
  38 + % the 'if' condition here.
  39 + if h_gcp(i) > 0
  40 + [range,a12,a21] = m_idist(LON0,LAT0,lon_gcp0(i),lat_gcp0(i));
  41 + proj_factor = H/(H-h_gcp(i));
  42 + new_range = range*proj_factor;
  43 + [lon_gcp(i),lat_gcp(i),a21] = m_fdist(LON0,LAT0,a12,new_range);
  44 + lon_gcp(i) = lon_gcp(i) - 360;
  45 + else
  46 + % If there's no elevation, then there's nothing to do.
  47 + lon_gcp(i) = lon_gcp0(i);
  48 + lat_gcp(i) = lat_gcp0(i);
  49 + end
  50 +
  51 + else
  52 +
  53 + % For lab situations where positions are provided in meters rather
  54 + % than in latitude longitude the calculation is simpler.
  55 + dx = lon_gcp0(i) - LON0;
  56 + dy = lat_gcp0(i) - LAT0;
  57 + range = sqrt(dx^2 + dy^2);
  58 + proj_factor = H/(H-h_gcp(i));
  59 + new_range = range*proj_factor;
  60 + beta = atan2(dy,dx);
  61 +
  62 + lon_gcp(i) = new_range*cos(beta) + LON0;
  63 + lat_gcp(i) = new_range*sin(beta) + LAT0;
  64 +
  65 + end
  66 +end
0 67 \ No newline at end of file
... ...
src/g_rect/g_rect.m
... ... @@ -5,122 +5,150 @@ function g_rect
5 5 % instructions.
6 6 %
7 7 % Inputs:
8   -% The function G_RECT reads an input parameter file that contains all
9   -% information required to perfrorm a georectification of a given image.
10   -% The format of this parameter file is detailed on-line on the G_RECT
  8 +% The function G_RECT reads an input parameter file that contains all
  9 +% information required to perfrorm a georectification of a given image.
  10 +% The format of this parameter file is detailed on-line on the G_RECT
11 11 % Wiki page.
12 12 %
13 13 % Outputs:
14   -% The function G_RECT creates an output file that contains the following
15   -% variables:
  14 +% The function G_RECT creates an output file that contains the following
  15 +% variables:
16 16 %
17 17 % imgFname: The reference image for the georectification.
18 18 %
19 19 % firstImgFname: The first image of a sequence of images to which the
20 20 % georectification could be applied to. This is really
21   -% just a comment.
  21 +% just a comment.
22 22 %
23 23 % lastImgFname: The last image of a sequence of images to which the
24 24 % georectification could be applied to. This is really
25 25 % just a comment.
26 26 %
27   -% LON: The main matrix that contain the longitude of each
  27 +% LON: The main matrix that contain the longitude of each
28 28 % pixel of the referecne image (imgFname). Note that
29   -% if the package is used to rectify lab images this
  29 +% if the package is used to rectify lab images this
30 30 % matrix rather contains the distance in meters from
31   -% a predefined x-origin.
32   -%
  31 +% a predefined x-origin.
  32 +%
33 33 % LAT: Same as LON but for the latitude.
34   -%
35   -% LON0: A scalar for the longitude of the camera or, in the
36   -% case of a lab setup its cartesian coordinate in meters.
37   -%
  34 +%
  35 +% LON0: A scalar for the longitude of the camera or, in the
  36 +% case of a lab setup its cartesian coordinate in meters.
  37 +%
38 38 % LAT0: Same as LON0 but for the latitude.
39   -%
40   -% lon_gcp: A vector containing the longitude of each ground
41   -% control points (GCP). For the lab case this is the
42   -% cartesian coordinate in meters.
43   -%
  39 +%
  40 +% lon0_gcp: A vector containing the longitude of each ground
  41 +% control points (GCP). For the lab case this is the
  42 +% cartesian coordinate in meters. These GCPs may have
  43 +% elevations.
  44 +%
  45 +% lat0_gcp: Same as lon_gcp for latitude.
  46 +%
  47 +% lon_gcp: A vector containing the longitude of each ground
  48 +% control points (GCP) projected onto the water level
  49 +% i.e. at 0 m of elevation. For the lab case this is
  50 +% the cartesian coordinate in meters.
  51 +%
44 52 % lat_gcp: Same as lon_gcp for latitude.
45 53 %
  54 +% h_gcp: The elevation in meter of the GCPs. The elevation is
  55 +% 0 m if taken at water level.
  56 +%
46 57 % i_gcp: The horizontal index of the image ground control
47 58 % points.
48   -%
  59 +%
49 60 % j_gcp: The vertical index of the image ground control
50 61 % points.
51   -%
  62 +%
52 63 % hfov: The camera horizontal field of view [degree].
53 64 %
54 65 % phi: Camera tilt angle [degree].
55 66 %
  67 +% lambda: Camera dip angle [degree].
  68 +%
56 69 % H: The camera altitude relative to the water [m].
57 70 %
58 71 % theta: View angle clockwise from North [degree].
59 72 %
60   -%
61 73 % errGeoFit: The rms error of the georectified image after
62 74 % geometrical transformation [m].
63 75 %
64 76 % errPolyFit: The rms error of the georectified image after
65   -% geometrical transformation and the polynomial
  77 +% geometrical transformation and the polynomial
66 78 % correction [m].
67 79 %
68 80 % precision: Calculation can be done in single or double
69 81 % precisions as defined by the user in the parameter
70   -% file. With today's computers this is now obsolete
71   -% and calculations can always be done in double
  82 +% file. With today's computers this is now obsolete
  83 +% and calculations can always be done in double
72 84 % precision.
73 85 %
  86 +% Delta: The effective resolution of the georectified image.
74 87 %
75 88 % Other m-files required: Works best with the m_map package for
76 89 % visualization.
77 90 % Subfunctions: all functions contained within the G_RECT folder.
78   -%
  91 +%
79 92 % Author: Daniel Bourgault
80 93 % Institut des sciences de la mer de Rimouski
81   -% email: daniel_bourgault@uqar.ca
  94 +% email: daniel_bourgault@uqar.ca
82 95 % Website: https://srwebpolr01.uqar.ca/g_rect/
83 96 % February 2013
84 97 %
85 98  
86   -%
87   -% The minimization is repeated nMinimize times where each time a random
  99 +%%
  100 +% The minimization is repeated nMinimize times where each time a random
88 101 % combination of the initial guesses is chosen within the given
89   -% uncertainties provided by the user. This is becasue the algorithm often
  102 +% uncertainties provided by the user. This is becasue the algorithm often
90 103 % converges toward a local minimum. The repetition is used to increase chances
91   -% that the minimum found is a true minimum within the uncertainties provided.
  104 +% that the minimum found is a true minimum within the uncertainties provided.
92 105 nMinimize = 50;
93 106  
94   -
95 107 %% Read the parameter file
96 108 % Count the number of header lines before the ground control points (GCPs)
97 109 % The GCPs start right after the variable gcpData is set to true.
98   -display(' ');
99   -display(' Welcome to g_rect: a package for georectifying oblique images on a flat ocean');
100   -display(' Authors: Daniel Bourgault and Rich Pawlowicz');
101   -display(' ');
102   -inputFname = input(' Enter the filename for the input parameters: ','s');
  110 +display(' ');
  111 +display(' Welcome to g_rect: a package for georectifying oblique images on a flat ocean');
  112 +display(' Authors: Daniel Bourgault and Rich Pawlowicz');
  113 +display(' ');
  114 +inputFname = input(' Enter the filename for the input parameters: ','s');
103 115 fid = fopen(inputFname);
104   -
105   -nHeaderLine = 0;
106   -gcpData = false;
  116 +
  117 +nHeaderLine = 0;
  118 +gcpData = false;
107 119  
108 120 % Read and execute each line of the parameter file until gcpData = true
109 121 % after which the GCP data appear and are read below with the importdata
110 122 % function.
111 123 while gcpData == false
112   - eval(fgetl(fid));
113   - nHeaderLine = nHeaderLine + 1;
  124 + eval(fgetl(fid));
  125 + nHeaderLine = nHeaderLine + 1;
114 126 end
115 127 fclose(fid);
116 128  
117   -%% Import the GCP data (4 column) at the end of the parameter file
118   -gcp = importdata(inputFname,' ',nHeaderLine)
119   -i_gcp = gcp.data(:,1);
120   -j_gcp = gcp.data(:,2);
121   -lon_gcp = gcp.data(:,3);
122   -lat_gcp = gcp.data(:,4);
123   -ngcp = length(i_gcp);
  129 +%% Import the GCP data at the end of the parameter file
  130 +gcp = importdata(inputFname,' ',nHeaderLine);
  131 +i_gcp = gcp.data(:,1);
  132 +j_gcp = gcp.data(:,2);
  133 +lon_gcp0 = gcp.data(:,3);
  134 +lat_gcp0 = gcp.data(:,4);
  135 +h_gcp = gcp.data(:,5);
  136 +
  137 +%%
  138 +% Check if the elevation of the GCPs are not too high and above
  139 +% a certain fraction (gamma) of the camera height. If so, stop.
  140 +gamma = 0.75;
  141 +i_bad = find(h_gcp > gamma*(H+dH));
  142 +if length(i_bad) > 0
  143 + display([' ']);
  144 + display([' WARNING:']);
  145 + for i = 1:length(i_bad)
  146 + display([' The elevation of GCP #',num2str(i_bad(i)),' is greater than ',num2str(gamma),'*(H+dH).']);
  147 + end
  148 + display([' FIX AND RERUN.']);
  149 + return
  150 +end
  151 +ngcp = length(i_gcp);
124 152  
125 153 % Get the image size
126 154 imgInfo = imfinfo(imgFname);
... ... @@ -128,12 +156,11 @@ imgWidth = imgInfo.Width;
128 156 imgHeight = imgInfo.Height;
129 157  
130 158 if precision == 'single'
131   - imgWidth = single(imgWidth);
132   - imgHeight = single(imgHeight);
  159 + imgWidth = single(imgWidth);
  160 + imgHeight = single(imgHeight);
133 161 end
134 162  
135   -
136   -%% Display information
  163 +%% Display information
137 164 fprintf('\n')
138 165 fprintf(' INPUT PARAMETERS\n')
139 166 fprintf(' Image filename: (imgFname):........... %s\n',imgFname)
... ... @@ -168,22 +195,23 @@ imagesc(imread(imgFname));
168 195 colormap(gray);
169 196 hold on
170 197 for i = 1:ngcp
171   - plot(i_gcp(i),j_gcp(i),'r.');
172   - text(i_gcp(i),j_gcp(i),num2str(i),'color','r','horizontalalignment','right');
  198 + plot(i_gcp(i),j_gcp(i),'r.');
  199 + text(i_gcp(i),j_gcp(i),[num2str(i),'(',num2str(h_gcp(i)),')'],...
  200 + 'color','r',...
  201 + 'horizontalalignment','right',...
  202 + 'fontsize',16);
173 203 end
174   -title('Ground Control Points','color','r');
  204 +title('Ground Control Points Number (elevation in meters)','color','r');
175 205  
176 206 print -dpng -r300 image1.png
177 207  
178 208 fprintf('\n')
179 209 ok = input('Is it ok to proceed with the rectification (y/n): ','s');
180 210 if ok ~= 'y'
181   - return
182   - %break
  211 + return
183 212 end
184 213  
185 214 %%
186   -
187 215 nUnknown = 0;
188 216 if dhfov > 0.0; nUnknown = nUnknown+1; end
189 217 if dlambda > 0.0; nUnknown = nUnknown+1; end
... ... @@ -192,154 +220,153 @@ if dH > 0.0; nUnknown = nUnknown+1; end
192 220 if dtheta > 0.0; nUnknown = nUnknown+1; end
193 221  
194 222 if nUnknown > ngcp
195   - fprintf('\n')
196   - fprintf('WARNING: \n');
197   - fprintf(' The number of GCPs is < number of unknown parameters.\n');
198   - fprintf(' Program stopped.\n');
199   - %break
200   - return
  223 + fprintf('\n')
  224 + fprintf('WARNING: \n');
  225 + fprintf(' The number of GCPs is < number of unknown parameters.\n');
  226 + fprintf(' Program stopped.\n');
  227 + return
201 228 end
202 229  
203   -% Check for consistencies between number of GCPs and order of the polynomial
  230 +% Check for consistencies between number of GCPs and order of the polynomial
204 231 % correction
205 232 ngcp = length(i_gcp);
206 233 if ngcp < 3*polyOrder
207   - fprintf('\n')
208   - fprintf('WARNING: \n');
209   - fprintf(' The number of GCPs is inconsistent with the order of the polynomial correction.\n');
210   - fprintf(' ngcp should be >= 3*polyOrder.\n');
211   - fprintf(' Polynomial correction will not be applied.\n');
212   - polyCorrection = false;
  234 + fprintf('\n')
  235 + fprintf('WARNING: \n');
  236 + fprintf(' The number of GCPs is inconsistent with the order of the polynomial correction.\n');
  237 + fprintf(' ngcp should be >= 3*polyOrder.\n');
  238 + fprintf(' Polynomial correction will not be applied.\n');
  239 + polyCorrection = false;
213 240 else
214   - polyCorrection = true;
  241 + polyCorrection = true;
215 242 end
216 243 if polyOrder == 0
217   - polyCorrection = false;
  244 + polyCorrection = false;
218 245 end
219 246  
220 247 %% This is the main section for the minimization algorithm
221 248  
222 249 if nUnknown > 0
223 250  
224   - % Options for the fminsearch function. May be needed for some particular
225   - % problems but in general the default values should work fine.
226   - %options=optimset('MaxFunEvals',100000,'MaxIter',100000);
227   - %options=optimset('MaxFunEvals',100000,'MaxIter',100000,'TolX',1.d-12,'TolFun',1.d-12);
228   - options = [];
229   -
  251 + % Options for the fminsearch function. May be needed for some particular
  252 + % problems but in general the default values should work fine.
  253 + %options=optimset('MaxFunEvals',100000,'MaxIter',100000);
  254 + %options=optimset('MaxFunEvals',100000,'MaxIter',100000,'TolX',1.d-12,'TolFun',1.d-12);
  255 + options = [];
  256 +
  257 + % Only feed the minimization algorithm with the GCPs. xp and yp are the
  258 + % image coordinate of these GCPs.
  259 + xp = i_gcp;
  260 + yp = j_gcp;
230 261  
231   - % Only feed the minimization algorithm with the GCPs. xp and yp are the
232   - % image coordinate of these GCPs.
233   - xp = i_gcp;
234   - yp = j_gcp;
235   -
236   - % This is the call to the minimization
237   - bestErrGeoFit = Inf;
238   -
239   - % Save inital guesses in new variables.
240   - hfovGuess = hfov;
241   - lambdaGuess = lambda;
242   - phiGuess = phi;
243   - HGuess = H;
244   - thetaGuess = theta;
245   -
246   - for iMinimize = 1:nMinimize
247   -
248   - % First guesses for the minimization
249   - if iMinimize == 1
250   - hfov0 = hfov;
251   - lambda0 = lambda;
252   - phi0 = phi;
253   - H0 = H;
254   - theta0 = theta;
255   - else
256   - % Select randomly new initial guesses within the specified
257   - % uncertainties.
258   - hfov0 = (hfovGuess - dhfov) + 2*dhfov*rand(1);
259   - lambda0 = (lambdaGuess - dlambda) + 2*dlambda*rand(1);
260   - phi0 = (phiGuess - dphi) + 2*dphi*rand(1);
261   - H0 = (HGuess - dH) + 2*dH*rand(1);
262   - theta0 = (thetaGuess - dtheta) + 2*dtheta*rand(1);
263   - end
264   -
265   - % Cretae vector cv0 for the initial guesses.
266   - i = 0;
267   - if dhfov > 0.0
268   - i = i+1;
269   - cv0(i) = hfov0;
270   - theOrder(i) = 1;
271   - end
272   - if dlambda > 0.0
273   - i = i + 1;
274   - cv0(i) = lambda0;
275   - theOrder(i) = 2;
276   - end
277   - if dphi > 0.0
278   - i = i + 1;
279   - cv0(i) = phi0;
280   - theOrder(i) = 3;
281   - end
282   - if dH > 0.0
283   - i = i + 1;
284   - cv0(i) = H0;
285   - theOrder(i) = 4;
286   - end
287   - if dtheta > 0.0
288   - i = i + 1;
289   - cv0(i) = theta0;
290   - theOrder(i) = 5;
291   - end
292   -
293   - [cv, errGeoFit] = fminsearch('g_error_geofit',cv0,options, ...
294   - imgWidth,imgHeight,xp,yp,ic,jc,...
295   - hfov,lambda,phi,H,theta,...
296   - hfov0,lambda0,phi0,H0,theta0,...
297   - hfovGuess,lambdaGuess,phiGuess,HGuess,thetaGuess,...
298   - dhfov,dlambda,dphi,dH,dtheta,...
299   - LON0,LAT0,...
300   - i_gcp,j_gcp,lon_gcp,lat_gcp,...
301   - theOrder,field);
302   -
303   -
304   - if errGeoFit < bestErrGeoFit
305   - bestErrGeoFit = errGeoFit;
306   - cvBest = cv;
307   - end
308   -
309   - fprintf('\n')
310   - fprintf(' Iteration # (iMinimize): %i\n',iMinimize);
311   - fprintf(' Max. number of iteration (nMinimize): %i\n',nMinimize);
312   - fprintf(' RSM error (m) for this iteration (errGeoFit): %f\n',errGeoFit);
313   - fprintf(' Best RSM error (m) so far (bestErrGeoFit): %f\n',bestErrGeoFit);
314   -
315   - end
316   -
317   - for i = 1:length(theOrder)
318   - if theOrder(i) == 1; hfov = cvBest(i); end
319   - if theOrder(i) == 2; lambda = cvBest(i); end
320   - if theOrder(i) == 3; phi = cvBest(i); end
321   - if theOrder(i) == 4; H = cvBest(i); end
322   - if theOrder(i) == 5; theta = cvBest(i); end
323   - end
324   -
325   - fprintf('\n')
326   - fprintf('PARAMETERS AFTER GEOMETRICAL RECTIFICATION \n')
327   - fprintf(' Field of view (hfov): %f\n',hfov)
328   - fprintf(' Dip angle (lambda): %f\n',lambda)
329   - fprintf(' Tilt angle (phi): %f\n',phi)
330   - fprintf(' Camera altitude (H): %f\n',H)
331   - fprintf(' View angle from North (theta): %f\n',theta)
332   - fprintf('\n')
333   -
334   - if length(theOrder) > 1
335   - fprintf('The rms error after geometrical correction (m): %f\n',bestErrGeoFit);
336   - end
337   -
  262 + % This is the call to the minimization
  263 + bestErrGeoFit = Inf;
  264 +
  265 + % Save inital guesses in new variables.
  266 + hfovGuess = hfov;
  267 + lambdaGuess = lambda;
  268 + phiGuess = phi;
  269 + HGuess = H;
  270 + thetaGuess = theta;
  271 +
  272 + for iMinimize = 1:nMinimize
  273 +
  274 + % First guesses for the minimization
  275 + if iMinimize == 1
  276 + hfov0 = hfov;
  277 + lambda0 = lambda;
  278 + phi0 = phi;
  279 + H0 = H;
  280 + theta0 = theta;
  281 + else
  282 + % Select randomly new initial guesses within the specified
  283 + % uncertainties.
  284 + hfov0 = (hfovGuess - dhfov) + 2*dhfov*rand(1);
  285 + lambda0 = (lambdaGuess - dlambda) + 2*dlambda*rand(1);
  286 + phi0 = (phiGuess - dphi) + 2*dphi*rand(1);
  287 + H0 = (HGuess - dH) + 2*dH*rand(1);
  288 + theta0 = (thetaGuess - dtheta) + 2*dtheta*rand(1);
  289 + end
  290 +
  291 + % Cretae vector cv0 for the initial guesses.
  292 + i = 0;
  293 + if dhfov > 0.0
  294 + i = i+1;
  295 + cv0(i) = hfov0;
  296 + theOrder(i) = 1;
  297 + end
  298 + if dlambda > 0.0
  299 + i = i + 1;
  300 + cv0(i) = lambda0;
  301 + theOrder(i) = 2;
  302 + end
  303 + if dphi > 0.0
  304 + i = i + 1;
  305 + cv0(i) = phi0;
  306 + theOrder(i) = 3;
  307 + end
  308 + if dH > 0.0
  309 + i = i + 1;
  310 + cv0(i) = H0;
  311 + theOrder(i) = 4;
  312 + end
  313 + if dtheta > 0.0
  314 + i = i + 1;
  315 + cv0(i) = theta0;
  316 + theOrder(i) = 5;
  317 + end
  318 +
  319 + [cv, errGeoFit] = fminsearch('g_error_geofit',cv0,options, ...
  320 + imgWidth,imgHeight,xp,yp,ic,jc,...
  321 + hfov,lambda,phi,H,theta,...
  322 + hfov0,lambda0,phi0,H0,theta0,...
  323 + hfovGuess,lambdaGuess,phiGuess,HGuess,thetaGuess,...
  324 + dhfov,dlambda,dphi,dH,dtheta,...
  325 + LON0,LAT0,...
  326 + i_gcp,j_gcp,lon_gcp0,lat_gcp0,h_gcp,...
  327 + theOrder,field);
  328 +
  329 + if errGeoFit < bestErrGeoFit
  330 + bestErrGeoFit = errGeoFit;
  331 + cvBest = cv;
  332 + end
  333 +
  334 + fprintf('\n')
  335 + fprintf(' Iteration # (iMinimize): %i\n',iMinimize);
  336 + fprintf(' Max. number of iteration (nMinimize): %i\n',nMinimize);
  337 + fprintf(' RSM error (m) for this iteration (errGeoFit): %f\n',errGeoFit);
  338 + fprintf(' Best RSM error (m) so far (bestErrGeoFit): %f\n',bestErrGeoFit);
  339 +
  340 + end
  341 +
  342 + for i = 1:length(theOrder)
  343 + if theOrder(i) == 1; hfov = cvBest(i); end
  344 + if theOrder(i) == 2; lambda = cvBest(i); end
  345 + if theOrder(i) == 3; phi = cvBest(i); end
  346 + if theOrder(i) == 4; H = cvBest(i); end
  347 + if theOrder(i) == 5; theta = cvBest(i); end
  348 + end
  349 +
  350 + fprintf('\n')
  351 + fprintf('PARAMETERS AFTER GEOMETRICAL RECTIFICATION \n')
  352 + fprintf(' Field of view (hfov): %f\n',hfov)
  353 + fprintf(' Dip angle (lambda): %f\n',lambda)
  354 + fprintf(' Tilt angle (phi): %f\n',phi)
  355 + fprintf(' Camera altitude (H): %f\n',H)
  356 + fprintf(' View angle from North (theta): %f\n',theta)
  357 + fprintf('\n')
  358 +
  359 + if length(theOrder) > 1
  360 + fprintf('The rms error after geometrical correction (m): %f\n',bestErrGeoFit);
  361 + end
338 362 end
339 363  
340   -%%
  364 +% Project the GCP that have elevation.
  365 +[lon_gcp,lat_gcp] = g_proj_GCP(LON0,LAT0,H,lon_gcp0,lat_gcp0,h_gcp,field);
  366 +
  367 +%%
341 368  
342   -% Now construct the matrices LON and LAT for the entire image using the
  369 +% Now construct the matrices LON and LAT for the entire image using the
343 370 % camera parameters found by minimization just above.
344 371  
345 372 % Camera coordinate of all pixels
... ... @@ -353,10 +380,10 @@ yp = repmat([1:imgHeight],imgWidth,1);
353 380  
354 381 %% Apply polynomial correction if requested.
355 382 if polyCorrection == true
356   - [LON LAT errPolyFit] = g_poly(LON,LAT,LON0,LAT0,i_gcp,j_gcp,lon_gcp,lat_gcp,polyOrder,field);
357   - fprintf('The rms error after polynomial stretching (m): %f\n',errPolyFit)
  383 + [LON LAT errPolyFit] = g_poly(LON,LAT,LON0,LAT0,i_gcp,j_gcp,lon_gcp,lat_gcp,polyOrder,field);
  384 + fprintf('The rms error after polynomial stretching (m): %f\n',errPolyFit)
358 385 else
359   - errPolyFit = NaN;
  386 + errPolyFit = NaN;
360 387 end
361 388 %%
362 389  
... ... @@ -369,7 +396,8 @@ fprintf(&#39;Saving rectification file in: %s\n&#39;,outputFname);
369 396 save(outputFname,'imgFname','firstImgFname','lastImgFname',...
370 397 'LON','LAT',...
371 398 'LON0','LAT0',...
372   - 'lon_gcp','lat_gcp',...
  399 + 'lon_gcp0','lat_gcp0',...
  400 + 'lon_gcp','lat_gcp','h_gcp',...
373 401 'i_gcp','j_gcp',...
374 402 'hfov','lambda','phi','H','theta',...
375 403 'errGeoFit','errPolyFit',...
... ... @@ -380,7 +408,7 @@ clear LON LAT
380 408 fprintf('\n')
381 409 fprintf('Making figure\n');
382 410  
383   -figure;
  411 +figure;
384 412 if field
385 413 g_viz_field(imgFname,outputFname);
386 414 else
... ...
src/g_rect/g_viz_field.m
... ... @@ -18,6 +18,12 @@ function [h_figure,h_pcolor,h_datetext] = g_viz_field(imgFname,rectFile,varargin
18 18 % corresponding objects in the figure, for use in g_viz_anim
19 19 %
20 20  
  21 +% Set some plotting parameters
  22 +ms = 10; % Marker Size
  23 +fs = 10; % Font size
  24 +lw = 2; % Line width
  25 +
  26 +% Option
21 27 show_time = 0;
22 28 show_land = 0;
23 29 land_color = [241 235 144]/255;
... ... @@ -34,30 +40,21 @@ if length(varargin) &gt; 1
34 40 end
35 41 end
36 42  
37   -
38   -% Set some plotting parameters
39   -ms = 10; % Marker Size
40   -fs = 10; % Font size
41   -lw = 2; % Line width
42   -
  43 +% Load the georectification file
43 44 load(rectFile);
44 45  
45   -%p = size(LON,3);
46   -
47   -lon_min = min(lon_gcp);
48   -lon_max = max(lon_gcp);
49   -lat_min = min(lat_gcp);
50   -lat_max = max(lat_gcp);
51   -lon_min = min(lon_min,LON0);
52   -lon_max = max(lon_max,LON0);
53   -lat_min = min(lat_min,LAT0);
54   -lat_max = max(lat_max,LAT0);
55   -
  46 +% Determine the region to plot, delimited by the GCP and the camera
  47 +% position. Add a factor (fac) all around
56 48 fac = 0.1;
57   -lon_min= lon_min - fac*abs(lon_max-lon_min);
58   -lon_max= lon_max + fac*abs(lon_max-lon_min);
59   -lat_min= lat_min - fac*abs(lat_max-lat_min);
60   -lat_max= lat_max + fac*abs(lat_max-lat_min);
  49 +lon_min = min([lon_gcp,LON0]);
  50 +lon_max = max([lon_gcp,LON0]);
  51 +lat_min = min([lat_gcp,LAT0]);
  52 +lat_max = max([lat_gcp,LAT0]);
  53 +
  54 +lon_min = lon_min - fac*abs(lon_max - lon_min);
  55 +lon_max = lon_max + fac*abs(lon_max - lon_min);
  56 +lat_min = lat_min - fac*abs(lat_max - lat_min);
  57 +lat_max = lat_max + fac*abs(lat_max - lat_min);
61 58  
62 59 rgb0 = double(imread(imgFname))/255;
63 60  
... ... @@ -70,19 +67,19 @@ end
70 67 clear rgb0;
71 68 int = int';
72 69  
73   -int = int - nanmean(nanmean(int));
  70 +% Normalize the image if wanted
  71 +%int = int - nanmean(nanmean(int));
74 72  
75   -figure('Renderer', 'painters', 'Position', [100 100 900 700])
  73 +%figure('Renderer', 'painters', 'Position', [100 100 900 700])
  74 +figure
76 75 m_proj('mercator','longitudes',[lon_min lon_max],'latitudes',[lat_min lat_max]);
77 76 hold on;
78 77  
79   -[X,Y] = m_ll2xy(LON,LAT);
80 78 cmap = contrast(int,256);
81 79 colormap(cmap);
82   -h = pcolor(X,Y,int);
  80 +h = m_pcolor(LON,LAT,int);
83 81 shading('interp');
84 82  
85   -
86 83 % Uncomment one of these lines if you want the coastline to be plotted.
87 84 if show_land
88 85 if strcmpi(show_land,'fjord')
... ... @@ -109,7 +106,14 @@ m_plot(LON0,LAT0,&#39;kx&#39;,&#39;markersize&#39;,ms,&#39;linewidth&#39;,lw); % Camera location
109 106  
110 107 %% Plot GCPs and ICPs.
111 108 for n=1:length(i_gcp)
  109 +
  110 + % Plot the original GCPs that may have elevations
  111 + m_plot(lon_gcp0(n),lat_gcp0(n),'ko','markersize',ms,'linewidth',lw);
  112 +
  113 + % Plot the projected GCPs that are actually used for the minimization
112 114 m_plot(lon_gcp(n),lat_gcp(n),'bo','markersize',ms,'linewidth',lw);
  115 +
  116 + % Plot the Image Control Points once georectified
113 117 m_plot(LON(i_gcp(n),j_gcp(n)),LAT(i_gcp(n),j_gcp(n)),'rx','MarkerSize',ms,'linewidth',lw);
114 118 end
115 119  
... ... @@ -118,7 +122,7 @@ end
118 122  
119 123 clear LON LAT X Y
120 124  
121   -m_grid_old('box','fancy','fontsize',fs);
  125 +m_grid('box','fancy','fontsize',fs);
122 126 %m_gshhs('f','patch', 'gray');
123 127 %print('g_rect_drone_1', '-dpng')
124 128 if nargout > 1
... ...
src/g_rect/g_viz_lab.m
1   -function g_viz_lab(imgFname,outputFname);
  1 +function g_viz_lab(imgFname,rectFile);
2 2  
3 3 % Set some plotting parameters
4 4 ms = 10; % Marker Size
5 5 fs = 10; % Font size
6 6 lw = 2; % Line width
7 7  
8   -load(outputFname);
9   -
10   -lon_min = min(lon_gcp);
11   -lon_max = max(lon_gcp);
12   -lat_min = min(lat_gcp);
13   -lat_max = max(lat_gcp);
14   -lon_min = min(lon_min,LON0);
15   -lon_max = max(lon_max,LON0);
16   -lat_min = min(lat_min,LAT0);
17   -lat_max = max(lat_max,LAT0);
  8 +load(rectFile);
18 9  
  10 +% Determine the region to plot, delimited by the GCP and the camera
  11 +% position. Add a factor (fac) all around
19 12 fac = 0.1;
20   -lon_min= lon_min - fac*abs(lon_max-lon_min);
21   -lon_max= lon_max + fac*abs(lon_max-lon_min);
22   -lat_min= lat_min - fac*abs(lat_max-lat_min);
23   -lat_max= lat_max + fac*abs(lat_max-lat_min);
  13 +lon_min = min([lon_gcp,LON0]);
  14 +lon_max = max([lon_gcp,LON0]);
  15 +lat_min = min([lat_gcp,LAT0]);
  16 +lat_max = max([lat_gcp,LAT0]);
  17 +
  18 +lon_min = lon_min - fac*abs(lon_max - lon_min);
  19 +lon_max = lon_max + fac*abs(lon_max - lon_min);
  20 +lat_min = lat_min - fac*abs(lat_max - lat_min);
  21 +lat_max = lat_max + fac*abs(lat_max - lat_min);
24 22  
25 23 rgb0 = double(imread(imgFname))/255;
26 24  
... ... @@ -35,18 +33,23 @@ int = int&#39;;
35 33  
36 34 hold on;
37 35  
38   -X = LON;
39   -Y = LAT;
40   -
41 36 colormap(gray);
42   -h = pcolor(X,Y,int);
  37 +pcolor(LON,LAT,int);
43 38 shading('flat');
44 39  
45   -
46 40 plot(LON0,LAT0,'kx','markersize',ms,'linewidth',lw); % Camera location
47 41  
48 42 %% Plot GCPs and ICPs.
49 43 for n=1:length(i_gcp)
50   - plot(lon_gcp(n),lat_gcp(n),'bo','markersize',ms,'linewidth',lw);
51   - plot(LON(i_gcp(n),j_gcp(n)),LAT(i_gcp(n),j_gcp(n)),'rx','MarkerSize',ms,'linewidth',lw);
  44 +
  45 + % Plot the original GCPs that may have elevations
  46 + plot(lon_gcp0(n),lat_gcp0(n),'ko','markersize',ms,'linewidth',lw);
  47 +
  48 + % Plot the projected GCPs that are actually used for the minimization
  49 + plot(lon_gcp(n),lat_gcp(n),'bo','markersize',ms,'linewidth',lw);
  50 +
  51 + % Plot the Image Control Points once georectified
  52 + plot(LON(i_gcp(n),j_gcp(n)),LAT(i_gcp(n),j_gcp(n)),'rx','MarkerSize',ms,'linewidth',lw);
52 53 end
  54 +
  55 +axis([lon_min lon_max lat_min lat_max]);
53 56 \ No newline at end of file
... ...
src/g_stabilize/g_roi2.m 0 → 100644
... ... @@ -0,0 +1,56 @@
  1 +function g_roi2(imgFname)
  2 +% G_ROI is a function to determine regions of interest in an image.
  3 +%
  4 +% This function allows the user to define a series of polygons
  5 +% on an image in order to define regions of interest (roi) for
  6 +% image stabilization. The result is a 2D matrix roi with 1s and 0s.
  7 +% Just follow the instructions.
  8 +%
  9 +% Input: imgFname: the image filename
  10 +% Output: The 2D matrix roi written to filename roi.mat
  11 +%
  12 +% ** There is tips to modifie and adjuste the roi before saving it in the
  13 +% help menu of the impoly function.
  14 +% Example : Hold the button A and click on the polygon border to add
  15 +% points.
  16 +%
  17 +% Author: Daniel Bourgault - 2011
  18 +%
  19 +% Updated : - 11/05/19 - Show the lines while creating the polygon.
  20 +% Updated : - 08/08/19 - Enable modification of the polygon before saving.
  21 +%
  22 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  23 +%% Reading reference images
  24 +im = imread(imgFname);
  25 +[m,n,~] = size(im);
  26 +roi(1:m,1:n) = 0; % Create ROI matrix
  27 +
  28 +%% Generating Region of Interest
  29 +imagesc(im)
  30 +hold on
  31 +colormap(gray);
  32 +
  33 +continue_draw = 'y';
  34 +while continue_draw == 'y'
  35 + % Instructions
  36 + fprintf(' Make a polygon with left click on the mouse\n')
  37 + fprintf(' Right click to link the last and first point\n')
  38 + fprintf(' Double click on the polygon when you are done arranging points\n')
  39 + fprintf(' You will have the option to make more polygons when done with this one\n')
  40 + % Drawing
  41 + h=impoly;
  42 + wait(h);
  43 + Mask = createMask(h);
  44 + roi = roi+Mask;
  45 + continue_draw = input('Draw another polygon (y/n) ? ','s');
  46 +end
  47 +hold off
  48 +
  49 +ij = roi > 1;
  50 +roi(ij) = 1;
  51 +
  52 +% Final figure
  53 +figure(2)