1# import the batch module and dbvalue from init
2# set the global variable, batch, on init before importing this file
3
4import brl_init
5dbvalue = brl_init.DummyBatch()
6batch = brl_init.DummyBatch()
7
8
9class VpglException(brl_init.BrlException):
10    pass
11
12#############################################################################
13# PROVIDES higher level vpgl python functions to make batch
14# code more readable/refactored
15#############################################################################
16
17import math
18
19# ;
20# camera loading;
21# ;
22
23
24def load_perspective_camera(file_path):
25    batch.init_process("vpglLoadPerspectiveCameraProcess")
26    batch.set_input_string(0, file_path)
27    batch.run_process()
28    (id, type) = batch.commit_output(0)
29    cam = dbvalue(id, type)
30    return cam
31
32
33def load_affine_camera(file_path, viewing_dist=1000, look_dir=(0, 0, -1)):
34    """ load an affine camera from a text file containing the projection matrix
35        The viewing rays will be flipped such that the dot product with look_dir is positive
36    """
37    batch.init_process("vpglLoadAffineCameraProcess")
38    batch.set_input_string(0, file_path)
39    batch.set_input_double(1, viewing_dist)
40    batch.set_input_double(2, look_dir[0])
41    batch.set_input_double(3, look_dir[1])
42    batch.set_input_double(4, look_dir[2])
43    batch.run_process()
44    (id, type) = batch.commit_output(0)
45    cam = dbvalue(id, type)
46    return cam
47
48
49def load_projective_camera(file_path):
50    batch.init_process("vpglLoadProjCameraProcess")
51    batch.set_input_string(0, file_path)
52    batch.run_process()
53    (id, type) = batch.commit_output(0)
54    cam = dbvalue(id, type)
55    return cam
56
57#Scale = (scale_u, scale_v), ppoint = (u,v), center = (x,y,z), look_pt = (x,y,z), up = (x,y,z);
58def create_perspective_camera(scale, ppoint, center, look_pt, up=[0, 1, 0]):
59    batch.init_process("vpglCreatePerspectiveCameraProcess")
60    batch.set_input_double(0, scale[0])
61    batch.set_input_double(1, ppoint[0])
62    batch.set_input_double(2, scale[1])
63    batch.set_input_double(3, ppoint[1])
64    batch.set_input_double(4, center[0])
65    batch.set_input_double(5, center[1])
66    batch.set_input_double(6, center[2])
67    batch.set_input_double(7, look_pt[0])
68    batch.set_input_double(8, look_pt[1])
69    batch.set_input_double(9, look_pt[2])
70    batch.run_process()
71    (id, type) = batch.commit_output(0)
72    cam = dbvalue(id, type)
73    return cam
74
75
76def create_perspective_camera_from_kml(ni, nj, right_fov, top_fov, altitude, heading, tilt, roll, cent_x, cent_y):
77    batch.init_process("vpglCreatePerspCameraFromKMLProcess")
78    batch.set_input_unsigned(0, ni)
79    batch.set_input_unsigned(1, nj)
80    batch.set_input_double(2, right_fov)
81    batch.set_input_double(3, top_fov)
82    batch.set_input_double(4, altitude)
83    batch.set_input_double(5, heading)
84    batch.set_input_double(6, tilt)
85    batch.set_input_double(7, roll)
86    batch.set_input_double(8, cent_x)
87    batch.set_input_double(9, cent_y)
88    batch.run_process()
89    (id, type) = batch.commit_output(0)
90    cam = dbvalue(id, type)
91    return cam
92
93
94def load_perspective_camera_from_kml_file(NI, NJ, kml_file):
95    batch.init_process("vpglLoadPerspCameraFromKMLFileProcess")
96    batch.set_input_unsigned(0, NI)
97    batch.set_input_unsigned(1, NJ)
98    batch.set_input_string(2, kml_file)
99    batch.run_process()
100    (id, type) = batch.commit_output(0)
101    cam = dbvalue(id, type)
102    (id, type) = batch.commit_output(1)
103    longitude = batch.get_output_double(id)
104    batch.remove_data(id)
105    (id, type) = batch.commit_output(2)
106    latitude = batch.get_output_double(id)
107    batch.remove_data(id)
108    (id, type) = batch.commit_output(3)
109    altitude = batch.get_output_double(id)
110    batch.remove_data(id)
111    return cam, longitude, latitude, altitude
112
113# resize a camera from size0 =(ni,nj) to size1 (ni_1, nj_1);
114def resample_perspective_camera(cam, size0, size1):
115    batch.init_process("vpglResamplePerspectiveCameraProcess")
116    batch.set_input_from_db(0, cam)
117    batch.set_input_int(1, size0[0])
118    batch.set_input_int(2, size0[1])
119    batch.set_input_int(3, size1[0])
120    batch.set_input_int(4, size1[1])
121    batch.run_process()
122    (id, type) = batch.commit_output(0)
123    out = dbvalue(id, type)
124    return out
125# resize a camera from size0 =(ni,nj) to size1 (ni_1, nj_1);
126def get_perspective_camera_center(cam):
127    batch.init_process("vpglGetPerspectiveCamCenterProcess")
128    batch.set_input_from_db(0, cam)
129    batch.run_process()
130    (id, type) = batch.commit_output(0)
131    x = batch.get_output_float(id)
132    batch.remove_data(id)
133    (id, type) = batch.commit_output(1)
134    y = batch.get_output_float(id)
135    batch.remove_data(id)
136    (id, type) = batch.commit_output(2)
137    z = batch.get_output_float(id)
138    batch.remove_data(id)
139    return x, y, z
140
141
142def get_backprojected_ray(cam, u, v):
143    batch.init_process("vpglGetBackprojectRayProcess")
144    batch.set_input_from_db(0, cam)
145    batch.set_input_float(1, u)
146    batch.set_input_float(2, v)
147    batch.run_process()
148    (id, type) = batch.commit_output(0)
149    x = batch.get_output_float(id)
150    batch.remove_data(id)
151    (id, type) = batch.commit_output(1)
152    y = batch.get_output_float(id)
153    batch.remove_data(id)
154    (id, type) = batch.commit_output(2)
155    z = batch.get_output_float(id)
156    batch.remove_data(id)
157    return x, y, z
158
159# returns cartesian cam center from azimuth (degrees), elevation
160# (degrees), radius, look point;
161def get_rpc_backprojected_ray(cam, u, v, altitude, initial_lon, initial_lat, initial_alt):
162    batch.init_process("vpglGetRpcBackprojectRayProcess")
163    batch.set_input_from_db(0, cam)
164    batch.set_input_double(1, u)
165    batch.set_input_double(2, v)
166    batch.set_input_double(3, altitude)
167    batch.set_input_double(4, initial_lon)
168    batch.set_input_double(5, initial_lat)
169    batch.set_input_double(6, initial_alt)
170    batch.run_process()
171    (id, type) = batch.commit_output(0)
172    x = batch.get_output_double(id)
173    batch.remove_data(id)
174    (id, type) = batch.commit_output(1)
175    y = batch.get_output_double(id)
176    batch.remove_data(id)
177    (id, type) = batch.commit_output(2)
178    z = batch.get_output_double(id)
179    batch.remove_data(id)
180    return x, y, z
181
182
183def get_camera_center(azimuth, elevation, radius, lookPt):
184    deg_to_rad = math.pi / 180.0
185    el = elevation * deg_to_rad
186    az = azimuth * deg_to_rad
187    cx = radius * math.sin(el) * math.cos(az)
188    cy = radius * math.sin(el) * math.sin(az)
189    cz = radius * math.cos(el)
190    center = (cx + lookPt[0], cy + lookPt[1], cz + lookPt[2])
191    return center
192
193# returns spherical coordinates about sCenter given cartesian point;
194def cart2sphere(cartPt, sCenter):
195    # offset cart point;
196    cartPt = numpy.subtract(cartPt, sCenter)
197    rad = math.sqrt(sum(cartPt * cartPt))
198    az = math.atan2(cartPt[1], cartPt[0])
199    el = math.acos(cartPt[2] / rad)
200    return (math.degrees(az), math.degrees(el), rad)
201
202
203def load_rational_camera(file_path):
204    batch.init_process("vpglLoadRationalCameraProcess")
205    batch.set_input_string(0, file_path)
206    status = batch.run_process()
207    cam = None
208    if status:
209        (id, type) = batch.commit_output(0)
210        cam = dbvalue(id, type)
211        return cam
212    else:
213        raise VpglException("Failed to load Rational Camera")
214
215
216def load_local_rational_camera(file_path):
217    batch.init_process("vpglLoadLocalRationalCameraProcess")
218    batch.set_input_string(0, file_path)
219    batch.run_process()
220    (id, type) = batch.commit_output(0)
221    cam = dbvalue(id, type)
222    return cam
223
224
225def load_rational_camera_nitf(file_path):
226    batch.init_process("vpglLoadRationalCameraNITFProcess")
227    batch.set_input_string(0, file_path)
228    batch.run_process()
229    (id, type) = batch.commit_output(0)
230    cam = dbvalue(id, type)
231    return cam
232
233
234def load_rational_camera_from_txt(file_path):
235    batch.init_process("vpglLoadRationalCameraFromTXTProcess")
236    batch.set_input_string(0, file_path)
237    status = batch.run_process()
238    if status:
239        (id, type) = batch.commit_output(0)
240        cam = dbvalue(id, type)
241        return cam
242    else:
243        raise VpglException("Failed to load Rational Camera from txt")
244
245
246def convert_local_rational_perspective_camera(local_cam):
247    batch.init_process("vpglConvertLocalRationalToPerspectiveProcess")
248    batch.set_input_from_db(0, local_cam)
249    batch.run_process()
250    (id, type) = batch.commit_output(0)
251    cam = dbvalue(id, type)
252    return cam
253
254
255def create_local_rational_camera(rational_cam_fname, lvcs_fname):
256    batch.init_process('vpglCreateLocalRationalCameraProcess')
257    batch.set_input_string(0, rational_cam_fname)
258    batch.set_input_string(1, lvcs_fname)
259    batch.run_process()
260    (id, type) = batch.commit_output(0)
261    cam = dbvalue(id, type)
262    return cam
263
264
265def convert_to_local_rational_camera(rational_cam, lvcs):
266    batch.init_process('vpglConvertToLocalRationalCameraProcess')
267    batch.set_input_from_db(0, rational_cam)
268    batch.set_input_from_db(1, lvcs)
269    status = batch.run_process()
270    cam = None
271    if status:
272        (id, type) = batch.commit_output(0)
273        cam = dbvalue(id, type)
274        return cam
275    else:
276        raise VpglException("Failed to convert local rational camera")
277
278# ;
279# camera saving;
280# ;
281def print_rational_camera(camera):
282    batch.init_process("vpglPrintRationalCameraProcess")
283    batch.set_input_from_db(0, camera)
284    status = batch.run_process()
285    if status:
286        return
287    else:
288        raise VpglException("Failed to print rational camera")
289
290def save_rational_camera(camera, path):
291    batch.init_process("vpglSaveRationalCameraProcess")
292    batch.set_input_from_db(0, camera)
293    batch.set_input_string(1, path)
294    batch.run_process()
295
296
297def save_perspective_camera(camera, path):
298    batch.init_process("vpglSavePerspectiveCameraProcess")
299    batch.set_input_from_db(0, camera)
300    batch.set_input_string(1, path)
301    batch.run_process()
302
303
304def save_perspective_camera_vrml(camera, path):
305    batch.init_process("vpglSavePerspectiveCameraVrmlProcess")
306    batch.set_input_from_db(0, camera)
307    batch.set_input_string(1, path)
308    batch.set_input_float(2, 5.0)
309    batch.run_process()
310
311
312def save_perspective_cameras_vrml(camerafolder, path):
313    batch.init_process("vpglSavePerspectiveCamerasVrmlProcess")
314    batch.set_input_string(0, camerafolder)
315    batch.set_input_string(1, path)
316    batch.set_input_float(2, 5.0)
317    batch.run_process()
318
319
320def save_proj_camera(camera, path):
321    batch.init_process("vpglSaveProjectiveCameraProcess")
322    batch.set_input_from_db(0, camera)
323    batch.set_input_string(1, path)
324    batch.run_process()
325
326# ;
327# perspective go generic conversion;
328# ;
329def persp2gen(pcam, ni, nj, level=0):
330    batch.init_process("vpglConvertToGenericCameraProcess")
331    batch.set_input_from_db(0, pcam)
332    batch.set_input_unsigned(1, ni)
333    batch.set_input_unsigned(2, nj)
334    batch.set_input_unsigned(3, level)
335    status = batch.run_process()
336    gcam = None
337    if status:
338        (id, type) = batch.commit_output(0)
339        gcam = dbvalue(id, type)
340        return gcam
341    else:
342        raise VpglException("Failed to convert perspective camera to generic")
343
344
345def persp2genWmargin(pcam, ni, nj, margin, level=0):
346    batch.init_process("vpglConvertToGenericCameraWithMarginProcess")
347    batch.set_input_from_db(0, pcam)
348    batch.set_input_unsigned(1, ni)
349    batch.set_input_unsigned(2, nj)
350    batch.set_input_unsigned(3, level)
351    batch.set_input_int(4, margin)
352    batch.run_process()
353    (id, type) = batch.commit_output(0)
354    gcam = dbvalue(id, type)
355    (id, type) = batch.commit_output(1)
356    ni = batch.get_output_unsigned(id)
357    batch.remove_data(id)
358    (id, type) = batch.commit_output(2)
359    nj = batch.get_output_unsigned(id)
360    batch.remove_data(id)
361    (id, type) = batch.commit_output(3)
362    new_pers_cam = dbvalue(id, type)
363    return (gcam, ni, nj, new_pers_cam)
364
365
366def write_generic_to_vrml(cam, out_file_name, level=0):
367    batch.init_process("vpglWriteGenericCameraProcess")
368    batch.set_input_from_db(0, cam)
369    batch.set_input_string(1, out_file_name)
370    batch.set_input_unsigned(2, level)
371    batch.run_process()
372
373
374def get_generic_cam_ray(cam, u, v):
375    batch.init_process("vpglGetGenericCamRayProcess")
376    batch.set_input_from_db(0, cam)
377    batch.set_input_unsigned(1, u)
378    batch.set_input_unsigned(2, v)
379    batch.run_process()
380    (id, type) = batch.commit_output(0)
381    orig_x = batch.get_output_double(id)
382    batch.remove_data(id)
383    (id, type) = batch.commit_output(1)
384    orig_y = batch.get_output_double(id)
385    batch.remove_data(id)
386    (id, type) = batch.commit_output(2)
387    orig_z = batch.get_output_double(id)
388    batch.remove_data(id)
389    (id, type) = batch.commit_output(3)
390    dir_x = batch.get_output_double(id)
391    batch.remove_data(id)
392    (id, type) = batch.commit_output(4)
393    dir_y = batch.get_output_double(id)
394    batch.remove_data(id)
395    (id, type) = batch.commit_output(5)
396    dir_z = batch.get_output_double(id)
397    batch.remove_data(id)
398    return orig_x, orig_y, orig_z, dir_x, dir_y, dir_z
399
400# gets bounding box from a directory of cameras... (incomplete)_;
401def camera_dir_planar_bbox(dir_name):
402    batch.init_process("vpglGetBoundingBoxProcess")
403    batch.set_input_string(0, dir_name)
404    batch.run_process()
405
406
407def project_point(camera, x, y, z):
408    batch.init_process('vpglProjectProcess')
409    batch.set_input_from_db(0, camera)
410    batch.set_input_double(1, x)
411    batch.set_input_double(2, y)
412    batch.set_input_double(3, z)
413    batch.run_process()
414    (id, type) = batch.commit_output(0)
415    u = batch.get_output_double(id)
416    batch.remove_data(id)
417    (id, type) = batch.commit_output(1)
418    v = batch.get_output_double(id)
419    batch.remove_data(id)
420    return (u, v)
421
422# gets view direction at a point for a perspective camera;
423def get_view_at_point(persp_cam, x, y, z):
424    batch.init_process("vpglGetViewDirectionAtPointProcess")
425    batch.set_input_from_db(0, persp_cam)
426    batch.set_input_float(1, x)
427    batch.set_input_float(2, y)
428    batch.set_input_float(3, z)
429    batch.run_process()
430    (id, type) = batch.commit_output(0)
431    theta = batch.get_output_float(id)
432    batch.remove_data(id)
433    (id, type) = batch.commit_output(1)
434    phi = batch.get_output_float(id)
435    batch.remove_data(id)
436    return theta, phi
437
438
439def get_xyz_from_depth_image(cam, depth_img):
440    batch.init_process("vpglGenerateXYZFromDepthImageProcess")
441    batch.set_input_from_db(0, cam)  # perspective or generic camera
442    batch.set_input_from_db(1, depth_img)
443    batch.run_process()
444    (id, type) = batch.commit_output(0)
445    x_img = dbvalue(id, type)
446    (id, type) = batch.commit_output(1)
447    y_img = dbvalue(id, type)
448    (id, type) = batch.commit_output(2)
449    z_img = dbvalue(id, type)
450
451    return x_img, y_img, z_img
452
453
454def get_3d_from_depth(cam, u, v, t):
455    batch.init_process("vpglGenerate3dPointFromDepthProcess")
456    batch.set_input_from_db(0, cam)  # perspective or generic camera
457    batch.set_input_float(1, u)
458    batch.set_input_float(2, v)
459    batch.set_input_float(3, t)
460    batch.run_process()
461    (id, type) = batch.commit_output(0)
462    x = batch.get_output_float(id)
463    batch.remove_data(id)
464    (id, type) = batch.commit_output(1)
465    y = batch.get_output_float(id)
466    batch.remove_data(id)
467    (id, type) = batch.commit_output(2)
468    z = batch.get_output_float(id)
469    batch.remove_data(id)
470    return x, y, z
471
472# triangulates a list of cams and a list of points;
473def get_3d_from_cams(cams, points):
474    assert(len(cams) == len(points) and len(cams) > 1)
475    # list of points will just be [u1,v1,u2,v2...];
476    ptlist = []
477    for p in points:
478        ptlist.append(p[0])
479        ptlist.append(p[1])
480    # list of cam ids (type will be checked in C++);
481    camlist = []
482    for cam in cams:
483        camlist.append(cam.id)
484    batch.init_process("vpglGenerate3dPointFromCamsProcess")
485    batch.set_input_unsigned_array(0, camlist)
486    batch.set_input_int_array(1, ptlist)
487    batch.run_process()
488    (id, type) = batch.commit_output(0)
489    x = batch.get_output_float(id)
490    batch.remove_data(id)
491    (id, type) = batch.commit_output(1)
492    y = batch.get_output_float(id)
493    batch.remove_data(id)
494    (id, type) = batch.commit_output(2)
495    z = batch.get_output_float(id)
496    batch.remove_data(id)
497    return x, y, z
498
499# create a generic camera;
500def convert_to_generic_camera(cam_in, ni, nj, level=0):
501    batch.init_process('vpglConvertToGenericCameraProcess')
502    batch.set_input_from_db(0, cam_in)
503    batch.set_input_unsigned(1, ni)
504    batch.set_input_unsigned(2, nj)
505    batch.set_input_unsigned(3, level)
506    status = batch.run_process()
507    generic_cam = None
508    if status:
509        (id, type) = batch.commit_output(0)
510        generic_cam = dbvalue(id, type)
511        return generic_cam
512    else:
513        raise VpglException("Failed to convert to generic camera")
514
515# create a generic camera from a local rational with user-specified z range;
516def convert_local_rational_to_generic(cam_in, ni, nj, min_z, max_z, level=0):
517    batch.init_process('vpglConvertLocalRationalToGenericProcess')
518    batch.set_input_from_db(0, cam_in)
519    batch.set_input_unsigned(1, ni)
520    batch.set_input_unsigned(2, nj)
521    batch.set_input_float(3, min_z)
522    batch.set_input_float(4, max_z)
523    batch.set_input_unsigned(5, level)
524    if not batch.run_process():
525        return None
526    (id, type) = batch.commit_output(0)
527    generic_cam = dbvalue(id, type)
528    return generic_cam
529
530# correct a rational camera;
531def correct_rational_camera(cam_in, offset_x, offset_y, verbose = False):
532    batch.init_process('vpglCorrectRationalCameraProcess')
533    batch.set_input_from_db(0, cam_in)
534    batch.set_input_double(1, offset_x)
535    batch.set_input_double(2, offset_y)
536    batch.set_input_bool(3, verbose)
537    if not batch.run_process():
538        return None
539    (id, type) = batch.commit_output(0)
540    corrected_cam = dbvalue(id, type)
541    return corrected_cam
542
543
544def get_rational_camera_offsets(cam_in):
545    batch.init_process('vpglGetRationalCameraOffsetsProcess')
546    batch.set_input_from_db(0, cam_in)
547    batch.run_process()
548    (id, type) = batch.commit_output(0)
549    offset_u = batch.get_output_double(id)
550    batch.remove_data(id)
551    (id, type) = batch.commit_output(1)
552    offset_v = batch.get_output_double(id)
553    batch.remove_data(id)
554    return (offset_u, offset_v)
555
556
557def get_correction_offset(cam_orig, cam_corrected):
558    offset_u,   offset_v = get_rational_camera_offsets(cam_orig)
559    offset_u_c, offset_v_c = get_rational_camera_offsets(cam_corrected)
560    diff_u = offset_u_c - offset_u
561    diff_v = offset_v_c - offset_v
562    return diff_u, diff_v
563
564
565def find_offset_and_correct_rational_camera(cam_orig, cam_corrected, cam_to_be_corrected):
566    offset_u, offset_v = get_rational_camera_offsets(cam_orig)
567    offset_u_c, offset_v_c = get_rational_camera_offsets(cam_corrected)
568    diff_u = offset_u_c - offset_u
569    diff_v = offset_v_c - offset_v
570    cam_out = correct_rational_camera(cam_to_be_corrected, diff_u, diff_v)
571    return cam_out
572
573# convert lat,lon,el to local coordinates;
574def convert_to_local_coordinates(lvcs_filename, lat, lon, el):
575    batch.init_process('vpglConvertToLocalCoordinatesProcess')
576    batch.set_input_string(0, lvcs_filename)
577    batch.set_input_float(1, lat)
578    batch.set_input_float(2, lon)
579    batch.set_input_float(3, el)
580    batch.run_process()
581    (id, type) = batch.commit_output(0)
582    x = batch.get_output_float(id)
583    batch.remove_data(id)
584    (id, type) = batch.commit_output(1)
585    y = batch.get_output_float(id)
586    batch.remove_data(id)
587    (id, type) = batch.commit_output(2)
588    z = batch.get_output_float(id)
589    batch.remove_data(id)
590    return (x, y, z)
591
592# convert lat,lon,el to local coordinates;
593def convert_to_local_coordinates2(lvcs, lat, lon, el):
594    batch.init_process('vpglConvertToLocalCoordinatesProcess2')
595    batch.set_input_from_db(0, lvcs)
596    batch.set_input_double(1, lat)
597    batch.set_input_double(2, lon)
598    batch.set_input_double(3, el)
599    batch.run_process()
600    (id, type) = batch.commit_output(0)
601    x = batch.get_output_double(id)
602    batch.remove_data(id)
603    (id, type) = batch.commit_output(1)
604    y = batch.get_output_double(id)
605    batch.remove_data(id)
606    (id, type) = batch.commit_output(2)
607    z = batch.get_output_double(id)
608    batch.remove_data(id)
609    return (x, y, z)
610
611# convert lat,lon,el to local coordinates;
612def convert_local_to_global_coordinates(lvcs, x, y, z):
613    batch.init_process('vpglConvertLocalToGlobalCoordinatesProcess')
614    batch.set_input_from_db(0, lvcs)
615    batch.set_input_double(1, x)
616    batch.set_input_double(2, y)
617    batch.set_input_double(3, z)
618    batch.run_process()
619    (id, type) = batch.commit_output(0)
620    lat = batch.get_output_double(id)
621    batch.remove_data(id)
622    (id, type) = batch.commit_output(1)
623    lon = batch.get_output_double(id)
624    batch.remove_data(id)
625    (id, type) = batch.commit_output(2)
626    el = batch.get_output_double(id)
627    batch.remove_data(id)
628    return (lat, lon, el)
629
630# convert lat,lon,el to local coordinates;
631def convert_local_to_global_coordinates_array(lvcs, x, y, z):
632    batch.init_process('vpglConvertLocalToGlobalCoordinatesArrayProcess')
633    batch.set_input_from_db(0, lvcs)
634    batch.set_input_double_array(1, x)
635    batch.set_input_double_array(2, y)
636    batch.set_input_double_array(3, z)
637    batch.run_process()
638    (id, type) = batch.commit_output(0)
639    lat = batch.get_output_double_array(id)
640    batch.remove_data(id)
641    (id, type) = batch.commit_output(1)
642    lon = batch.get_output_double_array(id)
643    batch.remove_data(id)
644    (id, type) = batch.commit_output(2)
645    el = batch.get_output_double_array(id)
646    batch.remove_data(id)
647    return (lat, lon, el)
648
649# convert lat,lon,el to local coordinates;
650def create_lvcs(lat, lon, el, csname):
651    batch.init_process('vpglCreateLVCSProcess')
652    batch.set_input_double(0, lat)
653    batch.set_input_double(1, lon)
654    batch.set_input_double(2, el)
655    batch.set_input_string(3, csname)
656    batch.run_process()
657    (id, type) = batch.commit_output(0)
658    lvcs = dbvalue(id, type)
659    return lvcs
660
661# randomly sample a camera rotated around principal axis;
662def perturb_camera(cam_in, angle, rng):
663    batch.init_process('vpglPerturbPerspCamOrientProcess')
664    batch.set_input_from_db(0, cam_in)
665    batch.set_input_float(1, angle)
666    batch.set_input_from_db(2, rng)
667    batch.run_process()
668    (id, type) = batch.commit_output(0)
669    pert_cam = dbvalue(id, type)
670    (theta_id, type) = batch.commit_output(1)
671    (phi_id, type) = batch.commit_output(2)
672    theta = batch.get_output_float(theta_id)
673    phi = batch.get_output_float(phi_id)
674    batch.remove_data(theta_id)
675    batch.remove_data(phi_id)
676    return pert_cam, theta, phi
677
678
679def write_perspective_cam_vrml(vrml_filename, pcam, camera_rad, axis_length, r, g, b):
680    batch.init_process("bvrmlWritePerspectiveCamProcess")
681    batch.set_input_string(0, vrml_filename)
682    batch.set_input_from_db(1, pcam)
683    batch.set_input_float(2, camera_rad)
684    batch.set_input_float(3, axis_length)
685    batch.set_input_float(4, r)
686    batch.set_input_float(5, g)
687    batch.set_input_float(6, b)
688    batch.run_process()
689
690# rotate a camera around principal axis;
691def rotate_perspective_camera(cam_in, theta, phi):
692    batch.init_process('vpglRotatePerspCamProcess')
693    batch.set_input_from_db(0, cam_in)
694    batch.set_input_float(1, theta)
695    batch.set_input_float(2, phi)
696    batch.run_process()
697    (id, type) = batch.commit_output(0)
698    rot_cam = dbvalue(id, type)
699    return rot_cam
700
701
702def get_perspective_cam_center(pcam):
703    batch.init_process("vpglGetPerspectiveCamCenterProcess")
704    batch.set_input_from_db(0, pcam)
705    batch.run_process()
706    (x_id, x_type) = batch.commit_output(0)
707    x = batch.get_output_float(x_id)
708    batch.remove_data(x_id)
709    (y_id, type) = batch.commit_output(1)
710    y = batch.get_output_float(y_id)
711    batch.remove_data(y_id)
712    (z_id, type) = batch.commit_output(2)
713    z = batch.get_output_float(z_id)
714    batch.remove_data(z_id)
715    return x, y, z
716
717
718def create_perspective_camera2(pcam, cent_x, cent_y, cent_z):
719    batch.init_process("vpglCreatePerspectiveCameraProcess2")
720    batch.set_input_from_db(0, pcam)
721    batch.set_input_float(1, cent_x)
722    batch.set_input_float(2, cent_y)
723    batch.set_input_float(3, cent_z)
724    batch.run_process()
725    (c_id, c_type) = batch.commit_output(0)
726    cam = dbvalue(c_id, c_type)
727    return cam
728
729
730def create_perspective_camera_with_rot(pcam, phi, theta, cent_x, cent_y, cent_z):
731    batch.init_process("vpglCreatePerspectiveCameraProcess3")
732    batch.set_input_from_db(0, pcam)
733    batch.set_input_float(1, phi)
734    batch.set_input_float(2, theta)
735    batch.set_input_float(3, cent_x)
736    batch.set_input_float(4, cent_y)
737    batch.set_input_float(5, cent_z)
738    batch.run_process()
739    (c_id, c_type) = batch.commit_output(0)
740    cam = dbvalue(c_id, c_type)
741    return cam
742
743
744def get_nitf_footprint(nitf_list_filename, out_kml_filename):
745    batch.init_process('vpglNITFFootprintProcess')
746    batch.set_input_string(0, nitf_list_filename)
747    batch.set_input_string(1, out_kml_filename)
748    batch.run_process()
749
750
751def get_single_nitf_footprint(nitf_filename, out_kml_filename="", isKml=False, metafolder=""):
752    batch.init_process('vpglNITFFootprintProcess2')
753    batch.set_input_string(0, nitf_filename)
754    batch.set_input_string(1, out_kml_filename)
755    batch.set_input_bool(2, isKml)
756    batch.set_input_string(3, metafolder)
757    batch.run_process()
758    (id, type) = batch.commit_output(0)
759    llon = batch.get_output_double(id)
760    (id, type) = batch.commit_output(1)
761    llat = batch.get_output_double(id)
762    (id, type) = batch.commit_output(2)
763    lele = batch.get_output_double(id)
764    (id, type) = batch.commit_output(3)
765    rlon = batch.get_output_double(id)
766    (id, type) = batch.commit_output(4)
767    rlat = batch.get_output_double(id)
768    (id, type) = batch.commit_output(5)
769    rele = batch.get_output_double(id)
770    batch.remove_data(id)
771    return llon, llat, lele, rlon, rlat, rele
772
773# use a local lvcs to calculate GSD of nitf image
774def calculate_nitf_gsd(rational_cam, lon1, lat1, elev1, distance=1000.0):
775    # create a local lvcs
776    lvcs = create_lvcs(lat1, lon1, elev1, 'wgs84')
777    lat2, lon2, elev2 = convert_local_to_global_coordinates(
778        lvcs, distance, distance, 0.0)
779    # calculate image pixel difference
780    i1, j1 = project_point(rational_cam, lon1, lat1, elev1)
781    i2, j2 = project_point(rational_cam, lon2, lat2, elev2)
782    gsd_i = distance / (i2 - i1)
783    gsd_j = distance / (j2 - j1)
784    if (gsd_i < 0.0):
785        gsd_i = -1 * gsd_i
786    if (gsd_j < 0.0):
787        gsd_j = -1 * gsd_j
788    batch.remove_data(lvcs.id)
789    return gsd_i, gsd_j
790
791def get_geocam_footprint_with_value(geocam, geotiff_filename, out_kml_filename="", write_kml=False):
792    batch.init_process("vpglGeoFootprintProcess2")
793    batch.set_input_from_db(0, geocam)
794    batch.set_input_string(1, geotiff_filename)
795    batch.set_input_string(2, out_kml_filename)
796    batch.set_input_bool(3, write_kml)
797    status = batch.run_process()
798    if status:
799        (id, type) = batch.commit_output(0)
800        ll_lon = batch.get_output_double(id)
801        (id, type) = batch.commit_output(1)
802        ll_lat = batch.get_output_double(id)
803        (id, type) = batch.commit_output(2)
804        ur_lon = batch.get_output_double(id)
805        (id, type) = batch.commit_output(3)
806        ur_lat = batch.get_output_double(id)
807        return ll_lon, ll_lat, ur_lon, ur_lat
808    else:
809        raise VpglException("Failed to get geographic camera footprint")
810
811
812def load_geotiff_cam(tfw_filename, lvcs=0, utm_zone=0, utm_hemisphere=0):
813    batch.init_process("vpglLoadGeoCameraProcess")
814    batch.set_input_string(0, tfw_filename)
815    if lvcs != 0:
816        batch.set_input_from_db(1, lvcs)
817    batch.set_input_int(2, utm_zone)
818    batch.set_input_unsigned(3, utm_hemisphere)
819    batch.run_process()
820    (c_id, c_type) = batch.commit_output(0)
821    cam = dbvalue(c_id, c_type)
822    return cam
823
824
825def save_geocam_to_tfw(cam, tfw_filename):
826    batch.init_process("vpglSaveGeoCameraTFWProcess")
827    batch.set_input_from_db(0, cam)
828    batch.set_input_string(1, tfw_filename)
829    batch.run_process()
830
831
832def get_geotransform(cam):
833    batch.init_process("vpglGetGeoTransformProcess")
834    batch.set_input_from_db(0, cam)
835    status = batch.run_process()
836    if status:
837        GT = [None]*6
838        for idx,gt in enumerate(GT):
839            (id, type) = batch.commit_output(idx)
840            GT[idx] = batch.get_output_double(id)
841            batch.remove_data(id)
842        return GT
843    else:
844        raise VpglException("Failed to return geotransform")
845
846
847def load_geotiff_cam2(filename, ni, nj):
848    batch.init_process("vpglLoadGeoCameraProcess2")
849    batch.set_input_string(0, filename)
850    batch.set_input_unsigned(1, ni)
851    batch.set_input_unsigned(2, nj)
852    batch.run_process()
853    (c_id, c_type) = batch.commit_output(0)
854    cam = dbvalue(c_id, c_type)
855    return cam
856
857
858def load_geotiff_from_header(filename, lvcs=0):
859    batch.init_process("vpglLoadGeotiffCamFromHeaderProcess")
860    batch.set_input_string(0, filename)
861    if lvcs != 0:
862        batch.set_input_from_db(1, lvcs)
863    batch.run_process()
864    (c_id, c_type) = batch.commit_output(0)
865    cam = dbvalue(c_id, c_type)
866    return cam
867
868
869def translate_geo_camera(geocam, x, y):
870    batch.init_process("vpglTranslateGeoCameraProcess")
871    batch.set_input_from_db(0, geocam)
872    batch.set_input_double(1, x)
873    batch.set_input_double(2, y)
874    batch.run_process()
875    (c_id, c_type) = batch.commit_output(0)
876    cam = dbvalue(c_id, c_type)
877    return cam
878
879
880def create_geotiff_cam(ll_lon, ll_lat, ur_lon, ur_lat, ni, nj, lvcs=0):
881    batch.init_process("vpglCreateGeoCameraProcess")
882    batch.set_input_double(0, ll_lon)
883    batch.set_input_double(1, ll_lat)
884    batch.set_input_double(2, ur_lon)
885    batch.set_input_double(3, ur_lat)
886    batch.set_input_unsigned(4, ni)
887    batch.set_input_unsigned(5, nj)
888    if lvcs != 0:
889        batch.set_input_from_db(6, lvcs)
890    status = batch.run_process()
891    if status:
892        (id, type) = batch.commit_output(0)
893        cam = dbvalue(id, type)
894        return cam
895    else:
896        raise VpglException("Failed to create geotiff camera")
897
898
899def geo2generic(geocam, ni, nj, scene_height, level):
900    batch.init_process("vpglConvertGeoCameraToGenericProcess")
901    batch.set_input_from_db(0, geocam)
902    batch.set_input_int(1, ni)
903    batch.set_input_int(2, nj)
904    batch.set_input_double(3, scene_height)
905    batch.set_input_int(4, level)
906    batch.run_process()
907    (c_id, c_type) = batch.commit_output(0)
908    cam = dbvalue(c_id, c_type)
909    return cam
910
911
912def geo2generic_nonnadir(geocam, ni, nj, scene_height, dir_x, dir_y, dir_z, level):
913    batch.init_process("vpglConvertNonNadirGeoCameraToGenericProcess")
914    batch.set_input_from_db(0, geocam)
915    batch.set_input_int(1, ni)
916    batch.set_input_int(2, nj)
917    batch.set_input_double(3, scene_height)
918    batch.set_input_int(4, level)
919    batch.set_input_double(5, dir_x)
920    batch.set_input_double(6, dir_y)
921    batch.set_input_double(7, dir_z)
922    batch.run_process()
923    (c_id, c_type) = batch.commit_output(0)
924    cam = dbvalue(c_id, c_type)
925    return cam
926
927
928def save_lvcs(lvcs, lvcs_filename):
929    batch.init_process("vpglSaveLVCSProcess")
930    batch.set_input_from_db(0, lvcs)
931    batch.set_input_string(1, lvcs_filename)
932    return batch.run_process()
933
934
935def create_and_save_lvcs(lat, lon, elev, cs_name, lvcs_filename):
936    batch.init_process("vpglCreateAndSaveLVCSProcess")
937    batch.set_input_float(0, lat)
938    batch.set_input_float(1, lon)
939    batch.set_input_float(2, elev)
940    batch.set_input_string(3, cs_name)
941    batch.set_input_string(4, lvcs_filename)
942    return batch.run_process()
943
944
945def load_lvcs(lvcs_filename):
946    batch.init_process("vpglLoadLVCSProcess")
947    batch.set_input_string(0, lvcs_filename)
948    batch.run_process()
949    (lvcs_id, lvcs_type) = batch.commit_output(0)
950    lvcs = dbvalue(lvcs_id, lvcs_type)
951    return lvcs
952
953
954def geo_cam_global_to_img(geocam, lon, lat):
955    batch.init_process("vpglGeoGlobalToImgProcess")
956    batch.set_input_from_db(0, geocam)
957    batch.set_input_double(1, lon)
958    batch.set_input_double(2, lat)
959    batch.run_process()
960    (id, type) = batch.commit_output(0)
961    u = batch.get_output_int(id)
962    batch.remove_data(id)
963    (id, type) = batch.commit_output(1)
964    v = batch.get_output_int(id)
965    batch.remove_data(id)
966    return u, v
967
968
969def geo_cam_img_to_global(geocam, i, j):
970    batch.init_process("vpglGeoImgToGlobalProcess")
971    batch.set_input_from_db(0, geocam)
972    batch.set_input_unsigned(1, i)
973    batch.set_input_unsigned(2, j)
974    status = batch.run_process()
975    if status:
976        (id, type) = batch.commit_output(0)
977        lon = batch.get_output_double(id)
978        (id, type) = batch.commit_output(1)
979        lat = batch.get_output_double(id)
980        return lon, lat
981    else:
982        raise VpglException("Failed to convert geographic camera image to global")
983
984
985def convert_perspective_to_nvm(cams_dir, imgs_dir, output_nvm):
986    batch.init_process("vpglExportCamerasToNvmProcess")
987    batch.set_input_string(0, cams_dir)
988    batch.set_input_string(1, imgs_dir)
989    batch.set_input_string(2, output_nvm)
990    return batch.run_process()
991
992
993def interpolate_perspective_cameras(cam0, cam1, ncams, outdir):
994    batch.init_process("vpglInterpolatePerspectiveCamerasProcess")
995    batch.set_input_from_db(0, cam0)
996    batch.set_input_from_db(1, cam1)
997    batch.set_input_unsigned(2, ncams)
998    batch.set_input_string(3, outdir)
999    return batch.run_process()
1000
1001
1002def compute_affine_from_local_rational(cropped_cam, min_x, min_y, min_z, max_x, max_y, max_z, n_points=100):
1003    batch.init_process("vpglComputeAffineFromRationalProcess")
1004    batch.set_input_from_db(0, cropped_cam)
1005    batch.set_input_double(1, min_x)
1006    batch.set_input_double(2, min_y)
1007    batch.set_input_double(3, min_z)
1008    batch.set_input_double(4, max_x)
1009    batch.set_input_double(5, max_y)
1010    batch.set_input_double(6, max_z)
1011    batch.set_input_unsigned(7, n_points)
1012    status = batch.run_process()
1013    if status:
1014        (id, type) = batch.commit_output(0)
1015        out_cam = dbvalue(id, type)
1016        return out_cam
1017    else:
1018        raise VpglException("Failed to compute affine from rational camera")
1019
1020# use the affine cameras of the images to compute an affine fundamental matrix and rectify them (flatten epipolar lines to scan lines and align them)
1021# use the 3-d box that the cameras see to compute correspondences for
1022# minimally distortive alignment
1023def affine_rectify_images(img1, affine_cam1, img2, affine_cam2, min_x, min_y, min_z, max_x, max_y, max_z, local_ground_plane_height=5, n_points=100):
1024    batch.init_process("vpglAffineRectifyImagesProcess")
1025    batch.set_input_from_db(0, img1)
1026    batch.set_input_from_db(1, affine_cam1)
1027    batch.set_input_from_db(2, img2)
1028    batch.set_input_from_db(3, affine_cam2)
1029    batch.set_input_double(4, min_x)
1030    batch.set_input_double(5, min_y)
1031    batch.set_input_double(6, min_z)
1032    batch.set_input_double(7, max_x)
1033    batch.set_input_double(8, max_y)
1034    batch.set_input_double(9, max_z)
1035    batch.set_input_unsigned(10, n_points)
1036    batch.set_input_double(11, local_ground_plane_height)
1037    batch.run_process()
1038    (id, type) = batch.commit_output(0)
1039    out_img1 = dbvalue(id, type)
1040    (id, type) = batch.commit_output(1)
1041    out_cam1 = dbvalue(id, type)
1042    (id, type) = batch.commit_output(2)
1043    out_img2 = dbvalue(id, type)
1044    (id, type) = batch.commit_output(3)
1045    out_cam2 = dbvalue(id, type)
1046    return out_img1, out_cam1, out_img2, out_cam2
1047
1048# use the affine cameras of the images to compute an affine fundamental matrix and rectify them (flatten epipolar lines to scan lines and align them)
1049# use the 3-d box that the cameras see to compute correspondences for
1050# minimally distortive alignment, use the local rational cameras to find
1051# the correspondence points
1052def affine_rectify_images2(img1, affine_cam1, local_rational_cam1, img2, affine_cam2, local_rational_cam2, min_x, min_y, min_z, max_x, max_y, max_z, output_path_H1, output_path_H2, local_ground_plane_height=5, n_points=100):
1053    batch.init_process("vpglAffineRectifyImagesProcess2")
1054    batch.set_input_from_db(0, img1)
1055    batch.set_input_from_db(1, affine_cam1)
1056    batch.set_input_from_db(2, local_rational_cam1)
1057    batch.set_input_from_db(3, img2)
1058    batch.set_input_from_db(4, affine_cam2)
1059    batch.set_input_from_db(5, local_rational_cam2)
1060    batch.set_input_double(6, min_x)
1061    batch.set_input_double(7, min_y)
1062    batch.set_input_double(8, min_z)
1063    batch.set_input_double(9, max_x)
1064    batch.set_input_double(10, max_y)
1065    batch.set_input_double(11, max_z)
1066    batch.set_input_unsigned(12, n_points)
1067    batch.set_input_double(13, local_ground_plane_height)
1068    batch.set_input_string(14, output_path_H1)
1069    batch.set_input_string(15, output_path_H2)
1070    status = batch.run_process()
1071    if status:
1072        (id, type) = batch.commit_output(0)
1073        out_img1 = dbvalue(id, type)
1074        (id, type) = batch.commit_output(1)
1075        out_cam1 = dbvalue(id, type)
1076        (id, type) = batch.commit_output(2)
1077        out_img2 = dbvalue(id, type)
1078        (id, type) = batch.commit_output(3)
1079        out_cam2 = dbvalue(id, type)
1080        return out_img1, out_cam1, out_img2, out_cam2
1081    else:
1082        raise VpglException("Image rectification from affine cameras failed")
1083
1084
1085# use the affine cameras of the images to compute an affine fundamental
1086# matrix and write the f matrix out
1087def affine_f_matrix(affine_cam1, affine_cam2, output_path):
1088    batch.init_process("vpglAffineFMatrixProcess")
1089    batch.set_input_from_db(0, affine_cam1)
1090    batch.set_input_from_db(1, affine_cam2)
1091    batch.set_input_string(2, output_path)
1092    batch.run_process()
1093
1094
1095def construct_height_map_from_disparity(img1, img1_disp, min_disparity, local_rational_cam1, img2, local_rational_cam2,
1096                                        min_x, min_y, min_z, max_x, max_y, max_z, path_H1, path_H2, voxel_size,
1097                                        z_offset = 0.0):
1098    batch.init_process("vpglConstructHeightMapProcess")
1099    batch.set_input_from_db(0, img1)
1100    batch.set_input_from_db(1, local_rational_cam1)
1101    batch.set_input_from_db(2, img1_disp)
1102    batch.set_input_float(3, min_disparity)
1103    batch.set_input_from_db(4, img2)
1104    batch.set_input_from_db(5, local_rational_cam2)
1105    batch.set_input_double(6, min_x)
1106    batch.set_input_double(7, min_y)
1107    batch.set_input_double(8, min_z)
1108    batch.set_input_double(9, max_x)
1109    batch.set_input_double(10, max_y)
1110    batch.set_input_double(11, max_z)
1111    batch.set_input_double(12, voxel_size)
1112    batch.set_input_string(13, path_H1)
1113    batch.set_input_string(14, path_H2)
1114    batch.set_input_double(15, z_offset)
1115    status = batch.run_process()
1116    if status:
1117        (id, type) = batch.commit_output(0)
1118        out_map = dbvalue(id, type)
1119        (id, type) = batch.commit_output(1)
1120        disparity_map = dbvalue(id, type)
1121        return out_map, disparity_map
1122    else:
1123        raise VpglException("DSM from Disparity failed")
1124
1125
1126
1127def compute_camera_to_world_homography(cam, plane, inverse=False):
1128    batch.init_process("vpglComputeImageToWorldHomographyProcess")
1129    batch.set_input_from_db(0, cam)
1130    batch.set_input_float_array(1, plane)
1131    batch.set_input_bool(2, inverse)
1132    batch.run_process()
1133    (id, type) = batch.commit_output(0)
1134    homg2d = batch.get_bbas_1d_array_float(id)
1135    batch.remove_data(id)
1136    return homg2d
1137
1138# use the 3-d box to crop an image using image camera, given certain uncertainty value in meter unit
1139# note that the input 3-d box is in unit of wgs84 geo coordinates
1140def crop_image_using_3d_box(img_res_ni, img_res_nj, camera, lower_left_lon, lower_left_lat, lower_left_elev, upper_right_lon, upper_right_lat, upper_right_elev, uncertainty, lvcs=0):
1141    batch.init_process("vpglCropImgUsing3DboxProcess")
1142    batch.set_input_unsigned(0, img_res_ni)
1143    batch.set_input_unsigned(1, img_res_nj)
1144    batch.set_input_from_db(2, camera)
1145    batch.set_input_double(3, lower_left_lon)
1146    batch.set_input_double(4, lower_left_lat)
1147    batch.set_input_double(5, lower_left_elev)
1148    batch.set_input_double(6, upper_right_lon)
1149    batch.set_input_double(7, upper_right_lat)
1150    batch.set_input_double(8, upper_right_elev)
1151    batch.set_input_double(9, uncertainty)
1152    if lvcs:
1153        batch.set_input_from_db(10, lvcs)
1154    status = batch.run_process()
1155    if status:
1156        (id, type) = batch.commit_output(0)
1157        local_cam = dbvalue(id, type)
1158        (id, type) = batch.commit_output(1)
1159        i0 = batch.get_output_unsigned(id)
1160        batch.remove_data(id)
1161        (id, type) = batch.commit_output(2)
1162        j0 = batch.get_output_unsigned(id)
1163        batch.remove_data(id)
1164        (id, type) = batch.commit_output(3)
1165        ni = batch.get_output_unsigned(id)
1166        batch.remove_data(id)
1167        (id, type) = batch.commit_output(4)
1168        nj = batch.get_output_unsigned(id)
1169        batch.remove_data(id)
1170        return status, local_cam, i0, j0, ni, nj
1171    else:
1172        raise VpglException("Failed to crop image using 3D box")
1173
1174
1175# use the 3-d box to crop an image using image camera, given certain uncertainty value in meter unit
1176# note that the elevation of 3-d box is obtained from DEM height map
1177def crop_image_using_3d_box_dem(img_res, camera, ll_lon, ll_lat, ur_lon, ur_lat, dem_folder, extra_height, uncertainty, lvcs=0):
1178    batch.init_process("vpglCropImgUsing3DboxDemProcess")
1179    batch.set_input_from_db(0, img_res)
1180    batch.set_input_from_db(1, camera)
1181    batch.set_input_double(2, ll_lon)
1182    batch.set_input_double(3, ll_lat)
1183    batch.set_input_double(4, ur_lon)
1184    batch.set_input_double(5, ur_lat)
1185    batch.set_input_string(6, dem_folder)
1186    batch.set_input_double(7, extra_height)
1187    batch.set_input_double(8, uncertainty)
1188    if lvcs != 0:
1189        batch.set_input_from_db(9, lvcs)
1190    status = batch.run_process()
1191    if status:
1192        (id, type) = batch.commit_output(0)
1193        local_cam = dbvalue(id, type)
1194        (id, type) = batch.commit_output(1)
1195        i0 = batch.get_output_unsigned(id)
1196        (id, type) = batch.commit_output(2)
1197        j0 = batch.get_output_unsigned(id)
1198        (id, type) = batch.commit_output(3)
1199        ni = batch.get_output_unsigned(id)
1200        (id, type) = batch.commit_output(4)
1201        nj = batch.get_output_unsigned(id)
1202        return status, local_cam, i0, j0, ni, nj
1203    else:
1204        raise VpglException("Failed to crop image using 3D box DEM")
1205
1206# use the 3-d box to crop an ortho image using its geo camera
1207# note that the input 3-d box is in unit of wgs84 geo coordinates
1208def crop_ortho_image_using_3d_box(img_res, camera, lower_left_lon, lower_left_lat, lower_left_elev, upper_right_lon, upper_right_lat, upper_right_elev):
1209    batch.init_process("vpglCropOrthoUsing3DboxPRocess")
1210    batch.set_input_from_db(0, img_res)
1211    batch.set_input_from_db(1, camera)
1212    batch.set_input_double(2, lower_left_lon)
1213    batch.set_input_double(3, lower_left_lat)
1214    batch.set_input_double(4, lower_left_elev)
1215    batch.set_input_double(5, upper_right_lon)
1216    batch.set_input_double(6, upper_right_lat)
1217    batch.set_input_double(7, upper_right_elev)
1218    status = batch.run_process()
1219    if status:
1220        (id, type) = batch.commit_output(0)
1221        local_geo_cam = dbvalue(id, type)
1222        (id, type) = batch.commit_output(1)
1223        i0 = batch.get_output_unsigned(id)
1224        (id, type) = batch.commit_output(2)
1225        j0 = batch.get_output_unsigned(id)
1226        (id, type) = batch.commit_output(3)
1227        ni = batch.get_output_unsigned(id)
1228        (id, type) = batch.commit_output(4)
1229        nj = batch.get_output_unsigned(id)
1230        return status, local_geo_cam, i0, j0, ni, nj
1231    else:
1232        raise VpglException("Failed to crop ortho image using 3D box")
1233
1234
1235# use the 3-d box to offset the local camera using image camera, given certain uncertainty value in meter unit
1236# note that the input 3-d box is in unit of wgs84 geo coordinates
1237def offset_cam_using_3d_box(camera, lower_left_lon, lower_left_lat, lower_left_elev, upper_right_lon, upper_right_lat, upper_right_elev, uncertainty, lvcs=None):
1238    batch.init_process("vpglOffsetCamUsing3DboxProcess")
1239    batch.set_input_from_db(0, camera)
1240    batch.set_input_double(1, lower_left_lon)
1241    batch.set_input_double(2, lower_left_lat)
1242    batch.set_input_double(3, lower_left_elev)
1243    batch.set_input_double(4, upper_right_lon)
1244    batch.set_input_double(5, upper_right_lat)
1245    batch.set_input_double(6, upper_right_elev)
1246    batch.set_input_double(7, uncertainty)
1247    if lvcs:
1248        batch.set_input_from_db(8, lvcs)
1249    status = batch.run_process()
1250    if status:
1251        (id, type) = batch.commit_output(0)
1252        local_cam = dbvalue(id, type)
1253        (id, type) = batch.commit_output(1)
1254        i0 = batch.get_output_unsigned(id)
1255        batch.remove_data(id)
1256        (id, type) = batch.commit_output(2)
1257        j0 = batch.get_output_unsigned(id)
1258        batch.remove_data(id)
1259        (id, type) = batch.commit_output(3)
1260        ni = batch.get_output_unsigned(id)
1261        batch.remove_data(id)
1262        (id, type) = batch.commit_output(4)
1263        nj = batch.get_output_unsigned(id)
1264        batch.remove_data(id)
1265        return status, local_cam, i0, j0, ni, nj
1266    else:
1267        raise VpglException("Failed to offset camera using 3D box")
1268
1269
1270# covert (lat, lon) to UTM coordinates
1271def utm_coords(lon, lat):
1272    batch.init_process("vpglComputeUTMZoneProcess")
1273    batch.set_input_double(0, lon)
1274    batch.set_input_double(1, lat)
1275    result = batch.run_process()
1276    if result:
1277        (id, type) = batch.commit_output(0)
1278        x = batch.get_output_double(id)
1279        (id, type) = batch.commit_output(1)
1280        y = batch.get_output_double(id)
1281        (id, type) = batch.commit_output(2)
1282        utm_zone = batch.get_output_int(id)
1283        (id, type) = batch.commit_output(3)
1284        northing = batch.get_output_int(id)
1285        return x, y, utm_zone, northing
1286    else:
1287        return 0.0, 0.0, 0, 0
1288
1289
1290# get the world point (wgs84) given the image point and rational camera
1291# Pass default initial guess point (-1.0, -1.0, -1.0) and plane height
1292# (-1.0) if initial is unknown at all
1293def rational_cam_img_to_global(camera, i, j, init_lon=-1.0, init_lat=-1.0, init_elev=-1.0, pl_elev=-1.0, error_tol=0.05):
1294    batch.init_process("vpglRationalImgToGlobalProcess")
1295    batch.set_input_from_db(0, camera)
1296    batch.set_input_unsigned(1, i)
1297    batch.set_input_unsigned(2, j)
1298    batch.set_input_double(3, init_lon)
1299    batch.set_input_double(4, init_lat)
1300    batch.set_input_double(5, init_elev)
1301    batch.set_input_double(6, pl_elev)
1302    batch.set_input_double(7, error_tol)
1303    status = batch.run_process()
1304    if status:
1305        (id, type) = batch.commit_output(0)
1306        lon = batch.get_output_double(id)
1307        (id, type) = batch.commit_output(1)
1308        lat = batch.get_output_double(id)
1309        (id, type) = batch.commit_output(2)
1310        elev = batch.get_output_double(id)
1311        return lon, lat, elev
1312    else:
1313        raise VpglException("Failed to convert rational camera image to global")
1314
1315
1316def rational_cam_nadirness(camera, lat, lon, elev):
1317    batch.init_process("vpglRationalCamNadirnessProcess")
1318    batch.set_input_from_db(0, camera)
1319    batch.set_input_double(1, lat)
1320    batch.set_input_double(2, lon)
1321    batch.set_input_double(3, elev)
1322    batch.run_process()
1323    (id, type) = batch.commit_output(0)
1324    val = batch.get_output_double(id)
1325    return val
1326
1327
1328# calculate GSD from a rational camera
1329def calculate_nitf_gsd(rational_cam, lon1, lat1, elev1, distance=1000):
1330    # create a lvcs
1331    lvcs = create_lvcs(lat1, lon1, elev1, "wgs84")
1332    lat2, lon2, elev2 = convert_local_to_global_coordinates(
1333        lvcs, distance, distance, 0.0)
1334    # calculate image pixel
1335    i1, j1 = project_point(rational_cam, lon1, lat1, elev1)
1336    i2, j2 = project_point(rational_cam, lon2, lat2, elev2)
1337    gsd_i = distance / (i2 - i1)
1338    gsd_j = distance / (j2 - j1)
1339    if (gsd_i < 0.0):
1340        gsd_i = -1 * gsd_i
1341    if (gsd_j < 0.0):
1342        gsd_j = -1 * gsd_j
1343    batch.remove_data(lvcs.id)
1344    return gsd_i, gsd_j
1345
1346
1347# geo-register series of rational cameras using their correspondence features
1348def isfm_rational_camera(trackfile, output_folder, pixel_radius):
1349    batch.init_process("vpglIsfmRationalCameraProcess")
1350    batch.set_input_string(0, trackfile)
1351    batch.set_input_string(1, output_folder)
1352    # pixel radius to count for inliers
1353    batch.set_input_float(2, pixel_radius)
1354    if not batch.run_process():
1355        return None, -1.0, -1.0
1356    (id, type) = batch.commit_output(0)
1357    cam = dbvalue(id, type)
1358    (id, type) = batch.commit_output(1)
1359    error = batch.get_output_float(id)
1360    (id, type) = batch.commit_output(2)
1361    inliers = batch.get_output_float(id)
1362    return cam, error, inliers
1363
1364
1365# geo-register a rational camera to group of geo-registered cameras
1366def isfm_rational_camera_seed(track_file, out_folder,
1367                              ll_lon, ll_lat, ll_elev,
1368                              ur_lon, ur_lat, ur_elev,
1369                              pixel_radius=2.0, enforce_existing=False,
1370                              verbose = False,
1371                              ):
1372    batch.init_process("vpglIsfmRationalCameraSeedProcess")
1373    batch.set_input_string(0, track_file)
1374    batch.set_input_string(1, out_folder)
1375    batch.set_input_double(2, ll_lon)
1376    batch.set_input_double(3, ll_lat)
1377    batch.set_input_double(4, ll_elev)
1378    batch.set_input_double(5, ur_lon)
1379    batch.set_input_double(6, ur_lat)
1380    batch.set_input_double(7, ur_elev)
1381    batch.set_input_double(8, pixel_radius)
1382    batch.set_input_bool(9, enforce_existing)
1383    batch.set_input_bool(10, verbose)
1384
1385    status = batch.run_process()
1386    return status
1387
1388
1389def isfm_rational_camera_with_init(track_file,
1390                                   ll_lon, ll_lat, ll_elev,
1391                                   ur_lon, ur_lat, ur_elev,
1392                                   pixel_radius=2.0,
1393                                   verbose = False,
1394                                   ):
1395    batch.init_process("vpglIsfmRationalCameraWithInitialProcess")
1396    batch.set_input_string(0, track_file)
1397    batch.set_input_double(1, ll_lon)
1398    batch.set_input_double(2, ll_lat)
1399    batch.set_input_double(3, ll_elev)
1400    batch.set_input_double(4, ur_lon)
1401    batch.set_input_double(5, ur_lat)
1402    batch.set_input_double(6, ur_elev)
1403    batch.set_input_double(7, pixel_radius)
1404    batch.set_input_bool(8, verbose)
1405
1406    if not batch.run_process():
1407        return None, -1.0, -1.0
1408    (id, type) = batch.commit_output(0)
1409    cam = dbvalue(id, type)
1410    (id, type) = batch.commit_output(1)
1411    error = batch.get_output_double(id)
1412    batch.remove_data(id)
1413    (id, type) = batch.commit_output(2)
1414    inliers = batch.get_output_double(id)
1415    batch.remove_data(id)
1416    return cam, error, inliers
1417
1418
1419# rotate a camera around principle axis
1420
1421
1422def perspective_camera_distance(cam1, cam2):
1423    batch.init_process('vpglPerspCamDistanceProcess')
1424    batch.set_input_from_db(0, cam1)
1425    batch.set_input_from_db(1, cam2)
1426    batch.run_process()
1427    (dist_id, type) = batch.commit_output(0)
1428    dist = batch.get_output_float(dist_id)
1429    return dist
1430
1431
1432def correct_cam_rotation(img, pcam, exp_img, cone_half_angle, n_steps, refine=True):
1433    batch.init_process('icamCorrectCamRotationProcess')
1434    batch.set_input_from_db(0, img)
1435    batch.set_input_from_db(1, pcam)
1436    batch.set_input_from_db(2, exp_img)
1437    batch.set_input_float(3, cone_half_angle)
1438    batch.set_input_unsigned(4, n_steps)
1439    batch.set_input_bool(5, refine)
1440    batch.run_process()
1441    (m_id, m_type) = batch.commit_output(0)
1442    mapped_img = dbvalue(m_id, m_type)
1443    (c_id, c_type) = batch.commit_output(1)
1444    corr_cam = dbvalue(c_id, c_type)
1445    return mapped_img, corr_cam
1446
1447
1448def compute_direction_covariance(pcam, std_dev_angle, out_file):
1449    batch.init_process("vpglComputePerspCamPACovarianceProcess")
1450    batch.set_input_from_db(0, pcam)
1451    batch.set_input_float(1, std_dev_angle)
1452    batch.set_input_string(2, out_file)
1453    batch.run_process()
1454
1455# uniformly sample a camera rotated around principle axis
1456
1457
1458def perturb_camera_uniform(cam_in, angle, rng):
1459    batch.init_process('vpglPerturbUniformPerspCamOrientProcess')
1460    batch.set_input_from_db(0, cam_in)
1461    batch.set_input_float(1, angle)
1462    batch.set_input_from_db(2, rng)
1463    batch.run_process()
1464    (id, type) = batch.commit_output(0)
1465    pert_cam = dbvalue(id, type)
1466    (theta_id, type) = batch.commit_output(1)
1467    (phi_id, type) = batch.commit_output(2)
1468    theta = batch.get_output_float(theta_id)
1469    phi = batch.get_output_float(phi_id)
1470    return pert_cam, theta, phi
1471
1472
1473def create_perspective_camera_with_motion_dir(pcam, cent_x, cent_y, cent_z, cent2_x, cent2_y, cent2_z):
1474    batch.init_process("vpglCreatePerspectiveCameraProcess4")
1475    batch.set_input_from_db(0, pcam)
1476    batch.set_input_float(1, cent_x)
1477    batch.set_input_float(2, cent_y)
1478    batch.set_input_float(3, cent_z)
1479    batch.set_input_float(4, cent2_x)
1480    batch.set_input_float(5, cent2_y)
1481    batch.set_input_float(6, cent2_z)
1482    batch.run_process()
1483    (c_id, c_type) = batch.commit_output(0)
1484    cam = dbvalue(c_id, c_type)
1485    return cam
1486
1487
1488def pers_cam_from_photo_overlay(lvcs, heading, tilt, roll, lat, lon, alt, fov_hor, fov_ver, ni, nj):
1489    batch.init_process("vpglPerspCameraFromPhotoOverlayProcess")
1490    batch.set_input_from_db(0, lvcs)
1491    batch.set_input_float(1, heading)
1492    batch.set_input_float(2, tilt)
1493    batch.set_input_float(3, roll)
1494    batch.set_input_float(4, lat)
1495    batch.set_input_float(5, lon)
1496    batch.set_input_float(6, alt)
1497    batch.set_input_float(7, fov_hor)
1498    batch.set_input_float(8, fov_ver)
1499    batch.set_input_unsigned(9, ni)
1500    batch.set_input_unsigned(10, nj)
1501    batch.run_process()
1502    (c_id, c_type) = batch.commit_output(0)
1503    cam = dbvalue(c_id, c_type)
1504    return cam
1505
1506
1507def create_perspective_camera_krt(k, r, t):
1508    ''' Take a k(3x3), r(3x3), and t(3) numpy array and returns a database object
1509
1510      k, r, t can also be a flattened list
1511    '''
1512    if type(k) != list:
1513        k = k.flatten().tolist()
1514    if type(r) != list:
1515        r = r.flatten().tolist()
1516    if type(t) != list:
1517        t = t.flatten().tolist()
1518
1519    batch.init_process("vpglCreatePerspectiveCameraProcess5")
1520    batch.set_input_double_array(0, k)
1521    batch.set_input_double_array(1, r)
1522    batch.set_input_double_array(2, t)
1523    batch.run_process()
1524    (db_id, db_type) = batch.commit_output(0)
1525    cam = dbvalue(db_id, db_type)
1526    return cam
1527
1528
1529# input two sets of points that correspond to each other in two different coordinate systems
1530# compute the similarity transformation that maps space of pts0 to space of pts1, the size of pts0 and pts1 better match!
1531# outputs a 4 by 4 similarity matrix as a vector of size 16
1532# construct the matrix as follows
1533# 0  1  2  3
1534# 4  5  6  7
1535# 8  9  10 11
1536# 12 13 14 15
1537def compute_transformation(pts0_xs, pts0_ys, pts0_zs,
1538                           pts1_xs, pts1_ys, pts1_zs,
1539                           input_cam_folder, output_cam_folder):
1540    batch.init_process("vpglTransformSpaceProcess")
1541    batch.set_input_double_array(0, pts0_xs)
1542    batch.set_input_double_array(1, pts0_ys)
1543    batch.set_input_double_array(2, pts0_zs)
1544    batch.set_input_double_array(3, pts1_xs)
1545    batch.set_input_double_array(4, pts1_ys)
1546    batch.set_input_double_array(5, pts1_zs)
1547    batch.set_input_string(6, input_cam_folder)
1548    batch.set_input_string(7, output_cam_folder)
1549    batch.run_process()
1550    (id, type) = batch.commit_output(0)
1551    matrix_as_array = batch.get_output_double_array(id)
1552    batch.remove_data(id)
1553    (id, type) = batch.commit_output(1)
1554    scale = batch.get_output_double(id)
1555    batch.remove_data(id)
1556    return matrix_as_array, scale
1557
1558# inputs a 4 by 4 similarity matrix as a vector of size 16
1559# construct the matrix as follows
1560# 0  1  2  3
1561# 4  5  6  7
1562# 8  9  10 11
1563# 12 13 14 15
1564def compute_transformed_box(min_pt, max_pt, matrix_as_array):
1565    batch.init_process("vpglTransformBoxProcess")
1566    batch.set_input_double_array(0, min_pt)
1567    batch.set_input_double_array(1, max_pt)
1568    batch.set_input_double_array(2, matrix_as_array)
1569    batch.run_process()
1570    (id, type) = batch.commit_output(0)
1571    out_min_pt = batch.get_output_double_array(id)
1572    batch.remove_data(id)
1573    (id, type) = batch.commit_output(1)
1574    out_max_pt = batch.get_output_double_array(id)
1575    batch.remove_data(id)
1576    return out_min_pt, out_max_pt
1577
1578# get connected component of a geotiff image
1579def find_connected_component(in_img, in_cam, threshold, out_kml, is_above=True):
1580    batch.init_process("vpglFindConnectedComponentProcess")
1581    batch.set_input_from_db(0, in_img)
1582    batch.set_input_from_db(1, in_cam)
1583    batch.set_input_float(2, threshold)
1584    batch.set_input_string(3, out_kml)
1585    batch.set_input_bool(4, is_above)
1586    status = batch.run_process()
1587    if status:
1588        (id, type) = batch.commit_output(0)
1589        out_img = dbvalue(id, type)
1590        (id, type) = batch.commit_output(1)
1591        num_regions = batch.get_output_unsigned(id)
1592        return out_img, num_regions
1593    else:
1594        raise VpglException("Failed to find connected components")
1595
1596# rotate a image north up based on its RPC camera.  The return value is
1597# rotation angle between -Pi to Pi
1598def rational_camera_rotate_to_north(in_cam):
1599    batch.init_process("vpglRationalCamRotationToNorthProcess")
1600    batch.set_input_from_db(0, in_cam)
1601    status = batch.run_process()
1602    if status:
1603        (id, type) = batch.commit_output(0)
1604        ang_in_deg = batch.get_output_double(id)
1605        return ang_in_deg
1606    else:
1607        raise VpglException("Failed to get north angle from rational camera")
1608
1609# rotate a image north up based on its RPC camera.  The return value is
1610# rotation angle between -Pi to Pi
1611def rational_camera_get_up_vector(in_cam):
1612    batch.init_process("vpglRationalCamRotationToUpVectorProcess")
1613    batch.set_input_from_db(0, in_cam)
1614    status = batch.run_process()
1615    if status:
1616        (id, type) = batch.commit_output(0)
1617        u = batch.get_output_double(id)
1618        (id, type) = batch.commit_output(1)
1619        v = batch.get_output_double(id)
1620        return u,v
1621    else:
1622        raise VpglException("Failed to get north angle from rational camera")
1623
1624# create a DEM manager to support DEM utility functions
1625# note if zmin > zmax, these values will be calculated from the DEM
1626def create_DEM_manager(dem_img_resc,zmin=0.0,zmax=-1.0):
1627    batch.init_process("vpglCreateDemManagerProcess")
1628    batch.set_input_from_db(0, dem_img_resc)
1629    batch.set_input_double(1, zmin)
1630    batch.set_input_double(2, zmax)
1631    status = batch.run_process()
1632    if status:
1633        (id0, type) = batch.commit_output(0)
1634        dem_mgr = dbvalue(id0, type)
1635        (id1, type) = batch.commit_output(1)
1636        zmin = batch.get_output_double(id1)
1637        (id2, type) = batch.commit_output(2)
1638        zmax = batch.get_output_double(id2)
1639        return (dem_mgr,zmin,zmax)
1640    raise VpglException("failed to create a DEM manager")
1641
1642# Backproject an image point onto the DEM and return a 3-d point
1643def DEM_backproj(dem_mgr, cam, u, v, err_tol = 1.0):
1644    batch.init_process("vpglBackprojectDemProcess")
1645    batch.set_input_from_db(0, dem_mgr)
1646    batch.set_input_from_db(1, cam)
1647    batch.set_input_double(2, u)
1648    batch.set_input_double(3, v)
1649    batch.set_input_double(4, err_tol)
1650    status = batch.run_process()
1651    if status:
1652        (id0, type) = batch.commit_output(0)
1653        x = batch.get_output_double(id0)
1654        (id1, type) = batch.commit_output(1)
1655        y = batch.get_output_double(id1)
1656        (id2, type) = batch.commit_output(2)
1657        z = batch.get_output_double(id2)
1658        batch.remove_data(id0)
1659        batch.remove_data(id1)
1660        batch.remove_data(id2)
1661        return (x, y, z)
1662    raise VpglException("failed to backproject onto the DEM")
1663
1664# convert a geotiff image to a ASCII xyz point cloud file via a LVCS conversion
1665def dem_to_pts_lvcs(img, cam, lvcs, out_file, is_convert_z = True):
1666    batch.init_process("vpglConvertGeotiffToPointCloudProcess")
1667    batch.set_input_from_db(0, img)
1668    batch.set_input_from_db(1, cam)
1669    batch.set_input_from_db(2, lvcs)
1670    batch.set_input_string(3, out_file)
1671    batch.set_input_bool(4, is_convert_z)
1672    status = batch.run_process()
1673    if status:
1674        (id, type) = batch.commit_output(0)
1675        n_pts = batch.get_output_unsigned(id)
1676        return n_pts
1677    raise VpglException("failed to convert geotiff to point clouds")
1678
1679# Project a reference image that controled by a rational camera onto target image domain using DEM
1680def DEM_project_img(dem_mgr, ref_img, ref_cam, tgr_cam, tgr_i0, tgr_j0, tgr_ni, tgr_nj, err_tol = 1.0):
1681    batch.init_process("vpglDemImageProjectionProcess")
1682    batch.set_input_from_db(0, ref_img)
1683    batch.set_input_from_db(1, ref_cam)
1684    batch.set_input_from_db(2, dem_mgr)
1685    batch.set_input_from_db(3, tgr_cam)
1686    batch.set_input_unsigned(4, tgr_i0)
1687    batch.set_input_unsigned(5, tgr_j0)
1688    batch.set_input_unsigned(6, tgr_ni)
1689    batch.set_input_unsigned(7, tgr_nj)
1690    batch.set_input_double(8, err_tol)
1691    status = batch.run_process()
1692    if status:
1693        (id0, type0) = batch.commit_output(0)
1694        out_img = dbvalue(id0, type0)
1695        (id1, type1) = batch.commit_output(1)
1696        err_cnt = batch.get_output_unsigned(id1)
1697        return out_img, err_cnt
1698    raise VpglException("failed to project reference image to target image using DEM manager")
1699