예제 #1
0
def plot_matches(im1, im2, p1, p2):
    h1, w1, c = im1.shape
    h2, w2, c = im2.shape
    image = np.zeros((max(h1, h2), w1 + w2, 3), dtype=im1.dtype)
    image[0:h1, 0:w1, :] = im1
    image[0:h2, w1:(w1 + w2), :] = im2

    p1 = features.denormalized_image_coordinates(p1, w1, h1)
    p2 = features.denormalized_image_coordinates(p2, w2, h2)
    pl.imshow(image)
    for a, b in zip(p1, p2):
        pl.plot([a[0], b[0] + w1], [a[1], b[1]], "c")

    pl.plot(p1[:, 0], p1[:, 1], "ob")
    pl.plot(p2[:, 0] + w1, p2[:, 1], "ob")
예제 #2
0
def render_perspective_view_of_a_panorama(image, panoshot, perspectiveshot):
    """Render a perspective view of a panorama."""
    # Get destination pixel coordinates
    dst_shape = (perspectiveshot.camera.height, perspectiveshot.camera.width)
    dst_y, dst_x = np.indices(dst_shape).astype(np.float32)
    dst_pixels_denormalized = np.column_stack([dst_x.ravel(), dst_y.ravel()])

    dst_pixels = features.normalized_image_coordinates(
        dst_pixels_denormalized, perspectiveshot.camera.width,
        perspectiveshot.camera.height)

    # Convert to bearing
    dst_bearings = perspectiveshot.camera.pixel_bearings(dst_pixels)

    # Rotate to panorama reference frame
    rotation = np.dot(panoshot.pose.get_rotation_matrix(),
                      perspectiveshot.pose.get_rotation_matrix().T)
    rotated_bearings = np.dot(dst_bearings, rotation.T)

    # Project to panorama pixels
    src_x, src_y = panoshot.camera.project(
        (rotated_bearings[:, 0], rotated_bearings[:, 1], rotated_bearings[:,
                                                                          2]))
    src_pixels = np.column_stack([src_x.ravel(), src_y.ravel()])

    src_pixels_denormalized = features.denormalized_image_coordinates(
        src_pixels, image.shape[1], image.shape[0])

    # Sample color
    colors = cv2.remap(image, src_pixels_denormalized[:, 0].astype(np.float32),
                       src_pixels_denormalized[:, 1].astype(np.float32),
                       cv2.INTER_LINEAR)
    colors.shape = dst_shape + (-1, )
    return colors
예제 #3
0
def render_perspective_view_of_a_panorama(image, panoshot, perspectiveshot,
                                          interpolation=cv2.INTER_LINEAR,
                                          borderMode=cv2.BORDER_WRAP):
    """Render a perspective view of a panorama."""
    # Get destination pixel coordinates
    dst_shape = (perspectiveshot.camera.height, perspectiveshot.camera.width)
    dst_y, dst_x = np.indices(dst_shape).astype(np.float32)
    dst_pixels_denormalized = np.column_stack([dst_x.ravel(), dst_y.ravel()])

    dst_pixels = features.normalized_image_coordinates(
        dst_pixels_denormalized,
        perspectiveshot.camera.width,
        perspectiveshot.camera.height)

    # Convert to bearing
    dst_bearings = perspectiveshot.camera.pixel_bearing_many(dst_pixels)

    # Rotate to panorama reference frame
    rotation = np.dot(panoshot.pose.get_rotation_matrix(),
                      perspectiveshot.pose.get_rotation_matrix().T)
    rotated_bearings = np.dot(dst_bearings, rotation.T)

    # Project to panorama pixels
    src_pixels = panoshot.camera.project_many(rotated_bearings)
    src_pixels_denormalized = features.denormalized_image_coordinates(
        src_pixels, image.shape[1], image.shape[0])

    src_pixels_denormalized.shape = dst_shape + (2,)

    # Sample color
    x = src_pixels_denormalized[..., 0].astype(np.float32)
    y = src_pixels_denormalized[..., 1].astype(np.float32)
    colors = cv2.remap(image, x, y, interpolation, borderMode=borderMode)

    return colors
