2
/****************************************************************************
4
* MODULE: i.photo.rectify
5
* AUTHOR(S): Mike Baba, DBA Systems, Inc. (original contributor)
6
* Markus Neteler <neteler itc.it>,
7
* Bernhard Reiter <bernhard intevation.de>,
8
* Glynn Clements <glynn gclements.plus.com>,
9
* Hamish Bowman <hamish_b yahoo.com>,
12
* PURPOSE: Rectifies an image by using the image to photo coordinate
13
* and photo to target transformation matrices
14
* COPYRIGHT: (C) 1999-2010 by the GRASS Development Team
16
* This program is free software under the GNU General Public
17
* License (>=v2). Read the file COPYING that comes with GRASS
20
*****************************************************************************/
26
int seg_mb_img, seg_mb_elev;
29
struct Ortho_Image_Group group;
36
struct Cell_head target_window;
38
void err_exit(char *, char *);
40
/* modify this table to add new methods */
41
struct menu menu[] = {
42
{p_nearest, "nearest", "nearest neighbor"},
43
{p_bilinear, "bilinear", "bilinear"},
44
{p_cubic, "cubic", "cubic convolution"},
45
{p_bilinear_f, "bilinear_f", "bilinear with fallback"},
46
{p_cubic_f, "cubic_f", "cubic convolution with fallback"},
50
static char *make_ipol_list(void);
52
int main(int argc, char *argv[])
54
char extension[INAME_LEN];
55
char *ipolname; /* name of interpolation method */
59
int got_file = 0, target_overwrite = 0;
69
struct Cell_head cellhd, elevhd;
71
struct Option *grp, /* imagery group */
72
*ifile, /* input files */
74
*tres, /* target resolution */
75
*mem, /* amount of memory for cache */
76
*interpol, /* interpolation method:
77
nearest neighbor, bilinear, cubic */
78
*angle; /* camera angle relative to ground surface */
81
struct GModule *module;
85
module = G_define_module();
86
module->keywords = _("imagery, orthorectify");
88
_("Orthorectifies an image by using the image to photo coordinate transformation matrix.");
90
grp = G_define_standard_option(G_OPT_I_GROUP);
92
ifile = G_define_standard_option(G_OPT_R_INPUTS);
95
ext = G_define_option();
96
ext->key = "extension";
97
ext->type = TYPE_STRING;
100
ext->description = _("Output raster map(s) suffix");
102
tres = G_define_option();
103
tres->key = "resolution";
104
tres->type = TYPE_DOUBLE;
106
tres->description = _("Target resolution (ignored if -c flag used)");
108
mem = G_define_option();
110
mem->type = TYPE_DOUBLE;
111
mem->key_desc = "memory in MB";
114
mem->description = _("Amount of memory to use in MB");
116
ipolname = make_ipol_list();
118
interpol = G_define_option();
119
interpol->key = "method";
120
interpol->type = TYPE_STRING;
121
interpol->required = NO;
122
interpol->answer = "nearest";
123
interpol->options = ipolname;
124
interpol->description = _("Interpolation method to use");
126
angle = G_define_standard_option(G_OPT_R_OUTPUT);
127
angle->key = "angle";
128
angle->required = NO;
129
angle->description = _("Raster map with camera angle relative to ground surface");
134
_("Use current region settings in target location (def.=calculate smallest area)");
138
a->description = _("Rectify all raster maps in group");
140
if (G_parser(argc, argv))
144
for (method = 0; (ipolname = menu[method].name); method++)
145
if (strcmp(ipolname, interpol->answer) == 0)
149
G_fatal_error(_("<%s=%s> unknown %s"),
150
interpol->key, interpol->answer, interpol->key);
151
interpolate = menu[method].method;
153
G_strip(grp->answer);
154
strcpy(group.name, grp->answer);
155
strcpy(extension, ext->answer);
159
if (atoi(mem->answer) > 0)
160
seg_mb = mem->answer;
164
a->answer = 1; /* force all */
166
/* Find out how many files on command line */
168
for (k = 0; ifile->answers[k]; k++);
171
camera = (char *)G_malloc(GNAME_MAX * sizeof(char));
172
elev_name = (char *)G_malloc(GNAME_MAX * sizeof(char));
173
elev_mapset = (char *)G_malloc(GMAPSET_MAX * sizeof(char));
176
if (!I_find_group(group.name))
177
G_fatal_error(_("Group <%s> not found"), group.name);
179
/* get the group ref */
180
if (!I_get_group_ref(group.name, (struct Ref *)&group.group_ref))
181
G_fatal_error(_("Could not read REF file for group <%s>"), group.name);
182
nfiles = group.group_ref.nfiles;
184
G_important_message(_("Group <%s> contains no raster maps; run i.group"),
189
ref_list = (int *)G_malloc(nfiles * sizeof(int));
192
for (n = 0; n < group.group_ref.nfiles; n++) {
197
char xname[GNAME_MAX], xmapset[GMAPSET_MAX], *name, *mapset;
199
for (n = 0; n < group.group_ref.nfiles; n++)
202
for (m = 0; m < k; m++) {
204
if (G__name_is_fully_qualified(ifile->answers[m], xname, xmapset)) {
209
name = ifile->answers[m];
214
for (n = 0; n < group.group_ref.nfiles; n++) {
216
if (strcmp(name, group.group_ref.file[n].name) == 0 &&
217
strcmp(mapset, group.group_ref.file[n].mapset) == 0) {
224
if (strcmp(name, group.group_ref.file[n].name) == 0) {
232
err_exit(ifile->answers[m], group.name);
236
/** look for camera info for this block **/
237
if (!I_get_group_camera(group.name, camera))
238
G_fatal_error(_("No camera reference file selected for group <%s>"),
241
if (!I_get_cam_info(camera, &group.camera_ref))
242
G_fatal_error(_("Bad format in camera file for group <%s>"),
245
/* get initial camera exposure station, if any */
246
if (I_find_initial(group.name)) {
247
if (!I_get_init_info(group.name, &group.camera_exp))
248
G_warning(_("Bad format in initial exposure station file for group <%s>"),
252
/* read the reference points for the group, compute image-to-photo trans. */
255
/* read the control points for the group, convert to photo coords. */
259
get_target(group.name);
261
/* Check the GRASS_OVERWRITE environment variable */
262
if ((overstr = getenv("GRASS_OVERWRITE"))) /* OK ? */
263
target_overwrite = atoi(overstr);
265
if (!target_overwrite) {
266
/* check if output exists in target location/mapset */
267
char result[GNAME_MAX];
270
for (i = 0; i < group.group_ref.nfiles; i++) {
274
strcpy(result, group.group_ref.file[i].name);
275
strcat(result, extension);
277
if (G_legal_filename(result) < 0)
278
G_fatal_error(_("Extension <%s> is illegal"), extension);
280
if (G_find_cell(result, G_mapset())) {
281
G_warning(_("The following raster map already exists in"));
282
G_warning(_("target LOCATION %s, MAPSET %s:"),
283
G_location(), G_mapset());
284
G_warning("<%s>", result);
285
G_fatal_error(_("Orthorectification cancelled."));
289
if (G_find_cell(angle->answer, G_mapset())) {
290
G_warning(_("The following raster map already exists in"));
291
G_warning(_("target LOCATION %s, MAPSET %s:"),
292
G_location(), G_mapset());
293
G_warning("<%s>", angle->answer);
294
G_fatal_error(_("Orthorectification cancelled."));
298
select_current_env();
301
G_debug(1, "Overwriting OK");
303
/* do not use current region in target location */
308
if (!((res = atof(tres->answer)) > 0))
309
G_warning(_("Target resolution must be > 0, ignored"));
311
/* get reference window from imagery group */
312
get_ref_window(&cellhd);
313
georef_window(&cellhd, &target_window, res);
316
G_verbose_message(_("Using region: N=%f S=%f, E=%f W=%f"), target_window.north,
317
target_window.south, target_window.east, target_window.west);
319
G_debug(1, "Looking for elevation file in group: <%s>", group.name);
321
/* get the block elevation layer raster map in target location */
322
if (!I_get_group_elev(group.name, elev_name, elev_mapset, tl,
323
math_exp, units, nd))
324
G_fatal_error(_("No target elevation model selected for group <%s>"),
327
G_debug(1, "Block elevation: <%s> in <%s>", elev_name, elev_mapset);
329
/* get the elevation layer header in target location */
331
G_get_cellhd(elev_name, elev_mapset, &elevhd);
332
select_current_env();
334
/* determine memory for elevation and imagery */
335
seg_mb_img = seg_mb_elev = -1;
337
int max_rows, max_cols;
339
double max_mb_img, max_mb_elev;
342
max_rows = max_cols = 0;
343
for (i = 0; i < group.group_ref.nfiles; i++) {
345
G_get_cellhd(group.group_ref.file[i].name,
346
group.group_ref.file[i].mapset, &cellhd);
347
if (max_rows < cellhd.rows)
348
max_rows = cellhd.rows;
349
if (max_cols < cellhd.cols)
350
max_cols = cellhd.cols;
354
ny = (max_rows + BDIM - 1) / BDIM;
355
nx = (max_cols + BDIM - 1) / BDIM;
357
max_mb_img = ((double)nx * ny * sizeof(block)) / (1<<20);
359
ny = (target_window.rows + BDIM - 1) / BDIM;
360
nx = (target_window.cols + BDIM - 1) / BDIM;
362
max_mb_elev = ((double)nx * ny * sizeof(block)) / (1<<20);
364
if ((seg_mb_total = atoi(seg_mb)) > 0) {
365
seg_mb_elev = max_mb_elev * (seg_mb_total / (max_mb_img + max_mb_elev)) + 0.5;
366
seg_mb_img = max_mb_img * (seg_mb_total / (max_mb_img + max_mb_elev)) + 0.5;
371
exec_rectify(extension, interpol->answer, angle->answer);
377
void err_exit(char *file, char *grp)
381
G_warning(_("Input raster map <%s> does not exist in group <%s>."),
383
G_message(_("Try:"));
385
for (n = 0; n < group.group_ref.nfiles; n++)
386
G_message("%s@%s", group.group_ref.file[n].name, group.group_ref.file[n].mapset);
388
G_fatal_error(_("Exit!"));
391
static char *make_ipol_list(void)
397
for (i = 0; menu[i].name; i++)
398
size += strlen(menu[i].name) + 1;
400
buf = G_malloc(size);
403
for (i = 0; menu[i].name; i++) {
406
strcat(buf, menu[i].name);