def draw(self, rvec, tvec, status,
          triangl_idxs, imgp_to_objp_idxs, objp, objp_groups, color_palette, color_palette_size):    # TODO: move these variables to another class
     """
     Draw 3D composite view.
     Navigate using the following keys:
         LEFT/RIGHT    UP/DOWN    PAGEUP/PAGEDOWN    HOME/END
     
     'status' can have the following values:
         0: bad frame
         1: good frame but not a keyframe
         2: good frame and also a keyframe
     """
     
     # Calculate current camera's axis-system expressed in world coordinates and cache center
     if status:
         R_cam = cvh.Rodrigues(rvec)
         cam_axissys_objp = np.empty((4, 3))
         cam_axissys_objp[0, :] = -R_cam.T.dot(tvec).reshape(1, 3)    # cam_origin
         cam_axissys_objp[1:4, :] = cam_axissys_objp[0, :] + R_cam    # cam_x, cam_y, cam_z
         self.cams_pos = np.concatenate((self.cams_pos, cam_axissys_objp[0:1, :]))    # cache cam_origin
         if status == 2:    # frame is a keyframe
             self.cams_pos_keyfr = np.concatenate((self.cams_pos_keyfr, cam_axissys_objp[0:1, :]))    # cache cam_origin
     
     while True:
         # Fill with dark gray background color
         self.img.fill(56)
         
         # Draw world axis system
         if trfm.projection_depth(np.array([[0,0,4]]), self.P)[0] > 0:    # only draw axis-system if its Z-axis is entirely in sight
             draw_axis_system(self.img, cvh.Rodrigues(self.P[0:3, 0:3]), self.P[0:3, 3], self.K, None)
         
         # Draw 3D points
         objp_proj, objp_visible = trfm.project_points(objp, self.K, self.img.shape, self.P)
         objp_visible = set(np.where(objp_visible)[0])
         current_idxs = set(imgp_to_objp_idxs[np.array(tuple(triangl_idxs))]) & objp_visible
         done_idxs = np.array(tuple(objp_visible - current_idxs), dtype=int)
         current_idxs = np.array(tuple(current_idxs), dtype=int)
         groups = objp_groups[current_idxs]
         for opp, opg, color in zip(objp_proj[current_idxs], groups, color_palette[groups % color_palette_size]):
             cvh.circle(self.img, opp[0:2], 4, color, thickness=-1)    # draw point, big radius
         groups = objp_groups[done_idxs]
         for opp, opg, color in zip(objp_proj[done_idxs], groups, color_palette[groups % color_palette_size]):
             cvh.circle(self.img, opp[0:2], 2, color, thickness=-1)    # draw point, small radius
         
         # Draw camera trajectory
         cams_pos_proj, cams_pos_visible = trfm.project_points(self.cams_pos, self.K, self.img.shape, self.P)
         cams_pos_proj = cams_pos_proj[np.where(cams_pos_visible)[0]]
         color = rgb(0,0,0)
         for p1, p2 in zip(cams_pos_proj[:-1], cams_pos_proj[1:]):
             cvh.line(self.img, p1, p2, color, thickness=2)    # interconnect trajectory points
         cams_pos_keyfr_proj, cams_pos_keyfr_visible = trfm.project_points(self.cams_pos_keyfr, self.K, self.img.shape, self.P)
         cams_pos_keyfr_proj = cams_pos_keyfr_proj[np.where(cams_pos_keyfr_visible)[0]]
         color = rgb(255,255,255)
         for p in cams_pos_proj:
             cvh.circle(self.img, p, 1, color, thickness=-1)    # draw trajectory points
         for p in cams_pos_keyfr_proj:
             cvh.circle(self.img, p, 3, color)    # highlight keyframe trajectory points
         
         # Draw current camera axis system
         if status:
             (cam_origin, cam_xAxis, cam_yAxis, cam_zAxis), cam_visible = \
                     trfm.project_points(cam_axissys_objp, self.K, self.img.shape, self.P)
             if cam_visible.sum() == len(cam_visible):    # only draw axis-system if it's entirely in sight
                 cvh.line(self.img, cam_origin, cam_xAxis, rgb(255,0,0), lineType=cv2.CV_AA)
                 cvh.line(self.img, cam_origin, cam_yAxis, rgb(0,255,0), lineType=cv2.CV_AA)
                 cvh.line(self.img, cam_origin, cam_zAxis, rgb(0,0,255), lineType=cv2.CV_AA)
                 cvh.circle(self.img, cam_zAxis, 3, rgb(0,0,255))    # small dot to highlight cam Z axis
         else:
             last_cam_origin, last_cam_visible = trfm.project_points(self.cams_pos[-1:], self.K, self.img.shape, self.P)
             if last_cam_visible[0]:    # only draw if in sight
                 cvh.putText(self.img, '?', last_cam_origin[0] - (11, 11), fontFace, fontScale * 4, rgb(255,0,0))    # draw '?' because it's a bad frame
         
         # Display image
         cv2.imshow(self.img_title, self.img)
         
         # Translate view by keyboard
         key = cv2.waitKey() & 0xFF
         delta_t_view = np.zeros((3))
         if key in (0x51, 0x53):    # LEFT/RIGHT key
             delta_t_view[0] = 2 * (key == 0x51) - 1    # LEFT -> increase cam X pos
         elif key in (0x52, 0x54):    # UP/DOWN key
             delta_t_view[1] = 2 * (key == 0x52) - 1    # UP -> increase cam Y pos
         elif key in (0x55, 0x56):    # PAGEUP/PAGEDOWN key
             delta_t_view[2] = 2 * (key == 0x55) - 1    # PAGEUP -> increase cam Z pos
         elif key in (0x50, 0x57):    # HOME/END key
             delta_z_rot = 2 * (key == 0x50) - 1    # HOME -> counter-clockwise rotate around cam Z axis
             self.P[0:3, 0:4] = cvh.Rodrigues((0, 0, delta_z_rot * pi/36)).dot(self.P[0:3, 0:4])    # by steps of 5 degrees
         else:
             break
         self.P[0:3, 3] += delta_t_view * 0.3