예제 #4
0
파일: GUI.py 프로젝트: ziweiWWANG/OpenSfM
 def show_epipolar_lines(self, main_image_idx):
     if len(self.views) > 2:
         raise NotImplementedError("Not implemented yet for >2 views")
     img1 = self.views[0].current_image
     img2 = self.views[1].current_image
     img1_size = self.database.get_image_size(img1)
     img2_size = self.database.get_image_size(img2)
     matched_points = self.database.get_visible_points_coords(
         self.views[main_image_idx].current_image)
     matched_points_coords = convert_tuple_cords_to_list(matched_points)
     matched_points_coords = features.normalized_image_coordinates(
         matched_points_coords, img1_size[1], img1_size[0])
     color_idx = 0
     for point_idx, point in enumerate(matched_points_coords):
         image_pair = [img1, img2]
         line = calc_epipol_line(point, image_pair,
                                 self.database.get_path(), main_image_idx)
         denormalized_lines = features.denormalized_image_coordinates(
             line, img2_size[1], img2_size[0])
         for line_segment in denormalized_lines:
             circle = mpatches.Circle(
                 (line_segment[0], line_segment[1]),
                 3,
                 color=distinct_colors[divmod(
                     hash(list(matched_points.keys())[point_idx]), 19)[1]])
             self.views[main_image_idx].plt_artists.append(circle)
             self.views[not main_image_idx].subplot.add_artist(circle)
         color_idx = color_idx + 1
     self.views[not main_image_idx].figure.canvas.draw_idle()
예제 #5
0
def paint_reconstruction(data, graph, reconstruction):
    to_paint = defaultdict(list)
    to_paint_track = defaultdict(list)
    for track in reconstruction['points']:
        for shot in graph[track]:
            to_paint[shot].append(graph[track][shot]['feature'])
            to_paint_track[shot].append(track)

    track_colors = {track: np.zeros(3) for track in reconstruction['points']}
    track_sum = {track: 0 for track in reconstruction['points']}

    for shot in to_paint:
        points = np.array(to_paint[shot])
        tracks = to_paint_track[shot]
        im = data.image_as_array(shot)
        pixels = features.denormalized_image_coordinates(
            points, im.shape[1], im.shape[0]).astype(int)
        colors = im[pixels[:, 1], pixels[:, 0]]
        for track, color in zip(tracks, colors):
            track_colors[track] += color
            track_sum[track] += 1

    for track in reconstruction['points']:
        c = track_colors[track] / track_sum[track]
        reconstruction['points'][track]['color'] = list(c)
예제 #6
0
 def init_points(self, points):
     for point in points:
         point_id, observations = point['id'], point['observations']
         for observation in observations:
             h, w = self.get_image_size(observation["shot_id"])
             observation["projection"] = features.denormalized_image_coordinates(
                 np.array([observation["projection"]]), w, h)[0]
         self.points[point_id] = observations
