def main(args=None): # handle inputs # parser = argparse.ArgumentParser() parser.add_argument("-s", "--scene", metavar='FILE', default="./model/scene.xml", help="XML scene file defining the model") parser.add_argument( 'output_file', nargs='?', default=None, help="Filename to write scene.kml to. Default is scene.kml in same dir" ) options = parser.parse_args(args) scene_xml, scene_kml = options.scene, options.output_file scene = boxm2_scene_adaptor(scene_xml, "cpp") description = adaptor.describe_scene(scene.scene) for key, value in description.iteritems(): print(" key = {}, value = {}".format(key, value)) if scene_kml is None: scene_kml = os.path.join(description["dataPath"], "scene.kml") adaptor.write_scene_to_kml(scene.scene, scene_kml) scene.clear_cache()
def updateScene(self, stepNum): # Should initialize a GPU scenePath = os.path.abspath(self.config.uSceneFileName) scene = boxm2_scene_adaptor.boxm2_scene_adaptor(scenePath, "gpu0") # Get list of imgs and cams imgsDir = os.path.abspath( os.path.join(self.config.NVMOutputDirName, "imgs")) camsDir = os.path.abspath( os.path.join(self.config.NVMOutputDirName, "cams")) if False == os.path.isdir(imgsDir): log("The folder %s does not exist." % (imgsDir)) return -stepNum if False == os.path.isdir(camsDir): log("The folder %s does not exist." % (camsDir)) return -stepNum imgFiles = getAllFilesInSubDirs(imgsDir) camFiles = getAllFilesInSubDirs(camsDir) if len(imgFiles) != len(camFiles): log("The number of files in %s is %d." % (imgsDir, len(imgFiles))) log("The number of fiels in %s is %d." % (camsDir, len(camFiles))) log("These numbers should match and they do not.") return -stepNum if len(imgFiles) == 0: log("No image files were found in %s." % (imgsDir)) return -stepNum imgFiles.sort() camFiles.sort() # Make two passes over the image set for p in xrange(0, self.config.updateScenePassCount): frames = range(0, len(imgFiles), 1) if self.config.randomizeUpdateOrder: random.shuffle(frames) for idx, i in enumerate(frames): pcam = vpgl.load_perspective_camera( os.path.join(camsDir, camFiles[i])) img, ni, nj = vil.load_image(os.path.join( imgsDir, imgFiles[i])) scene.update(pcam, img, 1, "", "gpu0") if 0 == ( idx % 15 ): # No idea what is special about the magic number 15 scene.refine() scene.write_cache() return 0
def fetch_voxel_world_bounding_box(request, voxel_world_id): import boxm2_scene_adaptor import json import os voxel_world = voxel_globe.meta.models.VoxelWorld.objects.get(id=voxel_world_id) scene = boxm2_scene_adaptor.boxm2_scene_adaptor(os.path.join(voxel_world.directory, 'scene.xml'), 'cpp') return HttpResponse(json.dumps(scene.bbox))
def filter_number_observations(self, voxel_world_id, mean_multiplier=3.0, history=None): from boxm2_scene_adaptor import boxm2_scene_adaptor import voxel_globe.meta.models as models voxel_world = models.VoxelWorld.objects.get(id=voxel_world_id) scene_file = os.path.join(voxel_world.directory, 'scene.xml') scene = boxm2_scene_adaptor(scene_file, env['VIP_OPENCL_DEVICE']) self.update_state(state='PROCESSING', meta={'stage':'remove low observers'}) scene.remove_low_nobs(mean_multiplier) self.update_state(state='SAVING') scene.write_cache()
def filter_number_observations(self, voxel_world_id, mean_multiplier=3.0, history=None): from boxm2_scene_adaptor import boxm2_scene_adaptor import voxel_globe.meta.models as models voxel_world = models.VoxelWorld.objects.get(id=voxel_world_id) scene_file = os.path.join(voxel_world.directory, 'scene.xml') scene = boxm2_scene_adaptor(scene_file, env['VIP_OPENCL_DEVICE']) self.update_state(state='PROCESSING', meta={'stage': 'remove low observers'}) scene.remove_low_nobs(mean_multiplier) self.update_state(state='SAVING') scene.write_cache()
def main(): import matplotlib args = parse_args() plot_scene = PlotScene() if args.limits: xyz = [float(i) for i in args.limits] plot_scene.set_limits(xyz[0], xyz[1],\ xyz[2], xyz[3],\ xyz[4], xyz[5]) z_min = None if args.scene: scene = boxm2_scene_adaptor(args.scene, 'cpp') plot_scene.draw_scene_box(scene) z_min = scene.bbox[0][2] if (args.limits and not z_min): z_min = xyz[4] if args.cameras: cameras = [] camera_files = [ x for y in map(lambda x: glob(x), args.cameras) for x in y ] camera_files = natural_sorted(camera_files) for camera_file in camera_files: krt = Krt.load(camera_file) cameras.append(krt) plot_scene.draw_cameras(cameras, z_min) if args.cameras and args.diff: cameras = [] camera_files = [ x for y in map(lambda x: glob(x), args.diff) for x in y ] camera_files = natural_sorted(camera_files) for camera_file in camera_files: krt = Krt.load(camera_file) cameras.append(krt) plot_scene.draw_cameras(cameras, z_min, 'g') plt.show()
def filter_number_observations(self, voxel_world_id, mean_multiplier=3.0): from boxm2_scene_adaptor import boxm2_scene_adaptor import voxel_globe.meta.models as models import voxel_globe.tools from vsi.tools.dir_util import copytree voxel_world = models.VoxelWorld.objects.get(id=voxel_world_id) with voxel_globe.tools.storage_dir('voxel_world') as storage_dir: copytree(voxel_world.directory, storage_dir) voxel_world.id = None voxel_world.directory = storage_dir voxel_world.name = 'Filtered at %d %s' % (mean_multiplier, voxel_world.name) voxel_world.service_id = self.request.id voxel_world.save() scene_file = os.path.join(storage_dir, 'scene.xml') scene = boxm2_scene_adaptor(scene_file, env['VIP_OPENCL_DEVICE']) self.update_state(state='PROCESSING', meta={'stage':'remove low observers'}) scene.remove_low_nobs(mean_multiplier) self.update_state(state='SAVING') scene.write_cache()
def filter_number_observations(self, voxel_world_id, mean_multiplier=3.0): from boxm2_scene_adaptor import boxm2_scene_adaptor import voxel_globe.meta.models as models import voxel_globe.tools from vsi.tools.dir_util import copytree voxel_world = models.VoxelWorld.objects.get(id=voxel_world_id) with voxel_globe.tools.storage_dir('voxel_world') as storage_dir: copytree(voxel_world.directory, storage_dir) voxel_world.id = None voxel_world.directory = storage_dir voxel_world.name = 'Filtered at %d %s' % (mean_multiplier, voxel_world.name) voxel_world.service_id = self.request.id voxel_world.save() scene_file = os.path.join(storage_dir, 'scene.xml') scene = boxm2_scene_adaptor(scene_file, env['VIP_OPENCL_DEVICE']) self.update_state(state='PROCESSING', meta={'stage': 'remove low observers'}) scene.remove_low_nobs(mean_multiplier) self.update_state(state='SAVING') scene.write_cache()
def create_height_map(self, voxel_world_id, render_height): import shutil import urllib import numpy as np import brl_init from boxm2_scene_adaptor import boxm2_scene_adaptor from boxm2_adaptor import ortho_geo_cam_from_scene, scene_lvcs, scene_bbox from vpgl_adaptor_boxm2_batch import convert_local_to_global_coordinates, geo2generic, save_geocam_to_tfw from vil_adaptor_boxm2_batch import save_image, scale_and_offset_values, stretch_image, image_range import vsi.io.image import voxel_globe.tools import voxel_globe.tools.hash import voxel_globe.tools.camera import voxel_globe.meta.models as models import voxel_globe.ingest.payload.tools with voxel_globe.tools.task_dir('height_map', cd=True) as processing_dir: voxel_world = models.VoxelWorld.objects.get(id=voxel_world_id) scene = boxm2_scene_adaptor(os.path.join(voxel_world.directory, 'scene.xml'), env['VIP_OPENCL_DEVICE']) ortho_camera, cols, rows = ortho_geo_cam_from_scene(scene.scene) tfw_camera = os.path.join(processing_dir, 'cam.tfw') save_geocam_to_tfw(ortho_camera, tfw_camera) with open(tfw_camera, 'r') as fid: geo_transform = [float(x) for x in fid.readlines()] (x0,y0,z0),(x1,y1,z1) = scene_bbox(scene.scene) lvcs = scene_lvcs(scene.scene) #lvcs = vpgl_adaptor.create_lvcs(lat=origin[1], lon=origin[0], el=origin[2], # csname="wgs84") _,_,min_height = convert_local_to_global_coordinates(lvcs, x0, y0, z0) if render_height is None: render_height = z1+(z1-z0)/1000 #z1+(z1-z0)/1000 is basically to say "just a little above the top" *2 is #1) overkill and 2) doesn't work with sign, +1 could go crazy in an #arbitrarily scaled system, so this just calculates ".1% more" which is #more than good enough else: render_height = render_height - voxel_world.origin[2] logger.critical("Render Height is %f (%s)", render_height, type(render_height)) generic_camera = geo2generic(ortho_camera, cols, rows, render_height, 0) z_exp_img, z_var_img = scene.render_z_image(generic_camera, cols, rows) #This is TECHNICALLY wrong, it assumes the earth is flat. scale_and_offset_values(z_exp_img, 1, min_height) height_filename = os.path.join(processing_dir, 'height.tif') save_image(z_exp_img, height_filename) checksum = voxel_globe.tools.hash.sha256_file(height_filename) with voxel_globe.tools.image_sha_dir(checksum) as image_dir: original_filename = os.path.join(image_dir, 'height_map.tif') #If the exact file exist already, don't ingest it again. Unlikely if not os.path.exists(original_filename): img = vsi.io.image.imread(height_filename) vsi.io.image.imwrite_geotiff(img.raster(), original_filename, [geo_transform[x] for x in [4,0,1,5,2,3]]) zoomify_filename = os.path.join(image_dir, 'zoomify.tif') img_min, img_max = image_range(z_exp_img) if img_min == img_max: zoomify_image = z_exp_img #At least it won't crash else: zoomify_image = stretch_image(z_exp_img, img_min, img_max, 'byte') save_image(zoomify_image, zoomify_filename) zoomify_name = os.path.join(image_dir, 'zoomify') voxel_globe.ingest.payload.tools.zoomify_image(zoomify_filename, zoomify_name) img = voxel_globe.meta.models.Image( name="Height Map %s (%s)" % (voxel_world.name, voxel_world.id), image_width=cols, image_height=rows, number_bands=1, pixel_format='f', file_format='zoom', service_id=self.request.id) img.filename_path=original_filename img.save() image_set = models.ImageSet.objects.get_or_create(name="Height Maps", defaults={"_attributes":'{"autogen":true}'})[0] image_set.images.add(img) gsd = scene.description['voxelLength'] camera_center = ((x0+x1)/2, (y0+y1)/2, z1+10000) d = z1-z0+10000 k=np.eye(3) k[0,2] = cols/2 k[1,2] = rows/2 k[0,0] = k[1,1] = d/gsd r=np.eye(3) r[0,0]=-1 t = -r.T.dot(camera_center) camera=voxel_globe.tools.camera.save_krt(self.request.id, img, k, r, t, voxel_world.origin) camera_set=voxel_globe.meta.models.CameraSet(\ name="Height Map %s (%s)" % (voxel_world.name, voxel_world.id), \ images=image_set, service_id=self.request.id) camera_set.save() camera_set.cameras.add(camera)
def run_build_voxel_model_bp(self, image_set_id, camera_set_id, scene_id, bbox, skip_frames, cleanup=True): import random import glob import math import numpy as np from vsi.tools.redirect import StdRedirect from voxel_globe.meta import models from voxel_globe.tools.camera import get_krt import voxel_globe.tools from boxm2_scene_adaptor import boxm2_scene_adaptor import brl_init from vil_adaptor_boxm2_batch import load_image import vpgl_adaptor_boxm2_batch as vpgl from vsi.vxl.create_scene_xml import create_scene_xml from vsi.tools.dir_util import copytree from vsi.tools.file_util import lncp def rectint(recta,rectb): lx = max(recta[0],rectb[0]) rx = min(recta[2],rectb[2]) by = max(recta[1],rectb[1]) ty = min(recta[3],rectb[3]) if lx > rx or by > ty : return [0,0,0,0],0 else: return [lx,by,rx,ty], (rx-lx)*(ty-by) def generate_subsetim(scene,camfiles,ni,nj): subsetIdx = [] refIndices = [] minDepOverlap = 0.25 minRefOverlap = 0.5 minIndepAngle = 5.0 minRefAngle = 5.0 maxRefAngle = 15.0 minRefIndepAngle = 5.0 cosMinIndepAngle = math.cos( minIndepAngle*math.pi/180.0 ); cosMinRefAngle = math.cos( minRefAngle*math.pi/180.0 ); cosMaxRefAngle = math.cos( maxRefAngle*math.pi/180.0 ); cosMinRefIndepAngle = math.cos( minRefIndepAngle*math.pi/180.0 ); bbox = scene.bbox grect=[scene.bbox[0][0],scene.bbox[0][1],scene.bbox[1][0],scene.bbox[1][1]] worldoverlaps = [] camrects = [] cams = [] princAxis = [] for camfile in camfiles: pcam = vpgl.load_perspective_camera(camfile) prx,pry,prz=vpgl.get_backprojected_ray(pcam,ni/2,nj/2) princAxis.append([prx,pry,prz]) Hmat = vpgl.compute_camera_to_world_homography(pcam,[0,0,1,-bbox[0][2]]) H = np.array(Hmat).reshape([3,3]) ps = np.dot(H,np.transpose([[0,0,1], [ni,0,1], [ni,nj,1], [0,nj,1]])) xs = ps[0,:]/ps[2,:] ys = ps[1,:]/ps[2,:] rect = [min(xs),min(ys),max(xs),max(ys)] area = (rect[2]-rect[0])*(rect[3]-rect[1]) crect,carea = rectint(rect,grect) #print crect,carea if ( carea > 0 ): cams.append(pcam) camrects.append(crect) worldoverlaps.append(carea/area) usedcams = [False]*len(cams) for i in range(0,len(cams)): randidx = random.randint(0,len(cams)-1) while usedcams[randidx]: randidx = (randidx+1)%len(cams) usedcams[randidx]= True dep = False for c2 in range(0,len(subsetIdx)): cosAngle = np.dot(princAxis[randidx], princAxis[subsetIdx[c2]] ) if cosAngle > cosMinIndepAngle : rectc2 = camrects[subsetIdx[c2]] overlap,oarea = rectint(camrects[randidx] , rectc2) tarea = (rectc2[2]-rectc2[0])*(rectc2[3]-rectc2[1]) if( oarea/tarea > minDepOverlap ): dep = True break if dep: continue theseRefIndices= [] for c3 in range(0,len(cams)): #Check angle disparity cosAngle2 = np.dot(princAxis[randidx],princAxis[c3] ); if( cosAngle2 > cosMinRefAngle or cosAngle2 < cosMaxRefAngle ): continue # Check that a similar viewpoint isn't already used for reference refDep = False for c4 in range(0,len(theseRefIndices)): #Check angle disparity cosAngle3 = np.dot(princAxis[theseRefIndices[c4]],princAxis[c3] ); if( cosAngle3 > cosMinRefIndepAngle ): refDep = True break #If similar viewpoint don't add if( refDep ): continue theseRefIndices.append(c3) #If at least one reference image save this viewpoint if len(theseRefIndices) > 0 : subsetIdx.append( randidx ); refIndices.append( theseRefIndices ); return subsetIdx, refIndices def update_bp(scene, images, cameras, do_update_image=True, do_update_hmap=False): _, ni, nj = load_image (images[0]) frames,refimages = generate_subsetim(scene,cameras,ni,nj) for file_name in glob.glob(os.path.join(scene.model_dir, 'boxm2_*.bin')): os.remove(file_name) scene.init_uniform_prob() sradius = 16 idents = [] weights = [] if do_update_image: idents.append("if") weights.append(1.0) if do_update_hmap: idents.append("hf") weights.append(2.0) for idx, i in enumerate(frames): if do_update_image: print "Iteration ",idx, "Image " , images[i]; ####load image and camera viewid = os.path.splitext(os.path.basename(images[i]))[0] #### forming an app model using the neighbor images for lindex in refimages[idx]: lcam = vpgl.load_perspective_camera(cameras[lindex]); limg, ni, nj = load_image (images[lindex]); scene.update(lcam, limg,False, True,None ,"gpu0",0.05,viewid) scene.update_if(False,viewid) # subtracting the image factor scene.fuse_factors(idents,weights) pcam = vpgl.load_perspective_camera(cameras[i]); img, ni, nj = load_image (images[i]); scene.compute_pre_post(pcam, img,viewid,100000,100000); # computing the new image factor scene.update_if(True,viewid) # adding the image factor scene.fuse_factors(idents,weights) if do_update_hmap and idx % 2 == 0: scene.update_hf(False) # subtracting the height-map factor scene.fuse_factors(idents,weights) zimg,zvar,ximg,yimg,probimg = scene.render_height_map() #save_image(zimg, "./zimg.tif") scene.compute_hmapf(zimg,zvar,ximg,yimg,sradius) # computing the height-map factor scene.update_hf(True) # adding the height-map factor scene.fuse_factors(idents,weights) scene.write_cache() def refine(scene): scene.refine(0.3) for filename in glob.glob(os.path.join(scene.model_dir, '[a-b]*.bin')): os.remove(filename) scene.write_cache() with StdRedirect(open(os.path.join(voxel_globe.tools.log_dir(), self.request.id)+'_out.log', 'w'), open(os.path.join(voxel_globe.tools.log_dir(), self.request.id)+'_err.log', 'w')): openclDevice = os.environ['VIP_OPENCL_DEVICE'] opencl_memory = os.environ.get('VIP_OPENCL_MEMORY', None) if opencl_memory: opencl_memory = int(opencl_memory) scene = models.Scene.objects.get(id=scene_id) imageSet = models.ImageSet.objects.get(id=image_set_id) imageList = imageSet.images.all() with voxel_globe.tools.task_dir('voxel_world') as processing_dir: logger.warning(bbox) create_scene_xml(openclDevice, 0, float(bbox['voxel_size']), lvcs1=(float(bbox['x_min']), float(bbox['y_min']), float(bbox['z_min'])), lvcs2=(float(bbox['x_max']), float(bbox['y_max']), float(bbox['z_max'])), origin=scene.origin, model_dir='.', number_bins=1, output_file=open(os.path.join(processing_dir, 'scene.xml'), 'w'), n_bytes_gpu=opencl_memory) counter = 1 imageNames = [] cameraNames = [] os.mkdir(os.path.join(processing_dir, 'local')) #Prepping self.update_state(state='INITIALIZE', meta={'image_set_name': imageSet.name, 'stage':'camera fetch'}) for image in imageList: (K,R,T,o) = get_krt(image, camera_set_id) krtName = os.path.join(processing_dir, 'local', 'frame_%05d.krt' % counter) with open(krtName, 'w') as fid: print >>fid, (("%0.18f "*3+"\n")*3) % (K[0,0], K[0,1], K[0,2], K[1,0], K[1,1], K[1,2], K[2,0], K[2,1], K[2,2]) print >>fid, (("%0.18f "*3+"\n")*3) % (R[0,0], R[0,1], R[0,2], R[1,0], R[1,1], R[1,2], R[2,0], R[2,1], R[2,2]) print >>fid, ("%0.18f "*3+"\n") % (T[0,0], T[1,0], T[2,0]) imageName = image.filename_path extension = os.path.splitext(imageName)[1] localName = os.path.join(processing_dir, 'local', 'frame_%05d%s' % (counter, extension)) lncp(imageName, localName) counter += 1 imageNames.append(localName) cameraNames.append(krtName) variance = 0.06 vxl_scene = boxm2_scene_adaptor(os.path.join(processing_dir, "scene.xml"), openclDevice) # loaded_imgs = [] # loaded_cams = [] # for i in range(0, len(imageNames), skip_frames): # logger.debug("i: %d img name: %s cam name: %s", i, imageNames[i], # cameraNames[i]) # self.update_state(state='PRELOADING', meta={'image_set_name': imageSet.name, # 'stage':'image load', # 'i':i, # 'total':len(imageNames)}) # img, ni, nj = load_image(imageNames[i]) # loaded_imgs.append(img) # pcam = load_perspective_camera(cameraNames[i]) # loaded_cams.append(pcam) refine_cnt = 2 for rfk in range(0, refine_cnt, 1): self.update_state(state='PROCESSING', meta={'image_set_name': imageSet.name, 'stage':'update 1'}) update_bp(vxl_scene, imageNames, cameraNames) # self.update_state(state='PROCESSING', meta={'image_set_name': imageSet.name, # 'stage':'update 2'}) # update_bp(vxl_scene, imageNames, cameraNames, True, True) # self.update_state(state='PROCESSING', meta={'image_set_name': imageSet.name, # 'stage':'update 3'}) # update_bp(vxl_scene, imageNames, cameraNames, True, True) if rfk < refine_cnt-1: self.update_state(state='PROCESSING', meta={'image_set_name': imageSet.name, 'stage':'refine', 'i':rfk+1, 'total':refine_cnt}) refine(vxl_scene) #Update color appearance with open(os.path.join(processing_dir, "scene_color.xml"), 'w') as fid: lines = open(os.path.join(processing_dir, "scene.xml"), 'r').readlines() lines = [line.replace('boxm2_mog3_grey', 'boxm2_gauss_rgb').replace( 'boxm2_num_obs', 'boxm2_num_obs_single') for line in lines] fid.writelines(lines) vxl_scene = boxm2_scene_adaptor(os.path.join(processing_dir, "scene_color.xml"), openclDevice) for idx, (image_name, camera_name) in enumerate(zip(imageNames, cameraNames)): self.update_state(state='PROCESSING', meta={ 'image_set_name': imageSet.name, 'stage':'color_update', 'i':idx+1, 'total':len(imageNames), 'images':len(imageNames)}) img, _, _ = load_image(image_name) pcam = vpgl.load_perspective_camera(camera_name) logger.debug("color_paint idx: %d", idx) vxl_scene.update(pcam,img,False,False,None,openclDevice, tnear = 1000.0, tfar = 100000.0) vxl_scene.write_cache() with voxel_globe.tools.storage_dir('voxel_world') as voxel_world_dir: copytree(processing_dir, voxel_world_dir, ignore=lambda x,y:['local']) models.VoxelWorld( name='%s world (%s)' % (imageSet.name, self.request.id), origin=scene.origin, directory=voxel_world_dir, service_id=self.request.id).save() return {"image_set_name" : imageSet.name}
def generate_error_point_cloud(self, voxel_world_id, prob=0.5, history=None): from glob import glob import json import numpy as np from boxm2_adaptor import load_cpp, render_depth, cast_3d_point, \ cast_3d_point_pass2, write_cache, \ create_stream_cache from boxm2_scene_adaptor import boxm2_scene_adaptor from vpgl_adaptor import create_perspective_camera_krt, persp2gen, \ compute_direction_covariance from boxm2_mesh_adaptor import batch_compute_3d_points, gen_error_point_cloud from vsi.tools.redirect import Redirect, Logger as LoggerWrapper import voxel_globe.tools import voxel_globe.meta.models as models from voxel_globe.tools.camera import get_krt with Redirect(stdout_c=LoggerWrapper(logger, lvl=logging.INFO), stderr_c=LoggerWrapper(logger, lvl=logging.WARNING)): self.update_state(state='SETUP', meta={'pid':os.getpid()}) voxel_world = models.VoxelWorld.objects.get(id=voxel_world_id) service_inputs = json.loads(voxel_world.service.inputs) image_collection = models.ImageCollection.objects.get( id=service_inputs[0][0]) images = image_collection.images.all() scene = models.Scene.objects.get(id=service_inputs[0][1]) voxel_world_dir = voxel_world.directory scene_filename = os.path.join(voxel_world_dir, 'scene.xml') opencl_device = os.environ['VIP_OPENCL_DEVICE'] scene_gpu = boxm2_scene_adaptor(scene_filename, opencl_device) scene_cpp = boxm2_scene_adaptor(scene_filename, 'cpp') type_id_fname = "type_names_list.txt" image_id_fname = "image_list.txt" std_dev_angle = 0.1 cov_c_path = 'cov_c.txt' cov_c = 0*np.eye(3)*0.8**2 with voxel_globe.tools.task_dir('generate_error_point_cloud', cd=True) \ as processing_dir: np.savetxt(cov_c_path, cov_c) for index, image in enumerate(images): self.update_state(state='PROCESSING', meta={'stage':'casting', 'image':index+1, 'total':len(images)}) k,r,t,o = get_krt(image.history(history)) perspective_camera = create_perspective_camera_krt(k, r, t) (depth_image, variance_image, _) = render_depth(scene_gpu.scene, scene_gpu.opencl_cache, perspective_camera, image.imageWidth, image.imageHeight, scene_gpu.device) cov_v_path = 'cov_%06d.txt' % index appearance_model = 'image_%06d' % index generic_camera = persp2gen(perspective_camera, image.imageWidth, image.imageHeight) compute_direction_covariance(perspective_camera, std_dev_angle, cov_v_path) cast_3d_point(scene_cpp.scene,scene_cpp.cpu_cache,perspective_camera, generic_camera,depth_image,variance_image,appearance_model) cast_3d_point_pass2(scene_cpp.scene,scene_cpp.cpu_cache,generic_camera, appearance_model,cov_c_path,cov_v_path) write_cache(scene_cpp.cpu_cache, 1) self.update_state(state='PROCESSING', meta={'stage':'compute error'}) with open(image_id_fname, 'w') as fid: print >>fid, len(images) for index, image in enumerate(images): print >>fid, 'image_%06d' % (index) with open(type_id_fname,"w") as fid: print >>fid, 2 print >>fid, "boxm2_point" print >>fid, "boxm2_covariance" mem=3.0 stream_cache = create_stream_cache(scene_cpp.scene, type_id_fname, image_id_fname, mem) batch_compute_3d_points(scene_cpp.scene, scene_cpp.cpu_cache, stream_cache) self.update_state(state='EXPORTING', meta={'stage':'ply'}) with voxel_globe.tools.storage_dir('generate_error_point_cloud') \ as storage_dir: ply_filename = os.path.join(storage_dir, 'model.ply') gen_error_point_cloud(scene_cpp.scene, scene_cpp.cpu_cache, ply_filename, 0.5, True) potree_filename = os.path.join(storage_dir, 'potree.ply') with voxel_globe.tools.image_dir('point_cloud') as potree_dir: convert_ply_to_potree(ply_filename, potree_dir) models.PointCloud.create(name='%s point cloud' % image_collection.name, service_id=self.request.id, origin=voxel_world.origin, potree_url='%s://%s:%s/%s/point_cloud/%s/cloud.js' % \ (env['VIP_IMAGE_SERVER_PROTOCOL'], env['VIP_IMAGE_SERVER_HOST'], env['VIP_IMAGE_SERVER_PORT'], env['VIP_IMAGE_SERVER_URL_PATH'], os.path.basename(potree_dir)), directory=storage_dir).save() voxel_files = lambda x: glob(os.path.join(voxel_world_dir, x)) cleanup_files = [] cleanup_files += voxel_files('boxm2_covariance_*.bin') cleanup_files += voxel_files('boxm2_point_*.bin') cleanup_files += voxel_files('float16_image_*.bin') for cleanup_file in cleanup_files: os.remove(cleanup_file)
def run_build_voxel_model_bp(self, image_collection_id, scene_id, bbox, skip_frames, cleanup=True, history=None): from distutils.dir_util import remove_tree from shutil import move import random from vsi.tools.redirect import StdRedirect, Logger as LoggerWrapper from voxel_globe.meta import models from voxel_globe.tools.camera import get_krt import voxel_globe.tools from boxm2_scene_adaptor import boxm2_scene_adaptor from vil_adaptor import load_image from vpgl_adaptor import load_perspective_camera from voxel_globe.tools.wget import download as wget from vsi.vxl.create_scene_xml import create_scene_xml from vsi.tools.dir_util import copytree with StdRedirect( open( os.path.join(voxel_globe.tools.log_dir(), self.request.id) + '_out.log', 'w'), open( os.path.join(voxel_globe.tools.log_dir(), self.request.id) + '_err.log', 'w')): openclDevice = os.environ['VIP_OPENCL_DEVICE'] opencl_memory = os.environ.get('VIP_OPENCL_MEMORY', None) if opencl_memory: opencl_memory = int(opencl_memory) scene = models.Scene.objects.get(id=scene_id) imageCollection = models.ImageCollection.objects.get(\ id=image_collection_id).history(history) imageList = imageCollection.images.all() with voxel_globe.tools.task_dir('voxel_world') as processing_dir: logger.warning(bbox) if bbox['geolocated']: create_scene_xml( openclDevice, 3, float(bbox['voxel_size']), lla1=(float(bbox['x_min']), float(bbox['y_min']), float(bbox['z_min'])), lla2=(float(bbox['x_max']), float(bbox['y_max']), float(bbox['z_max'])), origin=scene.origin, model_dir='.', number_bins=1, output_file=open(os.path.join(processing_dir, 'scene.xml'), 'w'), n_bytes_gpu=opencl_memory) else: create_scene_xml( openclDevice, 3, float(bbox['voxel_size']), lvcs1=(float(bbox['x_min']), float(bbox['y_min']), float(bbox['z_min'])), lvcs2=(float(bbox['x_max']), float(bbox['y_max']), float(bbox['z_max'])), origin=scene.origin, model_dir='.', number_bins=1, output_file=open(os.path.join(processing_dir, 'scene.xml'), 'w'), n_bytes_gpu=opencl_memory) counter = 1 imageNames = [] cameraNames = [] os.mkdir(os.path.join(processing_dir, 'local')) #Prepping for image in imageList: self.update_state(state='INITIALIZE', meta={ 'stage': 'image fetch', 'i': counter, 'total': len(imageList) }) image = image.history(history) (K, R, T, o) = get_krt(image.history(history), history=history) krtName = os.path.join(processing_dir, 'local', 'frame_%05d.krt' % counter) with open(krtName, 'w') as fid: print >> fid, (("%0.18f " * 3 + "\n") * 3) % ( K[0, 0], K[0, 1], K[0, 2], K[1, 0], K[1, 1], K[1, 2], K[2, 0], K[2, 1], K[2, 2]) print >> fid, (("%0.18f " * 3 + "\n") * 3) % ( R[0, 0], R[0, 1], R[0, 2], R[1, 0], R[1, 1], R[1, 2], R[2, 0], R[2, 1], R[2, 2]) print >> fid, ("%0.18f " * 3 + "\n") % (T[0, 0], T[1, 0], T[2, 0]) imageName = image.originalImageUrl extension = os.path.splitext(imageName)[1] localName = os.path.join(processing_dir, 'local', 'frame_%05d%s' % (counter, extension)) wget(imageName, localName, secret=True) counter += 1 imageNames.append(localName) cameraNames.append(krtName) variance = 0.06 vxl_scene = boxm2_scene_adaptor( os.path.join(processing_dir, "scene.xml"), openclDevice) current_level = 0 loaded_imgs = [] loaded_cams = [] for i in range(0, len(imageNames), skip_frames): logger.debug("i: %d img name: %s cam name: %s", i, imageNames[i], cameraNames[i]) self.update_state(state='PRELOADING', meta={ 'stage': 'image load', 'i': i, 'total': len(imageNames) }) img, ni, nj = load_image(imageNames[i]) loaded_imgs.append(img) pcam = load_perspective_camera(cameraNames[i]) loaded_cams.append(pcam) refine_cnt = 5 refine_device = openclDevice[0:3] if refine_device == 'cpu': refine_device = 'cpp' for rfk in range(0, refine_cnt, 1): pair = zip(loaded_imgs, loaded_cams) random.shuffle(pair) for idx, (img, cam) in enumerate(pair): self.update_state(state='PROCESSING', meta={ 'stage': 'update', 'i': rfk + 1, 'total': refine_cnt, 'image': idx + 1, 'images': len(loaded_imgs) }) logger.debug("refine_cnt: %d, idx: %d", rfk, idx) vxl_scene.update(cam, img, True, True, None, openclDevice[0:3], variance, tnear=1000.0, tfar=100000.0) for bp_index in range(2): pass #height map update? logger.debug("writing cache: %d", rfk) vxl_scene.write_cache() logger.debug("wrote cache: %d", rfk) if rfk < refine_cnt - 1: self.update_state(state='PROCESSING', meta={ 'stage': 'refine', 'i': rfk, 'total': refine_cnt }) logger.debug("refining %d...", rfk) vxl_scene.refine(0.3, refine_device) vxl_scene.write_cache() with open(os.path.join(processing_dir, "scene_color.xml"), 'w') as fid: lines = open(os.path.join(processing_dir, "scene.xml"), 'r').readlines() lines = [ line.replace('boxm2_mog3_grey', 'boxm2_gauss_rgb').replace( 'boxm2_num_obs', 'boxm2_num_obs_single') for line in lines ] fid.writelines(lines) vxl_scene = boxm2_scene_adaptor( os.path.join(processing_dir, "scene_color.xml"), openclDevice) for idx, (img, cam) in enumerate(pair): self.update_state(state='PROCESSING', meta={ 'stage': 'color_update', 'i': rfk + 1, 'total': refine_cnt, 'image': idx + 1, 'images': len(loaded_imgs) }) logger.debug("color_paint idx: %d", idx) vxl_scene.update(cam, img, False, False, None, openclDevice[0:3], tnear=1000.0, tfar=100000.0) vxl_scene.write_cache() with voxel_globe.tools.storage_dir( 'voxel_world') as voxel_world_dir: copytree(processing_dir, voxel_world_dir, ignore=lambda x, y: ['images']) models.VoxelWorld.create( name='%s world (%s)' % (imageCollection.name, self.request.id), origin=scene.origin, directory=voxel_world_dir, service_id=self.request.id).save()
def generate_error_point_cloud( self, voxel_world_id, prob=0.5, position_error_override=None, orientation_error_override=None, history=None ): from glob import glob import json import numpy as np from boxm2_adaptor import ( load_cpp, render_depth, cast_3d_point, cast_3d_point_pass2, write_cache, accumulate_3d_point_and_cov, normalize_3d_point_and_cov, ) from boxm2_scene_adaptor import boxm2_scene_adaptor from vpgl_adaptor import create_perspective_camera_krt, persp2gen, compute_direction_covariance from boxm2_mesh_adaptor import gen_error_point_cloud from vsi.tools.redirect import StdRedirect, Logger as LoggerWrapper import voxel_globe.tools import voxel_globe.meta.models as models from voxel_globe.tools.camera import get_krt with StdRedirect( open(os.path.join(voxel_globe.tools.log_dir(), self.request.id) + "_out.log", "w"), open(os.path.join(voxel_globe.tools.log_dir(), self.request.id) + "_err.log", "w"), ): self.update_state(state="SETUP", meta={"pid": os.getpid()}) voxel_world = models.VoxelWorld.objects.get(id=voxel_world_id) service_inputs = json.loads(voxel_world.service.inputs) image_collection = models.ImageCollection.objects.get(id=service_inputs[0][0]) images = image_collection.images.all() scene = models.Scene.objects.get(id=service_inputs[0][1]) voxel_world_dir = voxel_world.directory scene_filename = os.path.join(voxel_world_dir, "scene_color.xml") opencl_device = os.environ["VIP_OPENCL_DEVICE"] scene_gpu = boxm2_scene_adaptor(scene_filename, opencl_device) scene_cpp = boxm2_scene_adaptor(scene_filename, "cpp") type_id_fname = "type_names_list.txt" image_id_fname = "image_list.txt" std_dev_angle_default = 0.1 cov_c_path = "cov_c.txt" cov_c_default = 0.8 with voxel_globe.tools.task_dir("generate_error_point_cloud", cd=True) as processing_dir: for index, image in enumerate(images): self.update_state( state="PROCESSING", meta={"stage": "casting", "image": index + 1, "total": len(images)} ) k, r, t, o = get_krt(image.history(history)) attributes = image.history(history).camera.history(history).attributes cov_c = attributes.get("position_error", std_dev_angle_default) if position_error_override is not None: cov_c = position_error_override std_dev_angle = attributes.get("orientation_error", cov_c_default) if orientation_error_override is not None: std_dev_angle = orientation_error_override cov_c = np.eye(3) * cov_c ** 2 np.savetxt(cov_c_path, cov_c) perspective_camera = create_perspective_camera_krt(k, r, t) self.update_state( state="PROCESSING", meta={"stage": "pre render", "image": index + 1, "total": len(images)} ) (depth_image, variance_image, _) = render_depth( scene_gpu.scene, scene_gpu.opencl_cache, perspective_camera, image.imageWidth, image.imageHeight, scene_gpu.device, ) self.update_state( state="PROCESSING", meta={"stage": "post_render", "image": index + 1, "total": len(images)} ) cov_v_path = "cov_%06d.txt" % index appearance_model = "image" self.update_state( state="PROCESSING", meta={"stage": "pre_persp2gen", "image": index + 1, "total": len(images)} ) generic_camera = persp2gen(perspective_camera, image.imageWidth, image.imageHeight) self.update_state( state="PROCESSING", meta={"stage": "pre_covar", "image": index + 1, "total": len(images)} ) compute_direction_covariance(perspective_camera, std_dev_angle, cov_v_path) self.update_state( state="PROCESSING", meta={"stage": "pre_cast1", "image": index + 1, "total": len(images)} ) cast_3d_point( scene_cpp.scene, scene_cpp.cpu_cache, perspective_camera, generic_camera, depth_image, variance_image, appearance_model, ) self.update_state( state="PROCESSING", meta={"stage": "pre_cast2", "image": index + 1, "total": len(images)} ) cast_3d_point_pass2( scene_cpp.scene, scene_cpp.cpu_cache, generic_camera, appearance_model, cov_c_path, cov_v_path ) self.update_state( state="PROCESSING", meta={"stage": "pre_accumulate", "image": index + 1, "total": len(images)} ) accumulate_3d_point_and_cov(scene_cpp.scene, scene_cpp.cpu_cache, appearance_model) # self.update_state(state='PROCESSING', # meta={'stage':'pre_write', 'image':index+1, # 'total':len(images)}) # write_cache(scene_cpp.cpu_cache, 1) self.update_state( state="PROCESSING", meta={"stage": "post_write", "image": index + 1, "total": len(images)} ) self.update_state(state="PROCESSING", meta={"stage": "compute error"}) normalize_3d_point_and_cov(scene_cpp.scene, scene_cpp.cpu_cache) self.update_state(state="PROCESSING", meta={"stage": "pre_write", "image": index + 1, "total": len(images)}) write_cache(scene_cpp.cpu_cache, 1) self.update_state(state="EXPORTING", meta={"stage": "ply"}) with voxel_globe.tools.storage_dir("generate_error_point_cloud") as storage_dir: ply_filename = os.path.join(storage_dir, "model.ply") gen_error_point_cloud(scene_cpp.scene, scene_cpp.cpu_cache, ply_filename, prob) potree_filename = os.path.join(storage_dir, "potree.ply") with voxel_globe.tools.image_dir("point_cloud") as potree_dir: convert_ply_to_potree(ply_filename, potree_dir) models.PointCloud.create( name="%s point cloud" % image_collection.name, service_id=self.request.id, origin=voxel_world.origin, potree_url="%s://%s:%s/%s/point_cloud/%s/cloud.js" % ( env["VIP_IMAGE_SERVER_PROTOCOL"], env["VIP_IMAGE_SERVER_HOST"], env["VIP_IMAGE_SERVER_PORT"], env["VIP_IMAGE_SERVER_URL_PATH"], os.path.basename(potree_dir), ), filename=ply_filename, ).save() voxel_files = lambda x: glob(os.path.join(voxel_world_dir, x)) cleanup_files = [] cleanup_files += voxel_files("boxm2_covariance_*.bin") cleanup_files += voxel_files("boxm2_point_*.bin") cleanup_files += voxel_files("float16_image_*.bin") for cleanup_file in cleanup_files: os.remove(cleanup_file)
def run_build_voxel_model_bp(self, image_set_id, camera_set_id, scene_id, bbox, skip_frames, cleanup=True): import random import glob import math import numpy as np from vsi.tools.redirect import StdRedirect from voxel_globe.meta import models from voxel_globe.tools.camera import get_krt import voxel_globe.tools from boxm2_scene_adaptor import boxm2_scene_adaptor import brl_init from vil_adaptor_boxm2_batch import load_image import vpgl_adaptor_boxm2_batch as vpgl from vsi.vxl.create_scene_xml import create_scene_xml from vsi.tools.dir_util import copytree from vsi.tools.file_util import lncp def rectint(recta, rectb): lx = max(recta[0], rectb[0]) rx = min(recta[2], rectb[2]) by = max(recta[1], rectb[1]) ty = min(recta[3], rectb[3]) if lx > rx or by > ty: return [0, 0, 0, 0], 0 else: return [lx, by, rx, ty], (rx - lx) * (ty - by) def generate_subsetim(scene, camfiles, ni, nj): subsetIdx = [] refIndices = [] minDepOverlap = 0.25 minRefOverlap = 0.5 minIndepAngle = 5.0 minRefAngle = 5.0 maxRefAngle = 15.0 minRefIndepAngle = 5.0 cosMinIndepAngle = math.cos(minIndepAngle * math.pi / 180.0) cosMinRefAngle = math.cos(minRefAngle * math.pi / 180.0) cosMaxRefAngle = math.cos(maxRefAngle * math.pi / 180.0) cosMinRefIndepAngle = math.cos(minRefIndepAngle * math.pi / 180.0) bbox = scene.bbox grect = [ scene.bbox[0][0], scene.bbox[0][1], scene.bbox[1][0], scene.bbox[1][1] ] worldoverlaps = [] camrects = [] cams = [] princAxis = [] for camfile in camfiles: pcam = vpgl.load_perspective_camera(camfile) prx, pry, prz = vpgl.get_backprojected_ray(pcam, ni / 2, nj / 2) princAxis.append([prx, pry, prz]) Hmat = vpgl.compute_camera_to_world_homography( pcam, [0, 0, 1, -bbox[0][2]]) H = np.array(Hmat).reshape([3, 3]) ps = np.dot( H, np.transpose([[0, 0, 1], [ni, 0, 1], [ni, nj, 1], [0, nj, 1]])) xs = ps[0, :] / ps[2, :] ys = ps[1, :] / ps[2, :] rect = [min(xs), min(ys), max(xs), max(ys)] area = (rect[2] - rect[0]) * (rect[3] - rect[1]) crect, carea = rectint(rect, grect) #print crect,carea if (carea > 0): cams.append(pcam) camrects.append(crect) worldoverlaps.append(carea / area) usedcams = [False] * len(cams) for i in range(0, len(cams)): randidx = random.randint(0, len(cams) - 1) while usedcams[randidx]: randidx = (randidx + 1) % len(cams) usedcams[randidx] = True dep = False for c2 in range(0, len(subsetIdx)): cosAngle = np.dot(princAxis[randidx], princAxis[subsetIdx[c2]]) if cosAngle > cosMinIndepAngle: rectc2 = camrects[subsetIdx[c2]] overlap, oarea = rectint(camrects[randidx], rectc2) tarea = (rectc2[2] - rectc2[0]) * (rectc2[3] - rectc2[1]) if (oarea / tarea > minDepOverlap): dep = True break if dep: continue theseRefIndices = [] for c3 in range(0, len(cams)): #Check angle disparity cosAngle2 = np.dot(princAxis[randidx], princAxis[c3]) if (cosAngle2 > cosMinRefAngle or cosAngle2 < cosMaxRefAngle): continue # Check that a similar viewpoint isn't already used for reference refDep = False for c4 in range(0, len(theseRefIndices)): #Check angle disparity cosAngle3 = np.dot(princAxis[theseRefIndices[c4]], princAxis[c3]) if (cosAngle3 > cosMinRefIndepAngle): refDep = True break #If similar viewpoint don't add if (refDep): continue theseRefIndices.append(c3) #If at least one reference image save this viewpoint if len(theseRefIndices) > 0: subsetIdx.append(randidx) refIndices.append(theseRefIndices) return subsetIdx, refIndices def update_bp(scene, images, cameras, do_update_image=True, do_update_hmap=False): _, ni, nj = load_image(images[0]) frames, refimages = generate_subsetim(scene, cameras, ni, nj) for file_name in glob.glob(os.path.join(scene.model_dir, 'boxm2_*.bin')): os.remove(file_name) scene.init_uniform_prob() sradius = 16 idents = [] weights = [] if do_update_image: idents.append("if") weights.append(1.0) if do_update_hmap: idents.append("hf") weights.append(2.0) for idx, i in enumerate(frames): if do_update_image: print "Iteration ", idx, "Image ", images[i] ####load image and camera viewid = os.path.splitext(os.path.basename(images[i]))[0] #### forming an app model using the neighbor images for lindex in refimages[idx]: lcam = vpgl.load_perspective_camera(cameras[lindex]) limg, ni, nj = load_image(images[lindex]) scene.update(lcam, limg, False, True, None, "gpu0", 0.05, viewid) scene.update_if(False, viewid) # subtracting the image factor scene.fuse_factors(idents, weights) pcam = vpgl.load_perspective_camera(cameras[i]) img, ni, nj = load_image(images[i]) scene.compute_pre_post(pcam, img, viewid, 100000, 100000) # computing the new image factor scene.update_if(True, viewid) # adding the image factor scene.fuse_factors(idents, weights) if do_update_hmap and idx % 2 == 0: scene.update_hf(False) # subtracting the height-map factor scene.fuse_factors(idents, weights) zimg, zvar, ximg, yimg, probimg = scene.render_height_map() #save_image(zimg, "./zimg.tif") scene.compute_hmapf(zimg, zvar, ximg, yimg, sradius) # computing the height-map factor scene.update_hf(True) # adding the height-map factor scene.fuse_factors(idents, weights) scene.write_cache() def refine(scene): scene.refine(0.3) for filename in glob.glob(os.path.join(scene.model_dir, '[a-b]*.bin')): os.remove(filename) scene.write_cache() with StdRedirect( open( os.path.join(voxel_globe.tools.log_dir(), self.request.id) + '_out.log', 'w'), open( os.path.join(voxel_globe.tools.log_dir(), self.request.id) + '_err.log', 'w')): openclDevice = os.environ['VIP_OPENCL_DEVICE'] opencl_memory = os.environ.get('VIP_OPENCL_MEMORY', None) if opencl_memory: opencl_memory = int(opencl_memory) scene = models.Scene.objects.get(id=scene_id) imageSet = models.ImageSet.objects.get(id=image_set_id) imageList = imageSet.images.all() with voxel_globe.tools.task_dir('voxel_world') as processing_dir: logger.warning(bbox) create_scene_xml(openclDevice, 0, float(bbox['voxel_size']), lvcs1=(float(bbox['x_min']), float(bbox['y_min']), float(bbox['z_min'])), lvcs2=(float(bbox['x_max']), float(bbox['y_max']), float(bbox['z_max'])), origin=scene.origin, model_dir='.', number_bins=1, output_file=open( os.path.join(processing_dir, 'scene.xml'), 'w'), n_bytes_gpu=opencl_memory) counter = 1 imageNames = [] cameraNames = [] os.mkdir(os.path.join(processing_dir, 'local')) #Prepping self.update_state(state='INITIALIZE', meta={ 'image_set_name': imageSet.name, 'stage': 'camera fetch' }) for image in imageList: (K, R, T, o) = get_krt(image, camera_set_id) krtName = os.path.join(processing_dir, 'local', 'frame_%05d.krt' % counter) with open(krtName, 'w') as fid: print >> fid, (("%0.18f " * 3 + "\n") * 3) % ( K[0, 0], K[0, 1], K[0, 2], K[1, 0], K[1, 1], K[1, 2], K[2, 0], K[2, 1], K[2, 2]) print >> fid, (("%0.18f " * 3 + "\n") * 3) % ( R[0, 0], R[0, 1], R[0, 2], R[1, 0], R[1, 1], R[1, 2], R[2, 0], R[2, 1], R[2, 2]) print >> fid, ("%0.18f " * 3 + "\n") % (T[0, 0], T[1, 0], T[2, 0]) imageName = image.filename_path extension = os.path.splitext(imageName)[1] localName = os.path.join(processing_dir, 'local', 'frame_%05d%s' % (counter, extension)) lncp(imageName, localName) counter += 1 imageNames.append(localName) cameraNames.append(krtName) variance = 0.06 vxl_scene = boxm2_scene_adaptor( os.path.join(processing_dir, "scene.xml"), openclDevice) # loaded_imgs = [] # loaded_cams = [] # for i in range(0, len(imageNames), skip_frames): # logger.debug("i: %d img name: %s cam name: %s", i, imageNames[i], # cameraNames[i]) # self.update_state(state='PRELOADING', meta={'image_set_name': imageSet.name, # 'stage':'image load', # 'i':i, # 'total':len(imageNames)}) # img, ni, nj = load_image(imageNames[i]) # loaded_imgs.append(img) # pcam = load_perspective_camera(cameraNames[i]) # loaded_cams.append(pcam) refine_cnt = 2 for rfk in range(0, refine_cnt, 1): self.update_state(state='PROCESSING', meta={ 'image_set_name': imageSet.name, 'stage': 'update 1' }) update_bp(vxl_scene, imageNames, cameraNames) # self.update_state(state='PROCESSING', meta={'image_set_name': imageSet.name, # 'stage':'update 2'}) # update_bp(vxl_scene, imageNames, cameraNames, True, True) # self.update_state(state='PROCESSING', meta={'image_set_name': imageSet.name, # 'stage':'update 3'}) # update_bp(vxl_scene, imageNames, cameraNames, True, True) if rfk < refine_cnt - 1: self.update_state(state='PROCESSING', meta={ 'image_set_name': imageSet.name, 'stage': 'refine', 'i': rfk + 1, 'total': refine_cnt }) refine(vxl_scene) #Update color appearance with open(os.path.join(processing_dir, "scene_color.xml"), 'w') as fid: lines = open(os.path.join(processing_dir, "scene.xml"), 'r').readlines() lines = [ line.replace('boxm2_mog3_grey', 'boxm2_gauss_rgb').replace( 'boxm2_num_obs', 'boxm2_num_obs_single') for line in lines ] fid.writelines(lines) vxl_scene = boxm2_scene_adaptor( os.path.join(processing_dir, "scene_color.xml"), openclDevice) for idx, (image_name, camera_name) in enumerate(zip(imageNames, cameraNames)): self.update_state(state='PROCESSING', meta={ 'image_set_name': imageSet.name, 'stage': 'color_update', 'i': idx + 1, 'total': len(imageNames), 'images': len(imageNames) }) img, _, _ = load_image(image_name) pcam = vpgl.load_perspective_camera(camera_name) logger.debug("color_paint idx: %d", idx) vxl_scene.update(pcam, img, False, False, None, openclDevice, tnear=1000.0, tfar=100000.0) vxl_scene.write_cache() with voxel_globe.tools.storage_dir( 'voxel_world') as voxel_world_dir: copytree(processing_dir, voxel_world_dir, ignore=lambda x, y: ['local']) models.VoxelWorld(name='%s world (%s)' % (imageSet.name, self.request.id), origin=scene.origin, directory=voxel_world_dir, service_id=self.request.id).save() return {"image_set_name": imageSet.name}
def runVisualSfm(self, imageSetId, sceneId, cleanup=True): from voxel_globe.meta import models from os import environ as env from os.path import join as path_join import os import shutil import time from django.contrib.gis.geos import Point from .tools import writeNvm, writeGcpFile, generateMatchPoints, runSparse,\ readNvm import voxel_globe.tools from voxel_globe.tools.camera import get_kto, save_krt import voxel_globe.tools.enu as enu import numpy import boxm2_adaptor import boxm2_scene_adaptor from voxel_globe.tools.xml_dict import load_xml from django.contrib.gis.geos import Point from voxel_globe.tools.image import convert_image from distutils.spawn import find_executable from vsi.iglob import glob as glob self.update_state(state='INITIALIZE', meta={'stage':0}) #Make main temp dir and cd into it with voxel_globe.tools.task_dir('visualsfm', cd=True) as processing_dir: #Because visualsfm is so... bad, I need to copy it locally so I can #configure it visualsfm_exe = os.path.join(processing_dir, 'visualsfm') shutil.copy(find_executable('VisualSFM'), visualsfm_exe) with open(os.path.join(processing_dir, 'nv.ini'), 'w') as fid: fid.write('param_search_multiple_models 0\n') fid.write('param_use_siftgpu 2\n') matchFilename = path_join(processing_dir, 'match.nvm') sparce_filename = path_join(processing_dir, 'sparse.nvm') #This can NOT be changed in version 0.5.25 gcpFilename = matchFilename + '.gcp' logger.debug('Task %s is processing in %s' % (self.request.id, processing_dir)) image_set = models.ImageSet.objects.get( id=imageSetId) imageList = image_set.images.all() ### if 1: ### try: #Not fully integrated yet ### sift_gpu = siftgpu.SiftGPU() ### except: ### pass localImageList = [] for x in range(len(imageList)): #Download the image locally image = imageList[x] self.update_state(state='INITIALIZE', meta={'stage':'image fetch', 'i':x, 'total':len(imageList)}) imageName = image.filename_path extension = os.path.splitext(imageName)[1].lower() localName = path_join(processing_dir, 'frame_%05d%s' % (x+1, extension)) #lncp(imageName, localName) #Stupid VisualSFM dereferences symlinks, breaking this shutil.copyfile(imageName, localName) #Convert the image if necessary if extension not in ['.jpg', '.jpeg', '.pgm', '.ppm']: self.update_state(state='INITIALIZE', meta={'stage':'image convert', 'i':x, 'total':len(imageList)}) #Add code here to converty to jpg for visual sfm if extension in ['.png']:#'not implemented': from PIL import Image image_temp = Image.open(localName) # if len(image_temp.mode) > 1: #Stupid visual sfm is picky :( # new_local_name = os.path.splitext(localName)[0] + '.ppm' # else: # new_local_name = os.path.splitext(localName)[0] + '.pgm' new_local_name = os.path.splitext(localName)[0] + '.jpg' ###ingest.convert_image(localName, new_local_name, 'PNM') convert_image(localName, new_local_name, 'JPEG', options=('QUALITY=100',)) os.remove(localName) localName = new_local_name else: raise Exception('Unsupported file type') imageInfo = {'localName':localName, 'index':x} try: [K, T, llh] = get_kto(image) imageInfo['K_intrinsics'] = K imageInfo['transformation'] = T imageInfo['enu_origin'] = llh except: pass localImageList.append(imageInfo) ### if 1: ### try: #not fully integrated yet ### sift_gpu.create_sift(localName, os.path.splitext(localName)[0]+'.sift') ### except: ### pass # filenames = list(imageList.values_list('image_url')) # logger.info('The image list 0is %s' % filenames) self.update_state(state='PROCESSING', meta={'stage':'generate match points', 'processing_dir':processing_dir, 'total':len(imageList)}) pid = generateMatchPoints(map(lambda x:x['localName'], localImageList), matchFilename, logger=logger, executable=visualsfm_exe) old_mat=None old_sift=None #TODO: Replace with inotify to monitor directory while pid.poll() is None: mat = len(glob(os.path.join(processing_dir, '*.mat'), False)) sift = len(glob(os.path.join(processing_dir, '*.sift'), False)) if mat != old_mat or \ sift != old_sift: old_mat=mat old_sift=sift self.update_state(state='PROCESSING', meta={'stage':'generate match points', 'processing_dir':processing_dir, 'sift':sift, 'mat':mat, 'total':len(imageList)}) time.sleep(5) # cameras = [] # for image in imageList: # if 1: # #try: # [K, T, llh] = get_kto(image) # cameras.append({'image':image.id, 'K':K, 'tranformation': # T, 'origin':llh}) # #except: # pass # origin = numpy.median(origin, axis=0) # origin = [-92.215197, 37.648858, 268.599] scene = models.Scene.objects.get(id=sceneId) origin = list(scene.origin) if scene.geolocated: self.update_state(state='PROCESSING', meta={'stage':'writing gcp points'}) #find the middle origin, and make it THE origin data = []#.name .llh_xyz for imageInfo in localImageList: try: r = imageInfo['transformation'][0:3, 0:3] t = imageInfo['transformation'][0:3, 3:] enu_point = -r.transpose().dot(t) if not numpy.array_equal(imageInfo['enu_origin'], origin): ecef = enu.enu2xyz(refLong=imageInfo['enu_origin'][0], refLat=imageInfo['enu_origin'][1], refH=imageInfo['enu_origin'][2], #e=imageInfo['transformation'][0, 3], #n=imageInfo['transformation'][1, 3], #u=imageInfo['transformation'][2, 3]) e=enu_point[0], n=enu_point[1], u=enu_point[2]) enu_point = enu.xyz2enu(refLong=origin[0], refLat=origin[1], refH=origin[2], X=ecef[0], Y=ecef[1], Z=ecef[2]) # else: # enu_point = imageInfo['transformation'][0:3, 3] dataBit = {'filename':imageInfo['localName'], 'xyz':enu_point} data.append(dataBit) #Make this a separate ingest process, making CAMERAS linked to the #images #data = arducopter.loadAdjTaggedMetadata( # r'd:\visualsfm\2014-03-20 13-22-44_adj_tagged_images.txt') #Make this read the cameras from the DB instead writeGcpFile(data, gcpFilename) except: #some images may have no camera pass self.update_state(state='PROCESSING', meta={'stage':'sparse SFM'}) pid = runSparse(matchFilename, sparce_filename, gcp=scene.geolocated, shared=True, logger=logger, executable=visualsfm_exe) pid.wait() self.update_state(state='FINALIZE', meta={'stage':'loading resulting cameras'}) #prevent bundle2scene from getting confused and crashing sift_data = os.path.join(processing_dir, 'sift_data') os.mkdir(sift_data) for filename in glob(os.path.join(processing_dir, '*.mat'), False) +\ glob(os.path.join(processing_dir, '*.sift'), False): shutil.move(filename, sift_data) if scene.geolocated: #Create a uscene.xml for the geolocated case. All I want out of this is #the bounding box and gsd calculation. boxm2_adaptor.bundle2scene(sparce_filename, processing_dir, isalign=False, out_dir="") cams = readNvm(path_join(processing_dir, 'sparse.nvm')) #cams.sort(key=lambda x:x.name) #Since the file names are frame_00001, etc... and you KNOW this order is #identical to localImageList, with some missing camera_set = models.CameraSet(name="Visual SFM Geo %s" % image_set.name, service_id = self.request.id, images_id = imageSetId) camera_set.save() for cam in cams: frameName = cam.name #frame_00001, etc.... imageInfo = filter(lambda x: x['localName'].endswith(frameName), localImageList)[0] #I have to use endswith instead of == because visual sfm APPARENTLY #decides to take some liberty and make absolute paths relative image = imageList[imageInfo['index']] (k,r,t) = cam.krt(width=image.image_width, height=image.image_height) t = t.flatten() camera = save_krt(self.request.id, image, k, r, t, origin, srid=4326) camera_set.cameras.add(camera) else: from vsi.tools.natural_sort import natural_sorted from vsi.io.krt import Krt boxm2_adaptor.bundle2scene(sparce_filename, processing_dir, isalign=True, out_dir=processing_dir) #While the output dir is used for the b2s folders, uscene.xml is cwd #They are both set to processing_dir, so everything works out well aligned_cams = glob(os.path.join(processing_dir, 'cams_krt', '*')) #sort them naturally in case there are more then 99,999 files aligned_cams = natural_sorted(aligned_cams) if len(aligned_cams) != len(imageList): #Create a new image set new_image_set = models.ImageSet( name="SFM Result Subset (%s)" % image_set.name, service_id = self.request.id) # for image in image_set.images.all(): # new_image_set.images.add(image) new_image_set.save() frames_keep = set(map(lambda x: int(os.path.splitext(x.split('_')[-2])[0])-1, aligned_cams)) for frame_index in frames_keep: new_image_set.images.add(imageList[frame_index]) # frames_remove = set(xrange(len(imageList))) - frames_keep # # for remove_index in list(frames_remove): # #The frame number refers to the nth image in the image set, # #so frame_00100.tif is the 100th image, starting the index at one # #See local_name above # # #remove the images sfm threw away # new_image_set.remove(imageList[remove_index]) image_set = new_image_set frames_keep = list(frames_keep) else: frames_keep = xrange(len(aligned_cams)) camera_set = models.CameraSet(name="Visual SFM %s" % image_set.name, service_id = self.request.id, images_id = imageSetId) camera_set.save() #---Update the camera models in the database.--- for camera_index, frame_index in enumerate(frames_keep): krt = Krt.load(aligned_cams[camera_index]) image = imageList[frame_index] camera = save_krt(self.request.id, image, krt.k, krt.r, krt.t, [0,0,0], srid=4326) camera_set.cameras.add(camera) #---Update scene information important for the no-metadata case --- scene_filename = os.path.join(processing_dir, 'model', 'uscene.xml') boxm_scene = boxm2_scene_adaptor.boxm2_scene_adaptor(scene_filename) scene.bbox_min = Point(*boxm_scene.bbox[0]) scene.bbox_max = Point(*boxm_scene.bbox[1]) #This is not a complete or good function really... but it will get me the #information I need. scene_dict = load_xml(scene_filename) block = scene_dict['block'] scene.default_voxel_size=Point(float(block.at['dim_x']), float(block.at['dim_y']), float(block.at['dim_z'])) scene.save()
def generate_error_point_cloud(self, voxel_world_id, camera_set_id, prob=0.5, position_error_override=None, orientation_error_override=None, number_images=None): from glob import glob import json import random import numpy as np from boxm2_adaptor import load_cpp, render_depth, cast_3d_point, \ cast_3d_point_pass2, write_cache, \ accumulate_3d_point_and_cov, \ normalize_3d_point_and_cov from boxm2_scene_adaptor import boxm2_scene_adaptor from vpgl_adaptor_boxm2_batch import create_perspective_camera_krt, \ persp2gen, compute_direction_covariance from boxm2_mesh_adaptor import gen_error_point_cloud from vsi.tools.redirect import StdRedirect, Logger as LoggerWrapper import voxel_globe.tools import voxel_globe.meta.models as models from voxel_globe.tools.camera import get_krt with StdRedirect( open( os.path.join(voxel_globe.tools.log_dir(), self.request.id) + '_out.log', 'w'), open( os.path.join(voxel_globe.tools.log_dir(), self.request.id) + '_err.log', 'w')): self.update_state(state='SETUP', meta={'pid': os.getpid()}) voxel_world = models.VoxelWorld.objects.get(id=voxel_world_id) service_inputs = json.loads(voxel_world.service.inputs) image_set = models.ImageSet.objects.get(id=service_inputs[0][0]) images = image_set.images.all() voxel_world_dir = voxel_world.directory scene_filename = os.path.join(voxel_world_dir, 'scene_color.xml') opencl_device = os.environ['VIP_OPENCL_DEVICE'] scene_gpu = boxm2_scene_adaptor(scene_filename, opencl_device) scene_cpp = boxm2_scene_adaptor(scene_filename, 'cpp') type_id_fname = "type_names_list.txt" image_id_fname = "image_list.txt" std_dev_angle_default = 0 cov_c_path = 'cov_c.txt' cov_c_default = 0 if not number_images: number_images = len(images) number_images = min(len(images), number_images) with voxel_globe.tools.task_dir('generate_error_point_cloud', cd=True) \ as processing_dir: for index, image in enumerate(random.sample(images, number_images)): self.update_state(state='PROCESSING', meta={ 'stage': 'casting', 'image': index + 1, 'total': len(images) }) k, r, t, o = get_krt(image, camera_set_id) attributes = image.camera_set.get( cameraset=camera_set_id).attributes cov_c = attributes.get('position_error', cov_c_default) if position_error_override is not None: cov_c = position_error_override std_dev_angle = attributes.get('orientation_error', std_dev_angle_default) if orientation_error_override is not None: std_dev_angle = orientation_error_override cov_c = np.eye(3) * cov_c**2 np.savetxt(cov_c_path, cov_c) perspective_camera = create_perspective_camera_krt(k, r, t) self.update_state(state='PROCESSING', meta={ 'stage': 'pre render', 'image': index + 1, 'total': len(images) }) (depth_image, variance_image, _) = render_depth(scene_gpu.scene, scene_gpu.opencl_cache, perspective_camera, image.image_width, image.image_height, scene_gpu.device) self.update_state(state='PROCESSING', meta={ 'stage': 'post_render', 'image': index + 1, 'total': len(images) }) cov_v_path = 'cov_%06d.txt' % index appearance_model = 'image' self.update_state(state='PROCESSING', meta={ 'stage': 'pre_persp2gen', 'image': index + 1, 'total': len(images) }) generic_camera = persp2gen(perspective_camera, image.image_width, image.image_height) self.update_state(state='PROCESSING', meta={ 'stage': 'pre_covar', 'image': index + 1, 'total': len(images) }) compute_direction_covariance(perspective_camera, std_dev_angle, cov_v_path) self.update_state(state='PROCESSING', meta={ 'stage': 'pre_cast1', 'image': index + 1, 'total': len(images) }) cast_3d_point(scene_cpp.scene, scene_cpp.cpu_cache, perspective_camera, generic_camera, depth_image, variance_image, appearance_model) self.update_state(state='PROCESSING', meta={ 'stage': 'pre_cast2', 'image': index + 1, 'total': len(images) }) cast_3d_point_pass2(scene_cpp.scene, scene_cpp.cpu_cache, generic_camera, appearance_model, cov_c_path, cov_v_path) self.update_state(state='PROCESSING', meta={ 'stage': 'pre_accumulate', 'image': index + 1, 'total': len(images) }) accumulate_3d_point_and_cov(scene_cpp.scene, scene_cpp.cpu_cache, appearance_model) #self.update_state(state='PROCESSING', # meta={'stage':'pre_write', 'image':index+1, # 'total':len(images)}) #write_cache(scene_cpp.cpu_cache, 1) self.update_state(state='PROCESSING', meta={ 'stage': 'post_write', 'image': index + 1, 'total': len(images) }) self.update_state(state='PROCESSING', meta={'stage': 'compute error'}) normalize_3d_point_and_cov(scene_cpp.scene, scene_cpp.cpu_cache) self.update_state(state='PROCESSING', meta={ 'stage': 'pre_write', 'image': index + 1, 'total': len(images) }) write_cache(scene_cpp.cpu_cache, 1) self.update_state(state='EXPORTING', meta={'stage': 'ply'}) with voxel_globe.tools.storage_dir('generate_error_point_cloud') \ as storage_dir: ply_filename = os.path.join(storage_dir, 'model.ply') gen_error_point_cloud(scene_cpp.scene, scene_cpp.cpu_cache, ply_filename, prob) potree_filename = os.path.join(storage_dir, 'potree.ply') with voxel_globe.tools.image_dir('point_cloud') as potree_dir: convert_ply_to_potree(ply_filename, potree_dir) point_cloud = models.PointCloud(name='%s point cloud' % image_set.name, service_id=self.request.id, origin=voxel_world.origin) point_cloud.filename_path = ply_filename point_cloud.potree_dir = potree_dir point_cloud.save() voxel_files = lambda x: glob(os.path.join(voxel_world_dir, x)) cleanup_files = [] cleanup_files += voxel_files('boxm2_covariance_*.bin') cleanup_files += voxel_files('boxm2_point_*.bin') cleanup_files += voxel_files('float16_image_*.bin') for cleanup_file in cleanup_files: os.remove(cleanup_file)
def run_build_voxel_model(self, image_collection_id, scene_id, bbox, skip_frames, cleanup=True, history=None): from distutils.dir_util import remove_tree from shutil import move import random from vsi.tools.redirect import Redirect, Logger as LoggerWrapper from voxel_globe.meta import models from voxel_globe.tools.camera import get_krt import voxel_globe.tools from boxm2_scene_adaptor import boxm2_scene_adaptor from vil_adaptor import load_image from vpgl_adaptor import load_perspective_camera from voxel_globe.tools.wget import download as wget from vsi.vxl.create_scene_xml import create_scene_xml from vsi.tools.dir_util import copytree, mkdtemp with Redirect(stdout_c=LoggerWrapper(logger, lvl=logging.INFO), stderr_c=LoggerWrapper(logger, lvl=logging.WARNING)): openclDevice = os.environ['VIP_OPENCL_DEVICE'] opencl_memory = os.environ.get('VIP_OPENCL_MEMORY', None) scene = models.Scene.objects.get(id=scene_id) imageCollection = models.ImageCollection.objects.get(\ id=image_collection_id).history(history); imageList = imageCollection.images.all(); with voxel_globe.tools.task_dir('voxel_world') as processing_dir: logger.warning(bbox) if bbox['geolocated']: create_scene_xml(openclDevice, 3, float(bbox['voxel_size']), lla1=(float(bbox['x_min']), float(bbox['y_min']), float(bbox['z_min'])), lla2=(float(bbox['x_max']), float(bbox['y_max']), float(bbox['z_max'])), origin=scene.origin, model_dir='.', number_bins=1, output_file=open(os.path.join(processing_dir, 'scene.xml'), 'w'), n_bytes_gpu=opencl_memory) else: create_scene_xml(openclDevice, 3, float(bbox['voxel_size']), lvcs1=(float(bbox['x_min']), float(bbox['y_min']), float(bbox['z_min'])), lvcs2=(float(bbox['x_max']), float(bbox['y_max']), float(bbox['z_max'])), origin=scene.origin, model_dir='.', number_bins=1, output_file=open(os.path.join(processing_dir, 'scene.xml'), 'w'), n_bytes_gpu=opencl_memory) counter = 1; imageNames = [] cameraNames = [] os.mkdir(os.path.join(processing_dir, 'local')) #Prepping for image in imageList: self.update_state(state='INITIALIZE', meta={'stage':'image fetch', 'i':counter, 'total':len(imageList)}) image = image.history(history) (K,R,T,o) = get_krt(image.history(history), history=history) krtName = os.path.join(processing_dir, 'local', 'frame_%05d.krt' % counter) with open(krtName, 'w') as fid: print >>fid, (("%0.18f "*3+"\n")*3) % (K[0,0], K[0,1], K[0,2], K[1,0], K[1,1], K[1,2], K[2,0], K[2,1], K[2,2]); print >>fid, (("%0.18f "*3+"\n")*3) % (R[0,0], R[0,1], R[0,2], R[1,0], R[1,1], R[1,2], R[2,0], R[2,1], R[2,2]); print >>fid, ("%0.18f "*3+"\n") % (T[0,0], T[1,0], T[2,0]); imageName = image.originalImageUrl; extension = os.path.splitext(imageName)[1] localName = os.path.join(processing_dir, 'local', 'frame_%05d%s' % (counter, extension)); wget(imageName, localName, secret=True) counter += 1; imageNames.append(localName) cameraNames.append(krtName) variance = 0.06 vxl_scene = boxm2_scene_adaptor(os.path.join(processing_dir, "scene.xml"), openclDevice); current_level = 0; loaded_imgs = []; loaded_cams = []; for i in range(0, len(imageNames), skip_frames): logger.debug("i: %d img name: %s cam name: %s", i, imageNames[i], cameraNames[i]) self.update_state(state='PRELOADING', meta={'stage':'image load', 'i':i, 'total':len(imageNames)}) img, ni, nj = load_image(imageNames[i]) loaded_imgs.append(img) pcam = load_perspective_camera(cameraNames[i]) loaded_cams.append(pcam) refine_cnt = 5; for rfk in range(0, refine_cnt, 1): pair = zip(loaded_imgs, loaded_cams) random.shuffle(pair) for idx, (img, cam) in enumerate(pair): self.update_state(state='PROCESSING', meta={'stage':'update', 'i':rfk+1, 'total':refine_cnt, 'image':idx+1, 'images':len(loaded_imgs)}) logger.debug("refine_cnt: %d, idx: %d", rfk, idx) vxl_scene.update(cam,img,True,True,None,openclDevice[0:3],variance, tnear = 1000.0, tfar = 100000.0); logger.debug("writing cache: %d", rfk) vxl_scene.write_cache(); logger.debug("wrote cache: %d", rfk) if rfk < refine_cnt-1: self.update_state(state='PROCESSING', meta={'stage':'refine', 'i':rfk, 'total':refine_cnt}) logger.debug("refining %d...", rfk) refine_device = openclDevice[0:3] if refine_device == 'cpu': refine_device = 'cpp' vxl_scene.refine(0.3, refine_device); vxl_scene.write_cache(); voxel_world_dir = mkdtemp(dir=os.environ['VIP_STORAGE_DIR']) copytree(processing_dir, voxel_world_dir, ignore=lambda x,y:['images']) models.VoxelWorld.create( name='%s world (%s)' % (imageCollection.name, self.request.id), origin=scene.origin, directory=voxel_world_dir, service_id=self.request.id).save();
def runVisualSfm(self, imageCollectionId, sceneId, cleanup=True, history=None): from voxel_globe.meta import models from voxel_globe.order.visualsfm.models import Order from os import environ as env from os.path import join as path_join import os import shutil from .tools import writeNvm, writeGcpFile, generateMatchPoints, runSparse,\ readNvm import voxel_globe.tools from voxel_globe.tools.wget import download as wget from voxel_globe.tools.camera import get_kto import voxel_globe.tools.enu as enu import numpy import boxm2_adaptor import boxm2_scene_adaptor from voxel_globe.tools.xml_dict import load_xml from django.contrib.gis.geos import Point from voxel_globe.tools.image import convert_image from distutils.spawn import find_executable from glob import glob self.update_state(state='INITIALIZE', meta={'stage':0}) #Make main temp dir and cd into it with voxel_globe.tools.task_dir('visualsfm', cd=True) as processing_dir: #Because visualsfm is so... bad, I have to copy it locally so I can #configure it visualsfm_exe = os.path.join(processing_dir, os.path.basename(os.environ['VIP_VISUALSFM_EXE'])) shutil.copy(find_executable(os.environ['VIP_VISUALSFM_EXE']), visualsfm_exe) with open(os.path.join(processing_dir, 'nv.ini'), 'w') as fid: fid.write('param_search_multiple_models 0\n') fid.write('param_use_siftgpu 2\n') matchFilename = path_join(processing_dir, 'match.nvm'); sparce_filename = path_join(processing_dir, 'sparse.nvm'); #This can NOT be changed in version 0.5.25 gcpFilename = matchFilename + '.gcp' logger.debug('Task %s is processing in %s' % (self.request.id, processing_dir)) image_collection = models.ImageCollection.objects.get( id=imageCollectionId).history(history); imageList = image_collection.images.all(); #A Little bit of database logging oid = Order(processingDir=processing_dir, imageCollection=image_collection) ### if 1: ### try: #Not fully integrated yet ### sift_gpu = siftgpu.SiftGPU() ### except: ### pass localImageList = []; for x in range(len(imageList)): #Download the image locally image = imageList[x].history(history); self.update_state(state='INITIALIZE', meta={'stage':'image fetch', 'i':x, 'total':len(imageList)}) imageName = image.originalImageUrl; extension = os.path.splitext(imageName)[1].lower() localName = path_join(processing_dir, 'frame_%05d%s' % (x+1, extension)); wget(imageName, localName, secret=True) #Convert the image if necessary if extension not in ['.jpg', '.jpeg', '.pgm', '.ppm']: self.update_state(state='INITIALIZE', meta={'stage':'image convert', 'i':x, 'total':len(imageList)}) #Add code here to converty to jpg for visual sfm if extension in ['.png']:#'not implemented': from PIL import Image image_temp = Image.open(localName) if len(image_temp.mode) > 1: #Stupid visual sfm is picky :( new_local_name = os.path.splitext(localName)[0] + '.ppm'; else: new_local_name = os.path.splitext(localName)[0] + '.pgm'; new_local_name = os.path.splitext(localName)[0] + '.jpg'; ###ingest.convert_image(localName, new_local_name, 'PNM') convert_image(localName, new_local_name, 'JPEG', options=('QUALITY=100',)) os.remove(localName) localName = new_local_name; else: raise Exception('Unsupported file type'); imageInfo = {'localName':localName, 'index':x} try: [K, T, llh] = get_kto(image, history=history); imageInfo['K_intrinsics'] = K; imageInfo['transformation'] = T; imageInfo['enu_origin'] = llh; except: pass localImageList.append(imageInfo); ### if 1: ### try: #not fully integrated yet ### sift_gpu.create_sift(localName, os.path.splitext(localName)[0]+'.sift') ### except: ### pass # filenames = list(imageList.values_list('imageUrl')) # logger.info('The image list 0is %s' % filenames) self.update_state(state='PROCESSING', meta={'stage':'generate match points', 'processing_dir':processing_dir, 'total':len(imageList)}) generateMatchPoints(map(lambda x:x['localName'], localImageList), matchFilename, logger=logger, executable=visualsfm_exe) # cameras = []; # for image in imageList: # if 1: # #try: # [K, T, llh] = get_kto(image); # cameras.append({'image':image.id, 'K':K, 'tranformation': # T, 'origin':llh}) # #except: # pass # origin = numpy.median(origin, axis=0) # origin = [-92.215197, 37.648858, 268.599] scene = models.Scene.objects.get(id=sceneId).history(history) origin = list(scene.origin) if scene.geolocated: self.update_state(state='PROCESSING', meta={'stage':'writing gcp points'}) #find the middle origin, and make it THE origin data = []#.name .llh_xyz for imageInfo in localImageList: try: r = imageInfo['transformation'][0:3, 0:3] t = imageInfo['transformation'][0:3, 3:] enu_point = -r.transpose().dot(t); if not numpy.array_equal(imageInfo['enu_origin'], origin): ecef = enu.enu2xyz(refLong=imageInfo['enu_origin'][0], refLat=imageInfo['enu_origin'][1], refH=imageInfo['enu_origin'][2], #e=imageInfo['transformation'][0, 3], #n=imageInfo['transformation'][1, 3], #u=imageInfo['transformation'][2, 3]) e=enu_point[0], n=enu_point[1], u=enu_point[2]) enu_point = enu.xyz2enu(refLong=origin[0], refLat=origin[1], refH=origin[2], X=ecef[0], Y=ecef[1], Z=ecef[2]) # else: # enu_point = imageInfo['transformation'][0:3, 3]; dataBit = {'filename':imageInfo['localName'], 'xyz':enu_point} data.append(dataBit); #Make this a separate ingest process, making CAMERAS linked to the #images #data = arducopter.loadAdjTaggedMetadata( # r'd:\visualsfm\2014-03-20 13-22-44_adj_tagged_images.txt'); #Make this read the cameras from the DB instead writeGcpFile(data, gcpFilename) except: #some images may have no camera pass oid.lvcsOrigin = str(origin) oid.save() self.update_state(state='PROCESSING', meta={'stage':'sparse SFM'}) runSparse(matchFilename, sparce_filename, gcp=scene.geolocated, shared=True, logger=logger, executable=visualsfm_exe) self.update_state(state='FINALIZE', meta={'stage':'loading resulting cameras'}) #prevent bundle2scene from getting confused and crashing sift_data = os.path.join(processing_dir, 'sift_data') os.mkdir(sift_data) for filename in glob(os.path.join(processing_dir, '*.mat')) +\ glob(os.path.join(processing_dir, '*.sift')): shutil.move(filename, sift_data) if scene.geolocated: #Create a uscene.xml for the geolocated case. All I want out of this is #the bounding box and gsd calculation. boxm2_adaptor.bundle2scene(sparce_filename, processing_dir, isalign=False, out_dir="") cams = readNvm(path_join(processing_dir, 'sparse.nvm')) #cams.sort(key=lambda x:x.name) #Since the file names are frame_00001, etc... and you KNOW this order is #identical to localImageList, with some missing for cam in cams: frameName = cam.name; #frame_00001, etc.... imageInfo = filter(lambda x: x['localName'].endswith(frameName), localImageList)[0] #I have to use endswith instead of == because visual sfm APPARENTLY #decides to take some liberty and make absolute paths relative image = imageList[imageInfo['index']].history(history) (k,r,t) = cam.krt(width=image.imageWidth, height=image.imageHeight); logger.info('Origin is %s' % str(origin)) llh_xyz = enu.enu2llh(lon_origin=origin[0], lat_origin=origin[1], h_origin=origin[2], east=cam.translation_xyz[0], north=cam.translation_xyz[1], up=cam.translation_xyz[2]) grcs = models.GeoreferenceCoordinateSystem.create( name='%s 0' % image.name, xUnit='d', yUnit='d', zUnit='m', location='SRID=4326;POINT(%0.15f %0.15f %0.15f)' % (origin[0], origin[1], origin[2]), service_id = self.request.id) grcs.save() cs = models.CartesianCoordinateSystem.create( name='%s 1' % (image.name), service_id = self.request.id, xUnit='m', yUnit='m', zUnit='m'); cs.save() transform = models.CartesianTransform.create( name='%s 1_0' % (image.name), service_id = self.request.id, rodriguezX=Point(*r[0,:]), rodriguezY=Point(*r[1,:]), rodriguezZ=Point(*r[2,:]), translation=Point(t[0][0], t[1][0], t[2][0]), coordinateSystem_from_id=grcs.id, coordinateSystem_to_id=cs.id) transform.save() camera = image.camera; try: camera.update(service_id = self.request.id, focalLengthU=k[0,0], focalLengthV=k[1,1], principalPointU=k[0,2], principalPointV=k[1,2], coordinateSystem=cs); except: camera = models.Camera.create(name=image.name, service_id = self.request.id, focalLengthU=k[0,0], focalLengthV=k[1,1], principalPointU=k[0,2], principalPointV=k[1,2], coordinateSystem=cs); camera.save(); image.update(camera = camera); logger.info(str(cams[0])) else: from vsi.tools.natural_sort import natural_sorted from glob import glob from vsi.io.krt import Krt from voxel_globe.tools.camera import save_krt boxm2_adaptor.bundle2scene(sparce_filename, processing_dir, isalign=True, out_dir=processing_dir) #While the output dir is used for the b2s folders, uscene.xml is cwd #They are both set to processing_dir, so everything works out well aligned_cams = glob(os.path.join(processing_dir, 'cams_krt', '*')) #sort them naturally in case there are more then 99,999 files aligned_cams = natural_sorted(aligned_cams) if len(aligned_cams) != len(imageList): #Create a new image collection new_image_collection = models.ImageCollection.create( name="SFM Result Subset (%s)" % image_collection.name, service_id = self.request.id); # for image in image_collection.images.all(): # new_image_collection.images.add(image) new_image_collection.save(); frames_keep = set(map(lambda x: int(os.path.splitext(x.split('_')[-2])[0])-1, aligned_cams)) for frame_index in frames_keep: new_image_collection.images.add(imageList[frame_index]) # frames_remove = set(xrange(len(imageList))) - frames_keep # # for remove_index in list(frames_remove): # #The frame number refers to the nth image in the image collection, # #so frame_00100.tif is the 100th image, starting the index at one # #See local_name above # # #remove the images sfm threw away # new_image_collection.remove(imageList[remove_index]) image_collection = new_image_collection frames_keep = list(frames_keep) else: frames_keep = xrange(len(aligned_cams)) #---Update the camera models in the database.--- for camera_index, frame_index in enumerate(frames_keep): krt = Krt.load(aligned_cams[camera_index]) image = imageList[frame_index].history(history) save_krt(self.request.id, image, krt.k, krt.r, krt.t, [0,0,0], srid=4326) #---Update scene information important for the no-metadata case --- scene_filename = os.path.join(processing_dir, 'model', 'uscene.xml') boxm_scene = boxm2_scene_adaptor.boxm2_scene_adaptor(scene_filename) scene.bbox_min = 'POINT(%0.15f %0.15f %0.15f)' % boxm_scene.bbox[0] scene.bbox_max = 'POINT(%0.15f %0.15f %0.15f)' % boxm_scene.bbox[1] #This is not a complete or good function really... but it will get me the #information I need. scene_dict = load_xml(scene_filename) block = scene_dict['block'] scene.default_voxel_size='POINT(%f %f %f)' % \ (float(block.at['dim_x']), float(block.at['dim_y']), float(block.at['dim_z'])) scene.save() return oid.id;
def run_build_voxel_model(self, image_set_id, camera_set_id, scene_id, bbox, skip_frames, cleanup=True): import random from vsi.tools.redirect import StdRedirect from voxel_globe.meta import models from voxel_globe.tools.camera import get_krt import voxel_globe.tools from boxm2_scene_adaptor import boxm2_scene_adaptor import brl_init from vil_adaptor_boxm2_batch import load_image from vpgl_adaptor_boxm2_batch import load_perspective_camera from vsi.vxl.create_scene_xml import create_scene_xml from vsi.tools.dir_util import copytree from vsi.tools.file_util import lncp with StdRedirect(open(os.path.join(voxel_globe.tools.log_dir(), self.request.id)+'_out.log', 'w'), open(os.path.join(voxel_globe.tools.log_dir(), self.request.id)+'_err.log', 'w')): openclDevice = os.environ['VIP_OPENCL_DEVICE'] opencl_memory = os.environ.get('VIP_OPENCL_MEMORY', None) if opencl_memory: opencl_memory = int(opencl_memory) scene = models.Scene.objects.get(id=scene_id) imageSet = models.ImageSet.objects.get(\ id=image_set_id) imageList = imageSet.images.all() with voxel_globe.tools.task_dir('voxel_world') as processing_dir: logger.warning(bbox) create_scene_xml(openclDevice, 3, float(bbox['voxel_size']), lvcs1=(float(bbox['x_min']), float(bbox['y_min']), float(bbox['z_min'])), lvcs2=(float(bbox['x_max']), float(bbox['y_max']), float(bbox['z_max'])), origin=scene.origin, model_dir='.', number_bins=1, output_file=open(os.path.join(processing_dir, 'scene.xml'), 'w'), n_bytes_gpu=opencl_memory) counter = 1 imageNames = [] cameraNames = [] os.mkdir(os.path.join(processing_dir, 'local')) #Prepping for image in imageList: self.update_state(state='INITIALIZE', meta={'image_set_name': imageSet.name, 'stage':'image fetch', 'i':counter, 'total':len(imageList)}) (K,R,T,o) = get_krt(image, camera_set_id) krtName = os.path.join(processing_dir, 'local', 'frame_%05d.krt' % counter) with open(krtName, 'w') as fid: print >>fid, (("%0.18f "*3+"\n")*3) % (K[0,0], K[0,1], K[0,2], K[1,0], K[1,1], K[1,2], K[2,0], K[2,1], K[2,2]) print >>fid, (("%0.18f "*3+"\n")*3) % (R[0,0], R[0,1], R[0,2], R[1,0], R[1,1], R[1,2], R[2,0], R[2,1], R[2,2]) print >>fid, ("%0.18f "*3+"\n") % (T[0,0], T[1,0], T[2,0]) imageName = image.filename_path extension = os.path.splitext(imageName)[1] localName = os.path.join(processing_dir, 'local', 'frame_%05d%s' % (counter, extension)) lncp(imageName, localName) counter += 1 imageNames.append(localName) cameraNames.append(krtName) variance = 0.06 vxl_scene = boxm2_scene_adaptor(os.path.join(processing_dir, "scene.xml"), openclDevice) loaded_imgs = [] loaded_cams = [] for i in range(0, len(imageNames), skip_frames): logger.debug("i: %d img name: %s cam name: %s", i, imageNames[i], cameraNames[i]) self.update_state(state='PRELOADING', meta={'image_set_name': imageSet.name, 'stage':'image load', 'i':i, 'total':len(imageNames)}) img, ni, nj = load_image(imageNames[i]) loaded_imgs.append(img) pcam = load_perspective_camera(cameraNames[i]) loaded_cams.append(pcam) refine_cnt = 5 for rfk in range(0, refine_cnt, 1): pair = zip(loaded_imgs, loaded_cams) random.shuffle(pair) for idx, (img, cam) in enumerate(pair): self.update_state(state='PROCESSING', meta={'image_set_name': imageSet.name, 'stage':'update', 'i':rfk+1, 'total':refine_cnt, 'image':idx+1, 'images':len(loaded_imgs)}) logger.debug("refine_cnt: %d, idx: %d", rfk, idx) vxl_scene.update(cam,img,True,True,None,openclDevice,variance, tnear = 1000.0, tfar = 100000.0) logger.debug("writing cache: %d", rfk) vxl_scene.write_cache() logger.debug("wrote cache: %d", rfk) if rfk < refine_cnt-1: self.update_state(state='PROCESSING', meta={'image_set_name': imageSet.name, 'stage':'refine', 'i':rfk, 'total':refine_cnt}) logger.debug("refining %d...", rfk) vxl_scene.refine(0.3, openclDevice) vxl_scene.write_cache() with open(os.path.join(processing_dir, "scene_color.xml"), 'w') as fid: lines = open(os.path.join(processing_dir, "scene.xml"), 'r').readlines() lines = [line.replace('boxm2_mog3_grey', 'boxm2_gauss_rgb').replace( 'boxm2_num_obs', 'boxm2_num_obs_single') for line in lines] fid.writelines(lines) vxl_scene = boxm2_scene_adaptor(os.path.join(processing_dir, "scene_color.xml"), openclDevice) for idx, (img, cam) in enumerate(pair): self.update_state(state='PROCESSING', meta={'image_set_name': imageSet.name, 'stage':'color_update', 'i':rfk+1, 'total':refine_cnt, 'image':idx+1, 'images':len(loaded_imgs)}) logger.debug("color_paint idx: %d", idx) vxl_scene.update(cam,img,False,False,None,openclDevice, tnear = 1000.0, tfar = 100000.0) vxl_scene.write_cache() with voxel_globe.tools.storage_dir('voxel_world') as voxel_world_dir: copytree(processing_dir, voxel_world_dir, ignore=lambda x,y:['local']) models.VoxelWorld( name='%s world (%s)' % (imageSet.name, self.request.id), origin=scene.origin, directory=voxel_world_dir, service_id=self.request.id).save() return {"image_set_name" : imageSet.name}
def runVisualSfm(self, imageCollectionId, sceneId, cleanup=True, history=None): from voxel_globe.meta import models from voxel_globe.order.visualsfm.models import Order from os import environ as env from os.path import join as path_join import os import shutil from .tools import writeNvm, writeGcpFile, generateMatchPoints, runSparse,\ readNvm import voxel_globe.tools from voxel_globe.tools.wget import download as wget from voxel_globe.tools.camera import get_kto import voxel_globe.tools.enu as enu import numpy import boxm2_adaptor import boxm2_scene_adaptor from voxel_globe.tools.xml_dict import load_xml from django.contrib.gis.geos import Point from voxel_globe.tools.image import convert_image from distutils.spawn import find_executable from glob import glob self.update_state(state='INITIALIZE', meta={'stage': 0}) #Make main temp dir and cd into it with voxel_globe.tools.task_dir('visualsfm', cd=True) as processing_dir: #Because visualsfm is so... bad, I have to copy it locally so I can #configure it visualsfm_exe = os.path.join( processing_dir, os.path.basename(os.environ['VIP_VISUALSFM_EXE'])) shutil.copy(find_executable(os.environ['VIP_VISUALSFM_EXE']), visualsfm_exe) with open(os.path.join(processing_dir, 'nv.ini'), 'w') as fid: fid.write('param_search_multiple_models 0\n') fid.write('param_use_siftgpu 2\n') matchFilename = path_join(processing_dir, 'match.nvm') sparce_filename = path_join(processing_dir, 'sparse.nvm') #This can NOT be changed in version 0.5.25 gcpFilename = matchFilename + '.gcp' logger.debug('Task %s is processing in %s' % (self.request.id, processing_dir)) image_collection = models.ImageCollection.objects.get( id=imageCollectionId).history(history) imageList = image_collection.images.all() #A Little bit of database logging oid = Order(processingDir=processing_dir, imageCollection=image_collection) ### if 1: ### try: #Not fully integrated yet ### sift_gpu = siftgpu.SiftGPU() ### except: ### pass localImageList = [] for x in range(len(imageList)): #Download the image locally image = imageList[x].history(history) self.update_state(state='INITIALIZE', meta={ 'stage': 'image fetch', 'i': x, 'total': len(imageList) }) imageName = image.originalImageUrl extension = os.path.splitext(imageName)[1].lower() localName = path_join(processing_dir, 'frame_%05d%s' % (x + 1, extension)) wget(imageName, localName, secret=True) #Convert the image if necessary if extension not in ['.jpg', '.jpeg', '.pgm', '.ppm']: self.update_state(state='INITIALIZE', meta={ 'stage': 'image convert', 'i': x, 'total': len(imageList) }) #Add code here to converty to jpg for visual sfm if extension in ['.png']: #'not implemented': from PIL import Image image_temp = Image.open(localName) if len(image_temp.mode ) > 1: #Stupid visual sfm is picky :( new_local_name = os.path.splitext( localName)[0] + '.ppm' else: new_local_name = os.path.splitext( localName)[0] + '.pgm' new_local_name = os.path.splitext(localName)[0] + '.jpg' ###ingest.convert_image(localName, new_local_name, 'PNM') convert_image(localName, new_local_name, 'JPEG', options=('QUALITY=100', )) os.remove(localName) localName = new_local_name else: raise Exception('Unsupported file type') imageInfo = {'localName': localName, 'index': x} try: [K, T, llh] = get_kto(image, history=history) imageInfo['K_intrinsics'] = K imageInfo['transformation'] = T imageInfo['enu_origin'] = llh except: pass localImageList.append(imageInfo) ### if 1: ### try: #not fully integrated yet ### sift_gpu.create_sift(localName, os.path.splitext(localName)[0]+'.sift') ### except: ### pass # filenames = list(imageList.values_list('imageUrl')) # logger.info('The image list 0is %s' % filenames) self.update_state(state='PROCESSING', meta={ 'stage': 'generate match points', 'processing_dir': processing_dir, 'total': len(imageList) }) generateMatchPoints(map(lambda x: x['localName'], localImageList), matchFilename, logger=logger, executable=visualsfm_exe) # cameras = []; # for image in imageList: # if 1: # #try: # [K, T, llh] = get_kto(image); # cameras.append({'image':image.id, 'K':K, 'tranformation': # T, 'origin':llh}) # #except: # pass # origin = numpy.median(origin, axis=0) # origin = [-92.215197, 37.648858, 268.599] scene = models.Scene.objects.get(id=sceneId).history(history) origin = list(scene.origin) if scene.geolocated: self.update_state(state='PROCESSING', meta={'stage': 'writing gcp points'}) #find the middle origin, and make it THE origin data = [] #.name .llh_xyz for imageInfo in localImageList: try: r = imageInfo['transformation'][0:3, 0:3] t = imageInfo['transformation'][0:3, 3:] enu_point = -r.transpose().dot(t) if not numpy.array_equal(imageInfo['enu_origin'], origin): ecef = enu.enu2xyz( refLong=imageInfo['enu_origin'][0], refLat=imageInfo['enu_origin'][1], refH=imageInfo['enu_origin'][2], #e=imageInfo['transformation'][0, 3], #n=imageInfo['transformation'][1, 3], #u=imageInfo['transformation'][2, 3]) e=enu_point[0], n=enu_point[1], u=enu_point[2]) enu_point = enu.xyz2enu(refLong=origin[0], refLat=origin[1], refH=origin[2], X=ecef[0], Y=ecef[1], Z=ecef[2]) # else: # enu_point = imageInfo['transformation'][0:3, 3]; dataBit = { 'filename': imageInfo['localName'], 'xyz': enu_point } data.append(dataBit) #Make this a separate ingest process, making CAMERAS linked to the #images #data = arducopter.loadAdjTaggedMetadata( # r'd:\visualsfm\2014-03-20 13-22-44_adj_tagged_images.txt'); #Make this read the cameras from the DB instead writeGcpFile(data, gcpFilename) except: #some images may have no camera pass oid.lvcsOrigin = str(origin) oid.save() self.update_state(state='PROCESSING', meta={'stage': 'sparse SFM'}) runSparse(matchFilename, sparce_filename, gcp=scene.geolocated, shared=True, logger=logger, executable=visualsfm_exe) self.update_state(state='FINALIZE', meta={'stage': 'loading resulting cameras'}) #prevent bundle2scene from getting confused and crashing sift_data = os.path.join(processing_dir, 'sift_data') os.mkdir(sift_data) for filename in glob(os.path.join(processing_dir, '*.mat')) +\ glob(os.path.join(processing_dir, '*.sift')): shutil.move(filename, sift_data) if scene.geolocated: #Create a uscene.xml for the geolocated case. All I want out of this is #the bounding box and gsd calculation. boxm2_adaptor.bundle2scene(sparce_filename, processing_dir, isalign=False, out_dir="") cams = readNvm(path_join(processing_dir, 'sparse.nvm')) #cams.sort(key=lambda x:x.name) #Since the file names are frame_00001, etc... and you KNOW this order is #identical to localImageList, with some missing for cam in cams: frameName = cam.name #frame_00001, etc.... imageInfo = filter( lambda x: x['localName'].endswith(frameName), localImageList)[0] #I have to use endswith instead of == because visual sfm APPARENTLY #decides to take some liberty and make absolute paths relative image = imageList[imageInfo['index']].history(history) (k, r, t) = cam.krt(width=image.imageWidth, height=image.imageHeight) logger.info('Origin is %s' % str(origin)) llh_xyz = enu.enu2llh(lon_origin=origin[0], lat_origin=origin[1], h_origin=origin[2], east=cam.translation_xyz[0], north=cam.translation_xyz[1], up=cam.translation_xyz[2]) grcs = models.GeoreferenceCoordinateSystem.create( name='%s 0' % image.name, xUnit='d', yUnit='d', zUnit='m', location='SRID=4326;POINT(%0.15f %0.15f %0.15f)' % (origin[0], origin[1], origin[2]), service_id=self.request.id) grcs.save() cs = models.CartesianCoordinateSystem.create( name='%s 1' % (image.name), service_id=self.request.id, xUnit='m', yUnit='m', zUnit='m') cs.save() transform = models.CartesianTransform.create( name='%s 1_0' % (image.name), service_id=self.request.id, rodriguezX=Point(*r[0, :]), rodriguezY=Point(*r[1, :]), rodriguezZ=Point(*r[2, :]), translation=Point(t[0][0], t[1][0], t[2][0]), coordinateSystem_from_id=grcs.id, coordinateSystem_to_id=cs.id) transform.save() camera = image.camera try: camera.update(service_id=self.request.id, focalLengthU=k[0, 0], focalLengthV=k[1, 1], principalPointU=k[0, 2], principalPointV=k[1, 2], coordinateSystem=cs) except: camera = models.Camera.create(name=image.name, service_id=self.request.id, focalLengthU=k[0, 0], focalLengthV=k[1, 1], principalPointU=k[0, 2], principalPointV=k[1, 2], coordinateSystem=cs) camera.save() image.update(camera=camera) logger.info(str(cams[0])) else: from vsi.tools.natural_sort import natural_sorted from glob import glob from vsi.io.krt import Krt from voxel_globe.tools.camera import save_krt boxm2_adaptor.bundle2scene(sparce_filename, processing_dir, isalign=True, out_dir=processing_dir) #While the output dir is used for the b2s folders, uscene.xml is cwd #They are both set to processing_dir, so everything works out well aligned_cams = glob(os.path.join(processing_dir, 'cams_krt', '*')) #sort them naturally in case there are more then 99,999 files aligned_cams = natural_sorted(aligned_cams) if len(aligned_cams) != len(imageList): #Create a new image collection new_image_collection = models.ImageCollection.create( name="SFM Result Subset (%s)" % image_collection.name, service_id=self.request.id) # for image in image_collection.images.all(): # new_image_collection.images.add(image) new_image_collection.save() frames_keep = set( map( lambda x: int(os.path.splitext(x.split('_')[-2])[0]) - 1, aligned_cams)) for frame_index in frames_keep: new_image_collection.images.add(imageList[frame_index]) # frames_remove = set(xrange(len(imageList))) - frames_keep # # for remove_index in list(frames_remove): # #The frame number refers to the nth image in the image collection, # #so frame_00100.tif is the 100th image, starting the index at one # #See local_name above # # #remove the images sfm threw away # new_image_collection.remove(imageList[remove_index]) image_collection = new_image_collection frames_keep = list(frames_keep) else: frames_keep = xrange(len(aligned_cams)) #---Update the camera models in the database.--- for camera_index, frame_index in enumerate(frames_keep): krt = Krt.load(aligned_cams[camera_index]) image = imageList[frame_index].history(history) save_krt(self.request.id, image, krt.k, krt.r, krt.t, [0, 0, 0], srid=4326) #---Update scene information important for the no-metadata case --- scene_filename = os.path.join(processing_dir, 'model', 'uscene.xml') boxm_scene = boxm2_scene_adaptor.boxm2_scene_adaptor(scene_filename) scene.bbox_min = 'POINT(%0.15f %0.15f %0.15f)' % boxm_scene.bbox[0] scene.bbox_max = 'POINT(%0.15f %0.15f %0.15f)' % boxm_scene.bbox[1] #This is not a complete or good function really... but it will get me the #information I need. scene_dict = load_xml(scene_filename) block = scene_dict['block'] scene.default_voxel_size='POINT(%f %f %f)' % \ (float(block.at['dim_x']), float(block.at['dim_y']), float(block.at['dim_z'])) scene.save() return oid.id
def create_height_map(self, voxel_world_id, render_height): import shutil import urllib import numpy as np import brl_init from boxm2_scene_adaptor import boxm2_scene_adaptor from boxm2_adaptor import ortho_geo_cam_from_scene, scene_lvcs, scene_bbox from vpgl_adaptor_boxm2_batch import convert_local_to_global_coordinates, geo2generic, save_geocam_to_tfw from vil_adaptor_boxm2_batch import save_image, scale_and_offset_values, stretch_image, image_range import vsi.io.image import voxel_globe.tools import voxel_globe.tools.hash import voxel_globe.tools.camera import voxel_globe.meta.models as models import voxel_globe.ingest.payload.tools with voxel_globe.tools.task_dir('height_map', cd=True) as processing_dir: voxel_world = models.VoxelWorld.objects.get(id=voxel_world_id) scene = boxm2_scene_adaptor( os.path.join(voxel_world.directory, 'scene.xml'), env['VIP_OPENCL_DEVICE']) ortho_camera, cols, rows = ortho_geo_cam_from_scene(scene.scene) tfw_camera = os.path.join(processing_dir, 'cam.tfw') save_geocam_to_tfw(ortho_camera, tfw_camera) with open(tfw_camera, 'r') as fid: geo_transform = [float(x) for x in fid.readlines()] (x0, y0, z0), (x1, y1, z1) = scene_bbox(scene.scene) lvcs = scene_lvcs(scene.scene) #lvcs = vpgl_adaptor.create_lvcs(lat=origin[1], lon=origin[0], el=origin[2], # csname="wgs84") _, _, min_height = convert_local_to_global_coordinates( lvcs, x0, y0, z0) if render_height is None: render_height = z1 + (z1 - z0) / 1000 #z1+(z1-z0)/1000 is basically to say "just a little above the top" *2 is #1) overkill and 2) doesn't work with sign, +1 could go crazy in an #arbitrarily scaled system, so this just calculates ".1% more" which is #more than good enough else: render_height = render_height - voxel_world.origin[2] logger.critical("Render Height is %f (%s)", render_height, type(render_height)) generic_camera = geo2generic(ortho_camera, cols, rows, render_height, 0) z_exp_img, z_var_img = scene.render_z_image(generic_camera, cols, rows) #This is TECHNICALLY wrong, it assumes the earth is flat. scale_and_offset_values(z_exp_img, 1, min_height) height_filename = os.path.join(processing_dir, 'height.tif') save_image(z_exp_img, height_filename) checksum = voxel_globe.tools.hash.sha256_file(height_filename) with voxel_globe.tools.image_sha_dir(checksum) as image_dir: original_filename = os.path.join(image_dir, 'height_map.tif') #If the exact file exist already, don't ingest it again. Unlikely if not os.path.exists(original_filename): img = vsi.io.image.imread(height_filename) vsi.io.image.imwrite_geotiff( img.raster(), original_filename, [geo_transform[x] for x in [4, 0, 1, 5, 2, 3]]) zoomify_filename = os.path.join(image_dir, 'zoomify.tif') img_min, img_max = image_range(z_exp_img) if img_min == img_max: zoomify_image = z_exp_img #At least it won't crash else: zoomify_image = stretch_image(z_exp_img, img_min, img_max, 'byte') save_image(zoomify_image, zoomify_filename) zoomify_name = os.path.join(image_dir, 'zoomify') voxel_globe.ingest.payload.tools.zoomify_image( zoomify_filename, zoomify_name) img = voxel_globe.meta.models.Image( name="Height Map %s (%s)" % (voxel_world.name, voxel_world.id), image_width=cols, image_height=rows, number_bands=1, pixel_format='f', file_format='zoom', service_id=self.request.id) img.filename_path = original_filename img.save() image_set = models.ImageSet.objects.get_or_create( name="Height Maps", defaults={"_attributes": '{"autogen":true}'})[0] image_set.images.add(img) gsd = scene.description['voxelLength'] camera_center = ((x0 + x1) / 2, (y0 + y1) / 2, z1 + 10000) d = z1 - z0 + 10000 k = np.eye(3) k[0, 2] = cols / 2 k[1, 2] = rows / 2 k[0, 0] = k[1, 1] = d / gsd r = np.eye(3) r[0, 0] = -1 t = -r.T.dot(camera_center) camera = voxel_globe.tools.camera.save_krt(self.request.id, img, k, r, t, voxel_world.origin) camera_set=voxel_globe.meta.models.CameraSet(\ name="Height Map %s (%s)" % (voxel_world.name, voxel_world.id), \ images=image_set, service_id=self.request.id) camera_set.save() camera_set.cameras.add(camera)