Ejemplo n.º 1
0
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()
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
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))
Ejemplo n.º 4
0
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()
Ejemplo n.º 5
0
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()
Ejemplo n.º 6
0
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()
Ejemplo n.º 7
0
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()
Ejemplo n.º 8
0
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()
Ejemplo n.º 9
0
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)
Ejemplo n.º 10
0
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}
Ejemplo n.º 11
0
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)
Ejemplo n.º 12
0
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()
Ejemplo n.º 13
0
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)
Ejemplo n.º 14
0
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}
Ejemplo n.º 15
0
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()
Ejemplo n.º 16
0
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)
Ejemplo n.º 17
0
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();
Ejemplo n.º 18
0
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;
Ejemplo n.º 19
0
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}
Ejemplo n.º 20
0
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
Ejemplo n.º 21
0
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)