예제 #7
0
def project_pointcloud_save_depth(udata, urec, points, shot_id, max_sz):
    # Project points to the undistorted image
    shot = urec.shots[shot_id]
    w, h = shot.camera.width, shot.camera.height
    large = max(w, h)
    if large > max_sz:
        ar = w / h
        if w > h:
            w = max_sz
            h = int(w / ar)
        else:
            h = max_sz
            w = int(ar * h)

    points_2d = shot.project_many(points)

    pixel_coords = features.denormalized_image_coordinates(points_2d, w,
                                                           h).astype(int)
    # Filter out points that fall out of the image
    # <<< aren't we supposed to have points that are visible from this image only??!?!
    mask = np.ones(pixel_coords.shape[0], dtype=bool)
    mask[pixel_coords[:, 0] < 0] = 0
    mask[pixel_coords[:, 1] < 0] = 0
    mask[pixel_coords[:, 0] >= w] = 0
    mask[pixel_coords[:, 1] >= h] = 0
    pixel_coords = pixel_coords[mask]

    # Compute the depth
    distances = np.linalg.norm(points - shot.pose.get_origin(), axis=1)
    viewing_angles = np.arctan2(np.linalg.norm(points_2d, axis=1),
                                shot.camera.focal)
    depths = distances * np.cos(viewing_angles)
    depths[depths > udata.config["depthmap_max_depth"]] = 0

    # Create depth image
    depth_image = np.zeros([h, w])
    depth_image[pixel_coords[:, 1], pixel_coords[:, 0]] = depths[mask]

    # Save numpy
    filepath = Path(udata.depthmap_file(shot_id, "clean.npz"))
    filepath.parent.mkdir(exist_ok=True, parents=True)
    np.savez_compressed(filepath,
                        depth=depth_image,
                        plane=np.zeros(1),
                        score=np.zeros(1))

    # Save jpg for visualization
    import matplotlib.pyplot as plt

    fig = plt.figure()
    rgb, sm = depth_colormap(depth_image)
    plt.imshow(rgb)
    small_colorbar(plt.gca(), mappable=sm)
    filepath = Path(
        udata.data_path) / "plot_depthmaps" / "{}.png".format(shot_id)
    filepath.parent.mkdir(exist_ok=True, parents=True)
    plt.savefig(filepath, dpi=300)
    plt.close(fig)
예제 #8
0
def export_features(data, db, images_map):
    features_map = {}
    for image in data.images():
        width = data.load_exif(image)['width']
        height = data.load_exif(image)['height']
        feat, _, _ = data.load_features(image)
        feat = features.denormalized_image_coordinates(feat, width, height)
        features_map[image] = feat
        db.add_keypoints(images_map[image], feat)
    return features_map
예제 #9
0
 def gcp_to_pixel_coordinates(self, x: float,
                              y: float) -> Tuple[float, float]:
     """
     Transforms from normalized coordinates (in the whole geotiff) to
     pixels (in the viewing window)
     """
     h, w = self.image_manager.get_image_size(self.current_image)
     px = features.denormalized_image_coordinates(np.array([[x, y]]), w,
                                                  h)[0]
     x = px[0] - self.image_window.col_off
     y = px[1] - self.image_window.row_off
     return [x, y]
예제 #10
0
    def load_gcp_reprojections(self, filename):
        with open(filename, 'r') as f:
            d = json.load(f)

        for gcp_id in d:
            for shot_id in d[gcp_id]:
                h, w = self.get_image_size(shot_id)
                reproj = d[gcp_id][shot_id]['reprojection']
                reproj = features.denormalized_image_coordinates(np.array([reproj]), w, h)[0]
                d[gcp_id][shot_id]['reprojection'] = reproj

        self.gcp_reprojections = d
예제 #11
0
    def gcp_to_pixel_coordinates(self, x: float,
                                 y: float) -> Tuple[float, float]:
        """
        Transforms from normalized coordinates to pixels

        The view displays images at a reduced resolution for speed. We use the image
        manager to obtain the reduced coordinates to use for de-normalization.
        """
        h, w = self.image_manager.get_image_size(self.current_image)
        px = features.denormalized_image_coordinates(np.array([[x, y]]), w,
                                                     h)[0]
        return self.rotate_point(px[0], px[1], h, w, reverse=False)
예제 #12
0
파일: dataset.py 프로젝트: saengphet/GAAS
 def save_features_json(self, filepath, points, image):
     img = cv2.imread(self._image_file(image))
     print('image:', image)
     print('img:', img)
     print('image.shape', img.shape)
     h, w, d = img.shape
     denormed_points = features.denormalized_image_coordinates(points, w, h)
     _out = {}
     for i, item in enumerate(denormed_points):
         _out[str(i)] = list(map(str, list(item)))
     print(_out)
     with open(filepath + ".json", "w") as f:
         json.dump(_out, f, indent=4)
예제 #13
0
def export_features(data, db, images_map):
    features_map = {}
    for image in data.images():
        width = data.load_exif(image)["width"]
        height = data.load_exif(image)["height"]
        features_data = data.load_features(image)
        if not features_data:
            continue
        feat = features.denormalized_image_coordinates(features_data.points,
                                                       width, height)
        features_map[image] = feat
        db.add_keypoints(images_map[image], feat)
    return features_map