Beispiel #2
0
    def draw(
            self, rvec, tvec, status, triangl_idxs, imgp_to_objp_idxs, objp,
            objp_groups, color_palette,
            color_palette_size):  # TODO: move these variables to another class
        """
        Draw 3D composite view.
        Navigate using the following keys:
            LEFT/RIGHT    UP/DOWN    PAGEUP/PAGEDOWN    HOME/END
        
        'status' can have the following values:
            0: bad frame
            1: good frame but not a keyframe
            2: good frame and also a keyframe
        """

        # Calculate current camera's axis-system expressed in world coordinates and cache center
        if status:
            R_cam = cvh.Rodrigues(rvec)
            cam_axissys_objp = np.empty((4, 3))
            cam_axissys_objp[0, :] = -R_cam.T.dot(tvec).reshape(
                1, 3)  # cam_origin
            cam_axissys_objp[
                1:4, :] = cam_axissys_objp[0, :] + R_cam  # cam_x, cam_y, cam_z
            self.cams_pos = np.concatenate(
                (self.cams_pos, cam_axissys_objp[0:1, :]))  # cache cam_origin
            if status == 2:  # frame is a keyframe
                self.cams_pos_keyfr = np.concatenate(
                    (self.cams_pos_keyfr,
                     cam_axissys_objp[0:1, :]))  # cache cam_origin

        while True:
            # Fill with dark gray background color
            self.img.fill(56)

            # Draw world axis system
            if trfm.projection_depth(
                    np.array([[0, 0, 4]]), self.P
            )[0] > 0:  # only draw axis-system if its Z-axis is entirely in sight
                draw_axis_system(self.img, cvh.Rodrigues(self.P[0:3, 0:3]),
                                 self.P[0:3, 3], self.K, None)

            # Draw 3D points
            objp_proj, objp_visible = trfm.project_points(
                objp, self.K, self.img.shape, self.P)
            objp_visible = set(np.where(objp_visible)[0])
            current_idxs = set(imgp_to_objp_idxs[np.array(
                tuple(triangl_idxs))]) & objp_visible
            done_idxs = np.array(tuple(objp_visible - current_idxs), dtype=int)
            current_idxs = np.array(tuple(current_idxs), dtype=int)
            groups = objp_groups[current_idxs]
            for opp, opg, color in zip(
                    objp_proj[current_idxs], groups,
                    color_palette[groups % color_palette_size]):
                cvh.circle(self.img, opp[0:2], 4, color,
                           thickness=-1)  # draw point, big radius
            groups = objp_groups[done_idxs]
            for opp, opg, color in zip(
                    objp_proj[done_idxs], groups,
                    color_palette[groups % color_palette_size]):
                cvh.circle(self.img, opp[0:2], 2, color,
                           thickness=-1)  # draw point, small radius

            # Draw camera trajectory
            cams_pos_proj, cams_pos_visible = trfm.project_points(
                self.cams_pos, self.K, self.img.shape, self.P)
            cams_pos_proj = cams_pos_proj[np.where(cams_pos_visible)[0]]
            color = rgb(0, 0, 0)
            for p1, p2 in zip(cams_pos_proj[:-1], cams_pos_proj[1:]):
                cvh.line(self.img, p1, p2, color,
                         thickness=2)  # interconnect trajectory points
            cams_pos_keyfr_proj, cams_pos_keyfr_visible = trfm.project_points(
                self.cams_pos_keyfr, self.K, self.img.shape, self.P)
            cams_pos_keyfr_proj = cams_pos_keyfr_proj[np.where(
                cams_pos_keyfr_visible)[0]]
            color = rgb(255, 255, 255)
            for p in cams_pos_proj:
                cvh.circle(self.img, p, 1, color,
                           thickness=-1)  # draw trajectory points
            for p in cams_pos_keyfr_proj:
                cvh.circle(self.img, p, 3,
                           color)  # highlight keyframe trajectory points

            # Draw current camera axis system
            if status:
                (cam_origin, cam_xAxis, cam_yAxis, cam_zAxis), cam_visible = \
                        trfm.project_points(cam_axissys_objp, self.K, self.img.shape, self.P)
                if cam_visible.sum() == len(
                        cam_visible
                ):  # only draw axis-system if it's entirely in sight
                    cvh.line(self.img,
                             cam_origin,
                             cam_xAxis,
                             rgb(255, 0, 0),
                             lineType=cv2.CV_AA)
                    cvh.line(self.img,
                             cam_origin,
                             cam_yAxis,
                             rgb(0, 255, 0),
                             lineType=cv2.CV_AA)
                    cvh.line(self.img,
                             cam_origin,
                             cam_zAxis,
                             rgb(0, 0, 255),
                             lineType=cv2.CV_AA)
                    cvh.circle(self.img, cam_zAxis, 3,
                               rgb(0, 0,
                                   255))  # small dot to highlight cam Z axis
            else:
                last_cam_origin, last_cam_visible = trfm.project_points(
                    self.cams_pos[-1:], self.K, self.img.shape, self.P)
                if last_cam_visible[0]:  # only draw if in sight
                    cvh.putText(self.img, '?', last_cam_origin[0] - (11, 11),
                                fontFace, fontScale * 4,
                                rgb(255, 0,
                                    0))  # draw '?' because it's a bad frame

            # Display image
            cv2.imshow(self.img_title, self.img)

            # Translate view by keyboard
            key = cv2.waitKey() & 0xFF
            delta_t_view = np.zeros((3))
            if key in (0x51, 0x53):  # LEFT/RIGHT key
                delta_t_view[0] = 2 * (
                    key == 0x51) - 1  # LEFT -> increase cam X pos
            elif key in (0x52, 0x54):  # UP/DOWN key
                delta_t_view[1] = 2 * (key
                                       == 0x52) - 1  # UP -> increase cam Y pos
            elif key in (0x55, 0x56):  # PAGEUP/PAGEDOWN key
                delta_t_view[2] = 2 * (
                    key == 0x55) - 1  # PAGEUP -> increase cam Z pos
            elif key in (0x50, 0x57):  # HOME/END key
                delta_z_rot = 2 * (
                    key == 0x50
                ) - 1  # HOME -> counter-clockwise rotate around cam Z axis
                self.P[0:3,
                       0:4] = cvh.Rodrigues((0, 0, delta_z_rot * pi / 36)).dot(
                           self.P[0:3, 0:4])  # by steps of 5 degrees
            else:
                break
            self.P[0:3, 3] += delta_t_view * 0.3
