Example #1
0
def camera_from_json(key, obj):
    """
    Read camera from a json object
    """
    pt = obj.get('projection_type', 'perspective')
    if pt == 'perspective':
        camera = types.PerspectiveCamera()
        camera.id = key
        camera.width = obj.get('width', 0)
        camera.height = obj.get('height', 0)
        camera.focal = obj['focal']
        camera.k1 = obj.get('k1', 0.0)
        camera.k2 = obj.get('k2', 0.0)
        camera.focal_prior = obj.get('focal_prior', camera.focal)
        camera.k1_prior = obj.get('k1_prior', camera.k1)
        camera.k2_prior = obj.get('k2_prior', camera.k2)
        return camera
    elif pt in ['equirectangular', 'spherical']:
        camera = types.SphericalCamera()
        camera.id = key
        camera.width = obj['width']
        camera.height = obj['height']
        return camera
    else:
        raise NotImplementedError
Example #2
0
def camera_from_exif_metadata(metadata, data):
    '''
    Create a camera object from exif metadata
    '''
    pt = metadata.get('projection_type', 'perspective')
    if pt == 'perspective':
        calib = (hard_coded_calibration(metadata)
                 or focal_ratio_calibration(metadata)
                 or default_calibration(data))
        camera = types.PerspectiveCamera()
        camera.id = metadata['camera']
        camera.width = metadata['width']
        camera.height = metadata['height']
        camera.projection_type = metadata.get('projection_type', 'perspective')
        camera.focal = calib['focal']
        camera.k1 = calib['k1']
        camera.k2 = calib['k2']
        camera.focal_prior = calib['focal']
        camera.k1_prior = calib['k1']
        camera.k2_prior = calib['k2']
        return camera
    elif pt in ['equirectangular', 'spherical']:
        camera = types.SphericalCamera()
        camera.id = metadata['camera']
        camera.width = metadata['width']
        camera.height = metadata['height']
        return camera
    else:
        raise ValueError("Unknown projection type: {}".format(pt))
Example #3
0
def camera_from_exif_metadata(metadata, data):
    '''
    Create a camera object from exif metadata
    '''
    pt = metadata.get('projection_type', 'perspective').lower()
    if pt == 'perspective':
        calib = (hard_coded_calibration(metadata)
                 or focal_ratio_calibration(metadata)
                 or default_calibration(data))
        camera = types.PerspectiveCamera()
        camera.id = metadata['camera']
        camera.width = metadata['width']
        camera.height = metadata['height']
        camera.projection_type = pt
        camera.focal = calib['focal']
        camera.k1 = calib['k1']
        camera.k2 = calib['k2']
        return camera
    elif pt == 'brown':
        calib = (hard_coded_calibration(metadata)
                 or focal_xy_calibration(metadata)
                 or default_calibration(data))
        camera = types.BrownPerspectiveCamera()
        camera.id = metadata['camera']
        camera.width = metadata['width']
        camera.height = metadata['height']
        camera.projection_type = pt
        camera.focal_x = calib['focal_x']
        camera.focal_y = calib['focal_y']
        camera.c_x = calib['c_x']
        camera.c_y = calib['c_y']
        camera.k1 = calib['k1']
        camera.k2 = calib['k2']
        camera.p1 = calib['p1']
        camera.p2 = calib['p2']
        camera.k3 = calib['k3']
        return camera
    elif pt == 'fisheye':
        calib = (hard_coded_calibration(metadata)
                 or focal_ratio_calibration(metadata)
                 or default_calibration(data))
        camera = types.FisheyeCamera()
        camera.id = metadata['camera']
        camera.width = metadata['width']
        camera.height = metadata['height']
        camera.projection_type = pt
        camera.focal = calib['focal']
        camera.k1 = calib['k1']
        camera.k2 = calib['k2']
        return camera
    elif pt in ['equirectangular', 'spherical']:
        camera = types.SphericalCamera()
        camera.id = metadata['camera']
        camera.width = metadata['width']
        camera.height = metadata['height']
        return camera
    else:
        raise ValueError("Unknown projection type: {}".format(pt))
Example #4
0
def test_spherical_camera_projection():
    """Test spherical projection--backprojection loop."""
    camera = types.SphericalCamera()
    camera.width = 800
    camera.height = 600
    pixel = [0.1, 0.2]
    bearing = camera.pixel_bearing(pixel)
    projected = camera.project(bearing)
    assert np.allclose(pixel, projected)