def check_a_point(point, mask):
    # assert that the point is one dimensional
    points = np.array(point)
    points = points[np.newaxis, 0:2]
    points = features.denormalized_image_coordinates(points, mask.shape[1],
                                                     mask.shape[0])
    p = points[0, :]
    if mask[int(p[1]), int(p[0])] == 0:
        # then not include this point
        return 0
    else:
        # include this point
        return 1
예제 #15
0
 def gcp_to_pixel_coordinates(self, x: float,
                              y: float) -> Tuple[float, float]:
     """
     Transforms from normalized coordinates (in the whole geotiff) to
     pixels (in the viewing window)
     """
     h, w = self.image_manager.get_image_size(self.current_image)
     px = features.denormalized_image_coordinates(np.array([[x, y]]), w,
                                                  h)[0]
     # pyre-fixme[16]: `OrthoPhotoView` has no attribute `image_window`.
     x = px[0] - self.image_window.col_off
     y = px[1] - self.image_window.row_off
     # pyre-fixme[7]: Expected `Tuple[float, float]` but got `List[typing.Any]`.
     return [x, y]
예제 #16
0
    def filter_by_seg(self, image, points, func, relative_seg_path):
        # return a list of true or false indicating whether the point survive after mask
        seg = self.seg_as_array(image, relative_seg_path)

        points = points[:, 0:2]
        points = features.denormalized_image_coordinates(
            points, seg.shape[1], seg.shape[0])

        ans = []
        for p in points:
            if func(seg[int(p[1]), int(p[0])]):
                ans.append(True)
            else:
                ans.append(False)
        return np.array(ans)
예제 #17
0
 def show_epipolar_lines(self, main_image_idx):
     img1_size = self.database.get_image_size(self.curr_images[0])
     img2_size = self.database.get_image_size(self.curr_images[1])
     matched_points = self.database.get_visible_points_coords(self.curr_images[main_image_idx])
     matched_points_coords = convert_tuple_cords_to_list(matched_points)
     matched_points_coords = features.normalized_image_coordinates(matched_points_coords, img1_size[1], img1_size[0])
     color_idx = 0
     for point_idx, point in enumerate(matched_points_coords):
         line = calc_epipol_line(point, self.curr_images, self.database.get_path(), main_image_idx)
         denormalized_lines = features.denormalized_image_coordinates(line, img2_size[1], img2_size[0])
         for line_segment in denormalized_lines:
             circle = mpatches.Circle((line_segment[0], line_segment[1]), 3,
                                      color=distinct_colors[divmod(hash(list(matched_points.keys())[point_idx]), 19)[1]])
             self.plt_artists[main_image_idx].append(circle)
             self.subplots[not main_image_idx].add_artist(circle)
         color_idx = color_idx + 1
     self.figures[not main_image_idx].canvas.draw_idle()
예제 #18
0
def display_features(file_path, filename, config, n_fts):
    """
    Inputs:
        file_path: where the images, features are stored
        config: SfM configuration info
        n_fts: display every n features
    Outputs:
        will display the image along with every n_fts on it
    """
    fts = features.load_features(file_path + "features/" + filename, config)
    points = fts[0]
    img_name = filename[:-13]
    img = cv2.imread(file_path + "images/" + img_name)
    plt.imshow(img)
    denorm_pts = features.denormalized_image_coordinates(points, 1920, 1080)
    for pt_i, (x, y) in enumerate(denorm_pts):
        if (pt_i % n_fts) == 0:
            plt.scatter(x, y)
    plt.show()