def drawCamera(img, cam_origin, cam_axes, K, P, neg_fy=False, scale_factor=0.07, draw_axes=True, draw_frustum=True):
    """
    Draws a camera (X right, Y down) with 3D position "cam_origin" and local axes "cam_axes"
    on "img" where the viewer cam has (3x3 matrix) intrinsics "K" and (3x4 matrix) pose "P".
    
    "neg_fy" : set to True if the drawn cam has negative Y focal length, otherwise False
    "scale_factor" : the size of the drawn cam
    "draw_axes" : set to True to draw the axes of the to-be-drawn cam, otherwise False
    "draw_frustum" : set to True to draw the frustrum of the to-be-drawn cam, otherwise False
    """
    
    # Define local object-points
    objp_to_project = np.array([ [ 0. ,  0. , 0.],      # cam origin
                                 [ 1. ,  0.,  0.],      # cam X-axis
                                 [ 0. ,  1.,  0.],      # cam Y-axis
                                 [ 0. ,  0.,  1.],      # cam Z-axis
                                 
                                 [-0.5, -0.3, 1.],      # frustum top-left
                                 [ 0.5, -0.3, 1.],      # frustum top-right
                                 [ 0.5,  0.3, 1.],      # frustum bottom-right
                                 [-0.5,  0.3, 1.],      # frustum bottom-left
                                 
                                 [-0.3, -0.3, 1.],      # cam up indication triangle left
                                 [ 0.3, -0.3, 1.],      # cam up indication triangle right
                                 [ 0. , -0.6, 1.] ])    # cam up indication triangle top
    
    # Keep size of camera constant by normalizing using the distance between cam origin and origin of visualizing cam P
    objp_to_project *= cv2.norm(cam_origin.T + P[0:3, 0:3].T.dot(P[0:3, 3:4])) * scale_factor
    
    # Negative focal length requires the cam's Y-axis to be flipped
    if neg_fy:
        objp_to_project[:, 1] *= -1
    
    # Transform points in cam coords to world coords
    objp_to_project = cam_origin + objp_to_project.dot(cam_axes)
    
    # Project world coords to the viewer cam defined by (P, K)
    objp_projected, cam_visible = trfm.project_points(objp_to_project, K, img.shape, P)
    
    # Only draw axis-system if it's entirely in sight
    if cam_visible.sum() == len(cam_visible):
        cam_origin = objp_projected[0]
        
        if draw_axes:
            cam_xAxis, cam_yAxis, cam_zAxis = objp_projected[1:4]
            line(img, cam_origin, cam_xAxis, rgb(255,0,0), lineType=cv2.CV_AA)      # X-axis (red)
            line(img, cam_origin, cam_yAxis, rgb(0,255,0), lineType=cv2.CV_AA)      # Y-axis (green)
            line(img, cam_origin, cam_zAxis, rgb(0,0,255), lineType=cv2.CV_AA)      # Z-axis (blue)
            circle(img, cam_zAxis, 3, rgb(0,0,255))    # small dot to highlight cam Z axis
        
        if draw_frustum:
            yellow = rgb(255,255,0)
            frustum_plane = objp_projected[4:8]
            for i, p in enumerate(frustum_plane):
                # Create frustum plane
                line(img, frustum_plane[i], frustum_plane[(i+1) % 4], yellow, lineType=cv2.CV_AA)
                # Connect frustum plane points with origin
                line(img, cam_origin, p, yellow, lineType=cv2.CV_AA)
            # Draw up-facing frustum triangle
            cv2.fillPoly(img, [objp_projected[8:11]], yellow, lineType=cv2.CV_AA)
    
    return img