Example #5
0
def camera_from_json(key, obj):
    """
    Read camera from a json object
    """
    pt = obj.get('projection_type', 'perspective')
    if pt == 'perspective':
        camera = types.PerspectiveCamera()
        camera.id = key
        camera.width = obj.get('width', 0)
        camera.height = obj.get('height', 0)
        camera.focal = obj['focal']
        camera.k1 = obj.get('k1', 0.0)
        camera.k2 = obj.get('k2', 0.0)
        return camera
    if pt == 'brown':
        camera = types.BrownPerspectiveCamera()
        camera.id = key
        camera.width = obj.get('width', 0)
        camera.height = obj.get('height', 0)
        camera.focal_x = obj['focal_x']
        camera.focal_y = obj['focal_y']
        camera.c_x = obj.get('c_x', 0.0)
        camera.c_y = obj.get('c_y', 0.0)
        camera.k1 = obj.get('k1', 0.0)
        camera.k2 = obj.get('k2', 0.0)
        camera.p1 = obj.get('p1', 0.0)
        camera.p2 = obj.get('p2', 0.0)
        camera.k3 = obj.get('k3', 0.0)
        return camera
    elif pt == 'fisheye':
        camera = types.FisheyeCamera()
        camera.id = key
        camera.width = obj.get('width', 0)
        camera.height = obj.get('height', 0)
        camera.focal = obj['focal']
        camera.k1 = obj.get('k1', 0.0)
        camera.k2 = obj.get('k2', 0.0)
        return camera
    elif pt == 'dual':
        camera = types.DualCamera()
        camera.id = key
        camera.width = obj.get('width', 0)
        camera.height = obj.get('height', 0)
        camera.focal = obj['focal']
        camera.k1 = obj.get('k1', 0.0)
        camera.k2 = obj.get('k2', 0.0)
        camera.transition = obj.get('transition', 0.5)
        return camera
    elif pt in ['equirectangular', 'spherical']:
        camera = types.SphericalCamera()
        camera.id = key
        camera.width = obj['width']
        camera.height = obj['height']
        return camera
    else:
        raise NotImplementedError
Example #6
0
    def convert_points(self, p_unsorted, f_unsorted, c_unsorted):
        image_camera_model = types.SphericalCamera()
        image_camera_model.id = "v2 nctech pulsar 11000 5500 equirectangular 0.1666"
        image_camera_model.width = 11000
        image_camera_model.height = 5500

        if len(p_unsorted) > 0:
            # Mask pixels that are out of valid image bounds before converting to equirectangular image coordinates

            bearings = image_camera_model.unfolded_pixel_bearings(
                p_unsorted[:, :2])

            p_mask = np.array([point is not None for point in bearings])

            p_unsorted = p_unsorted[p_mask]
            f_unsorted = f_unsorted[p_mask]
            c_unsorted = c_unsorted[p_mask]

            p_unsorted[:, :
                       2] = self.unfolded_cube_to_equi_normalized_image_coordinates(
                           p_unsorted[:, :2], image_camera_model)
            return p_unsorted, f_unsorted, c_unsorted
def _get_spherical_camera():
    camera = types.SphericalCamera()
    camera.width = 800
    camera.height = 600
    return camera
Example #8
0
def _get_spherical_camera():
    camera = types.SphericalCamera()
    camera.width = 800
    camera.height = 600
    camera_cpp = pygeometry.Camera.create_spherical()
    return camera, camera_cpp