예제 #19
0
def render_perspective_view_of_a_panorama(image, panoshot, perspectiveshot,
                                          interpolation=cv2.INTER_LINEAR):
    """Render a perspective view of a panorama."""
    # Get destination pixel coordinates
    dst_shape = (perspectiveshot.camera.height, perspectiveshot.camera.width)
    dst_y, dst_x = np.indices(dst_shape).astype(np.float32)
    dst_pixels_denormalized = np.column_stack([dst_x.ravel(), dst_y.ravel()])

    dst_pixels = features.normalized_image_coordinates(
        dst_pixels_denormalized,
        perspectiveshot.camera.width,
        perspectiveshot.camera.height)

    # Convert to bearing
    dst_bearings = perspectiveshot.camera.pixel_bearing_many(dst_pixels)

    # Rotate to panorama reference frame
    rotation = np.dot(panoshot.pose.get_rotation_matrix(),
                      perspectiveshot.pose.get_rotation_matrix().T)
    rotated_bearings = np.dot(dst_bearings, rotation.T)

    # Project to panorama pixels
    src_x, src_y = panoshot.camera.project((rotated_bearings[:, 0],
                                            rotated_bearings[:, 1],
                                            rotated_bearings[:, 2]))
    src_pixels = np.column_stack([src_x.ravel(), src_y.ravel()])

    src_pixels_denormalized = features.denormalized_image_coordinates(
        src_pixels, image.shape[1], image.shape[0])

    src_pixels_denormalized.shape = dst_shape + (2,)

    # Sample color
    x = src_pixels_denormalized[..., 0].astype(np.float32)
    y = src_pixels_denormalized[..., 1].astype(np.float32)
    colors = cv2.remap(image, x, y, interpolation, borderMode=cv2.BORDER_WRAP)

    return colors
예제 #20
0
def getPointColorFromReconstruction(reconstruction, image_dir, point):
    label_list = []
    for shot_id in reconstruction.shots:
        shot = reconstruction.shots[shot_id]
        norm_projection = shot.project(point)
        image_path = os.path.join(image_dir,
                                  os.path.splitext(shot.id)[0] + ".png")
        # print("Projecting onto ", image_path)
        image = cv2.imread(image_path)
        pt_im = features.denormalized_image_coordinates(
            np.array(norm_projection).reshape(-1, 2), image.shape[1],
            image.shape[0])[0]
        # print(pt_im)
        row = int(pt_im[1])
        col = int(pt_im[0])
        if ((row in range(0, image.shape[0])
             and (col in range(0, image.shape[0])))):
            rgb = image[row, col]
            # print(rgb)
            if (np.all(rgb == np.array([98, 98, 98]))):
                rgb = 1
            elif (np.all(rgb == np.array([100, 100, 100]))):
                rgb = 1
            else:
                rgb = 2
            label_list.append(rgb)

    if (len(label_list) == 0):
        return None
    occurence_count = Counter(label_list)
    res = occurence_count.most_common(1)[0][0]
    if (res == 1):
        res = [0, 255, 255]
    else:
        res = [0, 0, 255]
    return res
예제 #21
0
def detect(args):
    image, tags, data = args
    logger.info('Extracting {} features for image {}'.format(
        data.feature_type().upper(), image))
    DEBUG = 0

    # check if features already exist
    if not data.feature_index_exists(image):

        mask = data.mask_as_array(image)
        if mask is not None:
            logger.info('Found mask to apply for image {}'.format(image))
        preemptive_max = data.config.get('preemptive_max', 200)
        p_unsorted, f_unsorted, c_unsorted = features.extract_features(
            data.image_as_array(image), data.config, mask)
        if len(p_unsorted) == 0:
            return

        #===== prune features in tags =====#
        if data.config.get('prune_features_on_tags', False):

            # setup
            img = cv2.imread(os.path.join(data.data_path, 'images', image))
            [height, width, _] = img.shape
            p_denorm = features.denormalized_image_coordinates(
                p_unsorted, width, height)

            # expand tag contour with grid points beyond unit square
            expn = 2.0
            gridpts = np.array(
                [[-expn, expn], [expn, expn], [expn, -expn], [-expn, -expn]],
                dtype='float32')

            # find features to prune
            rm_list = []
            for tag in tags:

                # contour from tag region
                contours = np.array(tag.corners)
                if DEBUG > 0:
                    for i in range(0, 3):
                        cv2.line(img, (tag.corners[i, 0].astype('int'),
                                       tag.corners[i, 1].astype('int')),
                                 (tag.corners[i + 1, 0].astype('int'),
                                  tag.corners[i + 1, 1].astype('int')),
                                 [0, 255, 0], 12)
                    cv2.line(img, (tag.corners[3, 0].astype('int'),
                                   tag.corners[3, 1].astype('int')),
                             (tag.corners[0, 0].astype('int'),
                              tag.corners[0, 1].astype('int')), [0, 255, 0],
                             12)

                # scale contour outward
                H = np.array(tag.homography, dtype='float32')
                contours_expanded = cv2.perspectiveTransform(
                    np.array([gridpts]), H)

                # for each point
                for pidx in range(0, len(p_unsorted)):

                    # point
                    pt = p_denorm[pidx, 0:2]

                    # point in contour
                    inout = cv2.pointPolygonTest(
                        contours_expanded.astype('int'), (pt[0], pt[1]), False)

                    # check result
                    if inout >= 0:
                        rm_list.append(pidx)

            # prune features
            p_unsorted = np.delete(p_unsorted, np.array(rm_list), axis=0)
            f_unsorted = np.delete(f_unsorted, np.array(rm_list), axis=0)
            c_unsorted = np.delete(c_unsorted, np.array(rm_list), axis=0)

            # debug
            if DEBUG > 0:
                p_denorm = np.delete(p_denorm, np.array(rm_list), axis=0)
                for pidx in range(0, len(p_denorm)):
                    pt = p_denorm[pidx, 0:2]
                    cv2.circle(img, (pt[0].astype('int'), pt[1].astype('int')),
                               5, [0, 0, 255], -1)

                cv2.namedWindow('ShowImage', cv2.WINDOW_NORMAL)
                height, width, channels = img.shape
                showw = max(752, width / 4)
                showh = max(480, height / 4)
                cv2.resizeWindow('ShowImage', showw, showh)
                cv2.imshow('ShowImage', img)
                cv2.waitKey(0)
        #===== prune features in tags =====#

        # sort for preemptive
        size = p_unsorted[:, 2]
        order = np.argsort(size)
        p_sorted = p_unsorted[order, :]
        f_sorted = f_unsorted[order, :]
        c_sorted = c_unsorted[order, :]
        p_pre = p_sorted[-preemptive_max:]
        f_pre = f_sorted[-preemptive_max:]

        # save
        data.save_features(image, p_sorted, f_sorted, c_sorted)
        data.save_preemptive_features(image, p_pre, f_pre)

        if data.config.get('matcher_type', 'FLANN') == 'FLANN':
            index = features.build_flann_index(f_sorted, data.config)
            data.save_feature_index(image, index)

    #===== tag features =====#
    if data.config.get('use_apriltags', False) or data.config.get(
            'use_arucotags', False) or data.config.get('use_chromatags',
                                                       False):

        # setup
        try:
            tags_all = data.load_tag_detection()
        except:
            return
        tags = tags_all[image]
        pt = []
        ft = []
        ct = []
        it = []
        imexif = data.load_exif(image)

        # for each tag in image
        for tag in tags:

            # normalize corners
            img = cv2.imread(os.path.join(data.data_path, 'images', image))
            [height, width, _] = img.shape
            #print 'width = ',str(imexif['width'])
            #print 'height= ',str(imexif['height'])
            #print 'width2= ',str(width)
            #print 'heigh2= ',str(height)
            norm_tag_corners = features.normalized_image_coordinates(
                tag.corners, width,
                height)  #imexif['width'], imexif['height'])

            # for each corner of tag
            for r in range(0, 4):

                # tag corners
                pt.append(norm_tag_corners[r, :])

                # tag id
                ft.append(tag.id)

                # colors
                ct.append(tag.colors[r, :])

                # corner id (0,1,2,3)
                it.append(r)

        # if tag features found
        if pt:
            pt = np.array(pt)
            ft = np.array(ft)
            ct = np.array(ct)
            it = np.array(it)
            data.save_tag_features(image, pt, ft, it, ct)