Example #9
0
    def convert_image(self, image, img, max_size):
        image_camera_model = types.SphericalCamera()
        image_camera_model.id = "v2 nctech pulsar 11000 5500 equirectangular 0.1666"
        image_camera_model.width = 11000
        image_camera_model.height = 5500

        undist_tile_size = max_size // 4

        undist_img = np.zeros((max_size // 2, max_size, 3), np.uint8)
        undist_mask = np.full((max_size // 2, max_size, 1), 255, np.uint8)

        undist_mask[undist_tile_size:2 * undist_tile_size,
                    2 * undist_tile_size:3 * undist_tile_size] = 0
        undist_mask[undist_tile_size:2 * undist_tile_size,
                    undist_tile_size:2 * undist_tile_size] = 0

        spherical_shot = types.Shot()
        spherical_shot.pose = types.Pose()
        spherical_shot.id = image
        spherical_shot.camera = image_camera_model

        perspective_shots = undistort.perspective_views_of_a_panorama(
            spherical_shot, undist_tile_size)

        for subshot in perspective_shots:

            undistorted = undistort.render_perspective_view_of_a_panorama(
                img, spherical_shot, subshot)

            subshot_id_prefix = '{}_perspective_view_'.format(
                spherical_shot.id)

            subshot_name = subshot.id[
                len(subshot_id_prefix):] if subshot.id.startswith(
                    subshot_id_prefix) else subshot.id
            (subshot_name, ext) = os.path.splitext(subshot_name)

            if subshot_name == 'front':
                undist_img[:undist_tile_size, :undist_tile_size] = undistorted
                # print( 'front')
            elif subshot_name == 'left':
                undist_img[:undist_tile_size,
                           undist_tile_size:2 * undist_tile_size] = undistorted
                # print( 'left')
            elif subshot_name == 'back':
                undist_img[:undist_tile_size, 2 * undist_tile_size:3 *
                           undist_tile_size] = undistorted
                # print( 'back')
            elif subshot_name == 'right':
                undist_img[:undist_tile_size, 3 * undist_tile_size:4 *
                           undist_tile_size] = undistorted
                # print( 'right')
            elif subshot_name == 'top':
                undist_img[undist_tile_size:2 * undist_tile_size, 3 *
                           undist_tile_size:4 * undist_tile_size] = undistorted
                # print( 'top')
            elif subshot_name == 'bottom':
                undist_img[undist_tile_size:2 *
                           undist_tile_size, :undist_tile_size] = undistorted
                # print( 'bottom')

        # data.save_undistorted_image(subshot.id, undist_img)
        return undist_img
Example #10
0
def create_full_mosaic(args):

    log.setup()

    shot, data = args
    logger.info('Creating full mosaic for image {}'.format( shot.id ) )

    config = data.config

    start = timer()

    projection_type = shot.camera.projection_type
    
    r_map_x = None
    r_map_y = None
    dst_mask_x = None
    dst_mask_y = None

    if projection_type in ['perspective', 'brown', 'fisheye']:

        img = data.load_image( shot.id )
        
        camera = types.SphericalCamera()
        camera.id = "Spherical Projection Camera"
        
        # Determine the correct mosaic size from the focal length of the camera
        # Limit this to a maximum of a 16K image which is the highest resolution
        # currently supported by PVR.
        
        K_pix = shot.camera.get_K_in_pixel_coordinates()
        
        camera.height = int( np.clip( math.pi*K_pix[0,0], 0, 8192 ) )
        camera.width = int( np.clip( 2*math.pi*K_pix[0,0], 0, 16384 ) )
        
        shot_cam = shot.camera
    
        # Project shot's pixels to the spherical mosaic image
    
        src_shape = ( shot_cam.height, shot_cam.width )
        src_y, src_x = np.indices( src_shape ).astype( np.float32 )
        
        src_pixels_denormalized = np.column_stack( [ src_x.ravel(), src_y.ravel() ] )

        src_pixels = features.normalized_image_coordinates( src_pixels_denormalized, shot_cam.width, shot_cam.height )

        # Convert to bearings
        
        src_bearings = shot_cam.pixel_bearing_many( src_pixels )
    
        # Project to spherical mosaic pixels
        
        dst_x, dst_y = camera.project( ( src_bearings[:, 0],
                                         src_bearings[:, 1],
                                         src_bearings[:, 2] ) )
                                            
        dst_pixels = np.column_stack( [ dst_x.ravel(), dst_y.ravel() ] )
        
        interp_mode = data.config.get( 'full_mosaic_proj_interpolation', 'linear' )
        
        if interp_mode == 'linear':
            
            # Snap to pixel centers to generate a projection index mask. This will be slower then finding 
            # the ROI using the projected border but it's far easier and covers wrap around and the poles with
            # minimal effort. It will also probably be more efficient when wrap around or crossing the poles does occur.
            
            dst_pixels_denormalized_int = features.denormalized_image_coordinates( dst_pixels, camera.width, camera.height ).astype( np.int32 )
            
            dst_pixels_snap = features.normalized_image_coordinates( dst_pixels_denormalized_int.astype( np.float32 ), camera.width, camera.height )
            
            dst_bearings_re = camera.pixel_bearing_many( dst_pixels_snap )
            
            # Project mosaic pixel center bearings back into the source image
            
            src_re_x, src_re_y = shot_cam.project( ( dst_bearings_re[:, 0],
                                                     dst_bearings_re[:, 1],
                                                     dst_bearings_re[:, 2] ) )
                                                     
            src_re_pixels = np.column_stack( [ src_re_x.ravel(), src_re_y.ravel() ] )
            
            src_re_denormalized = features.denormalized_image_coordinates( src_re_pixels, shot_cam.width, shot_cam.height )
            
            mosaic_img = initialize_mosaic_image( camera.width, camera.height, img )
            
            # Reshape arrays for cv.remap efficiency reasons and due to the SHRT_MAX limit of array size.
            # Another option is to process in chunks of linear array of shize SHRT_MAX. However, this 
            # approach was probably 4x slower.
            
            x = src_re_denormalized[:, 0].reshape( src_x.shape ).astype(np.float32)
            y = src_re_denormalized[:, 1].reshape( src_y.shape ).astype(np.float32)
            
            r_map_x = x
            r_map_y = y
            
            # Sample source imagery colors
            
            colors = cv2.remap( img, x, y, cv2.INTER_LINEAR , borderMode=cv2.BORDER_CONSTANT )
            
            dst_mask_y = dst_pixels_denormalized_int[:, 1].reshape( src_y.shape )
            dst_mask_x = dst_pixels_denormalized_int[:, 0].reshape( src_x.shape )
            
            mosaic_img[ dst_mask_y, dst_mask_x ] = colors
            
            blend_projection_border(  mosaic_img, dst_mask_y, dst_mask_x )
            
            
            # Initialize blurring and alpha mask kernels
            
            # half_chunk_size = 75
            # border = 41
            
            # half_size = half_chunk_size + border
            
            # kernel_1d = cv2.getGaussianKernel( 2*half_chunk_size+1,  1.5*(0.3*((2*half_chunk_size+1-1)*0.5 - 1) + 0.8) , cv2.CV_32F )
            # kernel_1d/=kernel_1d[ half_chunk_size ]
            
            # half_kernel_1d = kernel_1d[ half_chunk_size : 2*half_chunk_size ]
            
            # alpha = np.zeros( ( 2*half_chunk_size, 2*half_chunk_size, 3 ), dtype = np.float32 ) #np.float32 uint8)
            
            # for y in range(0,2*half_chunk_size):
                # for x in range(0,2*half_chunk_size):
                    # yt = y - half_chunk_size
                    # xt = x - half_chunk_size
                    
                    # r = int( math.sqrt( yt*yt + xt*xt ) )
                    
                    # if r > half_chunk_size-1:
                        # r = half_chunk_size-1
                    
                    # kv = half_kernel_1d[r]
                    
                    # alpha[ y, x, 0] = alpha[ y, x, 1] = alpha[ y, x, 2] = kv
            
            
            # # Grab the indices of pixels along the projected image border and blend into the
            # # background with a gaussian blur and alpha map.
            
            # dst_mask_y_border = np.concatenate( [ dst_mask_y[ 0:,0 ], 
                                                  # dst_mask_y[ 0:, -1 ],
                                                  # dst_mask_y[ 0, 0: ],
                                                  # dst_mask_y[-1, 0: ] ] )
                            
            # dst_mask_x_border = np.concatenate( [ dst_mask_x[ 0:,0 ], 
                                                  # dst_mask_x[ 0:, -1 ],
                                                  # dst_mask_x[ 0, 0: ],
                                                  # dst_mask_x[-1, 0: ] ] )
            
            # dst_mask_border = np.column_stack( [ dst_mask_y_border, dst_mask_x_border ] )
            
            # #for y_ind in np.arange( 0, dst_mask_y.shape[0], 75 ):
            
            # for border_pix in dst_mask_border[::75]:
                
                # border_y = border_pix[0] #dst_mask_y[y_ind,0]
                # border_x = border_pix[1] #dst_mask_x[y_ind,0]
            
                # sub_img = mosaic_img[ border_y - half_size : border_y + half_size, border_x - half_size : border_x + half_size ].copy()
            
                # sub_rng = border + 2*half_chunk_size
            
                # sub_img[border:sub_rng,border:sub_rng] = cv2.GaussianBlur( sub_img[border:sub_rng,border:sub_rng], (81,81), 0 )
            
                # mosaic_img[ border_y - half_chunk_size : border_y + half_chunk_size, border_x - half_chunk_size : border_x + half_chunk_size ] = \
                    # np.multiply( sub_img[border:sub_rng,border:sub_rng].astype( np.float32 ), alpha ) + \
                    # np.multiply( mosaic_img[ border_y - half_chunk_size : border_y + half_chunk_size, border_x - half_chunk_size : border_x + half_chunk_size ].astype( np.float32 ), 1 - alpha )
                
            #cv2.imwrite('c:\\alpha.png', alpha)
            
            #mosaic_img[ border_y - half_chunk_size : border_y + half_chunk_size, border_x - half_chunk_size : border_x + half_chunk_size ] = alpha
            
            #mosaic_img[ border_y - half_chunk_size : border_y + half_chunk_size, border_x - half_chunk_size : border_x + half_chunk_size ] = sub_img[border:sub_rng,border:sub_rng]
            
        elif interp_mode == 'nearest':

            # Implementing nearest this way rather than just changing the interpolation function of cv2.remap above
            # will be more efficient because we'll avoid the reprojection back to the source image and sample it directly
            # using our index mask.

            dst_pixels_denormalized = features.denormalized_image_coordinates( dst_pixels, camera.width, camera.height )

            # Create a full equirectangular index image with all zero indices for x and y

            fdst_y, fdst_x = np.zeros( ( 2, camera.height, camera.width ) ).astype( np.float32 )
            
            # Use the projected indices to swap in the source image indices.
            
            x = dst_pixels_denormalized[..., 0].astype(np.int32)
            y = dst_pixels_denormalized[..., 1].astype(np.int32)
            
            fdst_x[ y, x ] = src_pixels_denormalized[...,0]
            fdst_y[ y, x ] = src_pixels_denormalized[...,1]
            
            r_map_x = fdst_x
            r_map_y = fdst_y
            
            mosaic_img = cv2.remap( img, fdst_x, fdst_y, cv2.INTER_NEAREST, borderMode=cv2.BORDER_CONSTANT )
        
        else:
            raise NotImplementedError( 'Interpolation type not supported: {}'.format( interp_mode ) )
            
    data.save_full_mosaic_image( os.path.splitext( shot.id )[0], mosaic_img )

    end = timer()
    
    report = {
        "image": shot.id,
        "wall_time": end - start,
    }
    
    data.save_report( io.json_dumps(report),
                      'full_mosaic_reprojection/{}.json'.format( shot.id ) )
                      
    return ( r_map_x, r_map_y, dst_mask_x, dst_mask_y )
Example #11
0
def create_full_mosaic_precom_maps( args ):

    log.setup()

    shot, r_map_x, r_map_y, dst_mask_x, dst_mask_y, data = args
    logger.info('Creating full mosaic for image {}'.format( shot.id ) )

    config = data.config

    start = timer()

    projection_type = shot.camera.projection_type

    if projection_type in ['perspective', 'brown', 'fisheye']:

        img = data.load_image( shot.id )
        
        camera = types.SphericalCamera()
        camera.id = "Spherical Projection Camera"
        
        # Determine the correct mosaic size from the focal length of the camera
        # Limit this to a maximum of a 16K image which is the highest resolution
        # currently supported by PVR.
        
        K_pix = shot.camera.get_K_in_pixel_coordinates()
        
        camera.height = int( np.clip( math.pi*K_pix[0,0], 0, 8192 ) )
        camera.width = int( np.clip( 2*math.pi*K_pix[0,0], 0, 16384 ) )
        
        interp_mode = data.config.get( 'full_mosaic_proj_interpolation', 'linear' )
        
        if interp_mode == 'linear':
        
            mosaic_img = initialize_mosaic_image( camera.width, camera.height, img )
            
            # Sample source imagery colors
            
            colors = cv2.remap( img, r_map_x, r_map_y, cv2.INTER_LINEAR , borderMode=cv2.BORDER_CONSTANT )
            
            mosaic_img[ dst_mask_y, dst_mask_x ] = colors
            
            blend_projection_border( mosaic_img, dst_mask_y, dst_mask_x )

        elif interp_mode == 'nearest':
            
            mosaic_img = cv2.remap( img, r_map_x, r_map_y, cv2.INTER_NEAREST, borderMode=cv2.BORDER_CONSTANT )
        
        else:
            raise NotImplementedError( 'Interpolation type not supported: {}'.format( interp_mode ) )
            
    data.save_full_mosaic_image( os.path.splitext( shot.id )[0], mosaic_img )

    end = timer()
    
    report = {
        "image": shot.id,
        "wall_time": end - start,
    }
    
    data.save_report( io.json_dumps(report),
                      'full_mosaic_reprojection/{}.json'.format( shot.id ) )