예제 #22
0
def pix_coords(x, image):
    return features.denormalized_image_coordinates(
        np.array([[x[0], x[1]]]), image.shape[1], image.shape[0])[0]
예제 #23
0
파일: stats.py 프로젝트: CosmosHua/GLD
def gcp_errors(data: DataSetBase,
               reconstructions: List[types.Reconstruction]) -> Dict[str, Any]:
    all_errors = []

    reference = data.load_reference()
    gcps = data.load_ground_control_points()
    if not gcps:
        return {}

    all_errors = []
    gcp_stats = []

    for gcp in gcps:
        if not gcp.lla:
            continue
        triangulated = None
        for rec in reconstructions:
            triangulated = multiview.triangulate_gcp(gcp, rec.shots, 1.0, 0.1)
            if triangulated is None:
                continue
            else:
                break

        if triangulated is None:
            continue

        gcp_enu = reference.to_topocentric(*gcp.lla_vec)
        e = triangulated - gcp_enu
        all_errors.append(e)

        # Begin computation of GCP stats
        observations = []
        for i, obs in enumerate(gcp.observations):
            if not obs.shot_id in rec.shots:
                continue
            shot = rec.shots[obs.shot_id]

            reprojected = shot.project(gcp_enu)
            annotated = obs.projection

            r_pixel = features.denormalized_image_coordinates(
                np.array([[reprojected[0], reprojected[1]]]),
                shot.camera.width, shot.camera.height)[0]
            r_pixel[0] /= shot.camera.width
            r_pixel[1] /= shot.camera.height

            a_pixel = features.denormalized_image_coordinates(
                np.array([[annotated[0], annotated[1]]]), shot.camera.width,
                shot.camera.height)[0]
            a_pixel[0] /= shot.camera.width
            a_pixel[1] /= shot.camera.height

            observations.append({
                'shot_id': obs.shot_id,
                'annotated': list(a_pixel),
                'reprojected': list(r_pixel)
            })

        gcp_stats.append({
            'id': gcp.id,
            'coordinates': list(gcp_enu),
            'observations': observations,
            'error': list(e)
        })

        # End computation of GCP stats

    with open(
            os.path.join(data.data_path, "stats",
                         "ground_control_points.json"), 'w') as f:
        f.write(json.dumps(gcp_stats, indent=4))

    return _gps_gcp_errors_stats(np.array(all_errors))
                        default=3,
                        type=int,
                        help='number of points to generate')
    args = parser.parse_args()

    data = dataset.DataSet(args.dataset)
    reference = data.load_reference_lla()
    reconstruction = data.load_reconstruction()[0]

    print 'WGS84'
    for i in range(args.num_points):
        point = np.random.choice(reconstruction.points.values())

        for shot in reconstruction.shots.values():
            pixel = shot.project(point.coordinates)
            if np.fabs(pixel).max() < 0.5:

                lla = geo.lla_from_topocentric(point.coordinates[0],
                                               point.coordinates[1],
                                               point.coordinates[2],
                                               reference['latitude'],
                                               reference['longitude'],
                                               reference['altitude'])

                x, y = features.denormalized_image_coordinates(
                    pixel.reshape(1, 2), shot.camera.width,
                    shot.camera.height)[0]

                print "{} {} {} {} {} {}".format(lla[0], lla[1], lla[2], x, y,
                                                 shot.id)
예제 #25
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 )
예제 #26
0
def label_pointcloud(data_path, semantics_path):
    #We take each shot, see which points fall on it and label it with corresponding semantic label.
    data = dataset.DataSet(data_path)
    reconstruction = data.load_reconstruction()[0]

    tracks_manager = data.load_tracks_manager()
    images = tracks_manager.get_shot_ids()

    imcount = 0
    ptcount = 0
    vote_dict = {}
    campose = np.empty((0, 3))
    for im in images:
        if (not (data.load_exif(im)['camera'] in reconstruction.cameras)):
            continue
        camera = reconstruction.cameras[data.load_exif(im)['camera']]
        # print("Camera W, H ", camera.width, camera.height)
        pts2d, pts3d = get_shot_observations(tracks_manager, reconstruction,
                                             camera, im)
        if (not (im in reconstruction.shots)):
            print(im, " not in shots!")
            continue
        shot = reconstruction.shots[im]

        campose = np.vstack((campose, shot.pose.translation))
        semantic_image_path = os.path.join(semantics_path,
                                           os.path.splitext(im)[0] + ".png")
        semantic_image = cv2.imread(semantic_image_path)
        print("Getting projections for image:  ", im)

        #TODO: Filter outliers by reprojection threshold?
        #TODO: Create walkable area by filling up non object shit.
        pointcloud = np.empty((0, 3))
        for i in range(len(pts3d)):
            # inlier = testInlier(pts3d[i], pts2d[i], camera, shot, 0.004) #resection_threshold from config.py
            # if(not(inlier)):
            #     continue
            pt2d = features.denormalized_image_coordinates(
                np.array(pts2d[i]).reshape(-1, 2), semantic_image.shape[1],
                semantic_image.shape[0])[0]
            # print(pt2d)
            row = int(pt2d[1])
            col = int(pt2d[0])
            # print(row, col)
            point = pts3d[i]
            pointcloud = np.vstack((pointcloud, point))

            if (not (point.tobytes() in vote_dict)):
                vote_dict[point.tobytes()] = []

            rgb = semantic_image[row, col]
            if (np.all(rgb == np.array([98, 98, 98]))):
                rgb = 1
            elif (np.all(rgb == np.array([100, 100, 100]))):
                rgb = 1
            else:
                rgb = 2

            vote_dict[point.tobytes()].append(rgb)
            ptcount = ptcount + 1

        imcount = imcount + 1

    pcl, groundPoints = get_pointcloud_from_vote(vote_dict)
    print(groundPoints)

    #Fill up the non-walkable area.
    planePointSet = pcl[:12000, :3]
    # if(groundPoints.shape[0] > 2):
    #     planePointSet = groundPoints
    boundMin = np.amin(planePointSet, axis=0)
    boundMax = np.amax(planePointSet, axis=0)
    planePtList = samplePlanePoints(None, boundMin, boundMax)
    print("Sampled ", len(planePtList), " points on plane")
    validPlanePts = np.empty((0, 6))
    count = 0
    n_elem = len(planePtList)
    interval = int(len(planePtList) / n_elem)
    planePtList = planePtList[::interval]
    for planePt in planePtList:
        color = getPointColorFromReconstruction(reconstruction, semantics_path,
                                                planePt)
        if (color is None):
            continue
        validPt = np.hstack((planePt, color))
        validPlanePts = np.vstack((validPlanePts, validPt))
        labelCompletionPercent = int(count / len(planePtList) * 100)
        if (count % 20 == 0):
            print("Completed ", labelCompletionPercent, "% of labeling")
        count = count + 1

    final_pcl = np.vstack((pcl[:12000, :], validPlanePts))
    print("We got ", validPlanePts.shape[0], " valid plane points")
    # final_pcl = pcl[:12000, :]
    print("Labeled ", ptcount, " points")
    print("Labeled for ", imcount, " images")
    flat = flatten_by_plane_proj(final_pcl[:, :3], np.array([0, 0, 1, 0]),
                                 (640, 480), final_pcl[:, 3:])

    #Enable to Plot CAMERA POSE on IMAGE.
    # for pt in campose:
    #     ptproj = flatten_coords_by_plane_proj(pt, final_pcl[:, :3], np.array([0, 0, 1, 0]), (640, 480))
    #     flat[ptproj[0, 1], ptproj[0, 0], :] = np.array([0, 0, 255])

    cv2.imwrite("flattened_img.jpg", flat)
    return final_pcl
예제 #27
0
파일: apps.py 프로젝트: zcyroot/OpenSfM
def pix_coords(x, image):
    return features.denormalized_image_coordinates(np.array([[x[0], x[1]]]),
                                                   image.shape[1],
                                                   image.shape[0])[0]