コード例 #1
0
def run():
    with grpc.insecure_channel('localhost:50051') as channel:
        stub = detection_server_pb2_grpc.DetectionServerStub(channel)
        while True:
            res = get_camera_resolution(stub)
            print(res)
            res = get_detected_objects(stub)
            print(res)
コード例 #2
0
def plot_and_capture_data(num_samples, realtime_plot, save_plot, save_plot_path, desired_labels):
    def pol_2_cart_deg(a, r):
        ''' Convert polar coordinates, in degrees, to cartesian. '''
        a_rad = np.deg2rad(a)
        return (r * np.sin(a_rad), r * np.cos(a_rad))

    def gen_pos_map():
        ''' Create position coordinates map for plotting. '''
        arr_r = list(range(common.R_MIN, common.R_MAX, common.R_RES)) + [common.R_MAX]
        arr_t = list(range(common.THETA_MIN, common.THETA_MAX, common.THETA_RES)) + [common.THETA_MAX]
        arr_p = list(range(common.PHI_MIN, common.PHI_MAX, common.PHI_RES)) + [common.PHI_MAX]

        # Format of pmap_xz is [[list of x],[list of z],[list of dot size]].
        # Used to plot points on the XZ plane. 
        pmap_xz = np.array([list(pol_2_cart_deg(p, ra)) + [ra * 0.75] for ra in arr_r for p in arr_p]).T

        # Format of pmap_yz is [[list of y],[list of z],[list of dot size]].
        # Used to plot points on the YZ plane.
        pmap_yz = np.array([list(pol_2_cart_deg(t, ra)) + [ra * 0.75] for ra in arr_r for t in arr_t]).T

        return pmap_yz, pmap_xz

    def init_position_markers(ax):
        """Initialize position markers and annotations."""
        target_pt, = ax.plot(0, 0, 'ro', zorder=2)
        target_ant = ax.annotate('target', xy=(0,0), color='red', zorder=2)
        centroid_pt, = ax.plot(0, 0, 'go', zorder=3)
        centroid_ant = ax.annotate('', xy=(0,0), color='green', zorder=3)
        return (target_pt, target_ant, centroid_pt, centroid_ant)

    def init_axis(ax, title, xlabel, ylabel):
        """Initialize axis labels."""
        face_color = ScalarMappable(cmap='coolwarm').to_rgba(0)
        ax.set_title(title)
        ax.set_facecolor(face_color)
        ax.set_xlabel(xlabel)
        ax.set_ylabel(ylabel)

    def update_plot(data):
        '''Update plot for animation.'''
        projections, name, target_position, centroid_position = data
        projection_xz, projection_yz, projection_xy = projections
        target_x, target_y, target_z = target_position
        centroid_x, centroid_y = centroid_position

        # Update target position and annotation from radar on plots. 
        target_ant_xz.set_position(xy=(target_x, target_z))
        target_pt_xz.set_data(target_x, target_z)

        target_ant_yz.set_position(xy=(target_y, target_z))
        target_pt_yz.set_data(target_y, target_z)

        target_ant_xy.set_position(xy=(target_x, target_y))
        target_pt_xy.set_data(target_x, target_y)

        # Update name and postion annotations of centroid from camera on plots
        centroid_ant_xz.set_text(s=name)
        centroid_ant_xz.set_position(xy=(centroid_x, target_z))
        centroid_pt_xz.set_data(centroid_x, target_z)

        centroid_ant_yz.set_text(s=name)
        centroid_ant_yz.set_position(xy=(centroid_y, target_z))
        centroid_pt_yz.set_data(centroid_y, target_z)

        centroid_ant_xy.set_text(s=name)
        centroid_ant_xy.set_position(xy=(centroid_x, centroid_y))
        centroid_pt_xy.set_data(centroid_x, centroid_y)

        # Update image colors according to return signal strength on plots.
        sm = ScalarMappable(cmap='coolwarm')
        signal_pts_xz.set_color(sm.to_rgba(projection_xz.T.flatten()))

        sm = ScalarMappable(cmap='coolwarm')
        signal_pts_yz.set_color(sm.to_rgba(projection_yz.T.flatten()))

        # Scale xy image data relative to target distance. 
        signal_pts_xy.set_extent([v*target_z/(zmax-zmin) for v in [xmin,xmax,ymin,ymax]])
        # Rotate xy image if radar horizontal since x and y axis are rotated 90 deg CCW.
        if RADAR_HORIZONTAL:
            projection_xy = np.rot90(projection_xy)

        sm = ScalarMappable(cmap='coolwarm')
        signal_pts_xy.set_data(sm.to_rgba(projection_xy))

        return (signal_pts_xz, target_ant_xz, target_pt_xz, centroid_ant_xz, centroid_pt_xz,
            signal_pts_yz, target_ant_yz, target_pt_yz, centroid_ant_yz, centroid_pt_yz,
            signal_pts_xy, target_ant_xy, target_pt_xy, centroid_ant_xy, centroid_pt_xy)

    if realtime_plot or save_plot:
        if save_plot:
            # Set up formatting for movie files.
            Writer = animation.writers['ffmpeg']
            writer = Writer(fps=15, metadata=dict(artist='lindo'), bitrate=1800)

        # Get position maps. 
        pmap_xz, pmap_yz  = gen_pos_map()

        # Initial scan.
        radar.Trigger()
        raw_image, _, _, _, _ = radar.GetRawImage()
        raw_image_np = np.array(raw_image, dtype=np.float32)
        # projection_yz is the 2D projection of target in y-z plane.
        # Transpose to match ordering of position map.
        projection_yz = raw_image_np[0,:,:].transpose().flatten()
        # projection_xz is the 2D projection of target in x-z plane.
        projection_xz = raw_image_np[:,0,:].transpose().flatten()

        #fig, (ax1, ax2, ax3) = plt.subplots(1, 3)
        fig = plt.figure()
        fig.suptitle('Target Return Signal, Target Position, Object Position and ID')
        gs = fig.add_gridspec(2, 2)
        ax1 = fig.add_subplot(gs[0,0])
        ax2 = fig.add_subplot(gs[0,1])
        ax3 = fig.add_subplot(gs[1,:])

        # Setup x-z plane plot.
        # Radar target return signal strength and camera centroid in x-z plane.
        init_axis(ax1, 'X-Z Plane', 'X (cm)', 'Z (cm)')
        signal_pts_xz = ax1.scatter(pmap_xz[0], pmap_xz[1], s=pmap_xz[2],
            c=projection_xz, cmap='coolwarm', zorder=1)
        (target_pt_xz, target_ant_xz, centroid_pt_xz,
            centroid_ant_xz) = init_position_markers(ax1)

        # Setup y-z plane plot.
        # Radar target return signal strength and camera centroid in y-z plane.
        init_axis(ax2, 'Y-Z Plane', 'Y (cm)', 'Z (cm)')
        signal_pts_yz = ax2.scatter(pmap_yz[0], pmap_yz[1], s=pmap_yz[2],
            c=projection_yz, cmap='coolwarm', zorder=1)
        (target_pt_yz, target_ant_yz, centroid_pt_yz,
            centroid_ant_yz) = init_position_markers(ax2)

        # Setup x-y plane plot.
        # Radar target return signal strength and camera centroid in x-z plane.
        # NB: When radar is placed horizontally, a rotated image will be shown.
        init_axis(ax3, 'X-Y Plane', 'X (cm)', 'Y (cm)')

        # Calculate axis range to set axis limits and plot extent.
        # Plot extent will change as a function of target distance.
        xmax = np.amax(pmap_xz[0]).astype(np.int)
        xmin = np.amin(pmap_xz[0]).astype(np.int)
        ymax = np.amax(pmap_yz[0]).astype(np.int)
        ymin = np.amin(pmap_yz[0]).astype(np.int)
        zmax = np.amax(pmap_yz[1]).astype(np.int)
        zmin = np.amin(pmap_yz[1]).astype(np.int)

        ax3.set_xlim(xmax, xmin)
        ax3.set_ylim(ymax, ymin)
        init_img = np.zeros((xmax-xmin, ymax-ymin))
        signal_pts_xy = ax3.imshow(init_img, cmap='coolwarm',
            extent=[xmin,xmax,ymin,ymax], zorder=1)
        (target_pt_xy, target_ant_xy, centroid_pt_xy,
            centroid_ant_xy) = init_position_markers(ax3)

    # Initialize ground truth data.
    samples = []
    labels = []

    with grpc.insecure_channel(DETECT_SERVER_IP) as channel:
        stub = detection_server_pb2_grpc.DetectionServerStub(channel)

        res = get_camera_resolution(stub)
        width, height = res.width, res.height
        logger.info(f'camera resolution: {width, height}')

        res = get_camera_intrinsic_parameters(stub)
        fx, fy, cx, cy = res.fx, res.fy, res.cx, res.cy
        logger.debug(f'camera intrinsics fx: {fx} fy:{fy} cx:{cx} cy:{cy}')

        # Calculate camera field (aka angle) of view from intrinsics.
        fov_hor = 2 * np.arctan(width / (2 * fx)) * 180.0 / np.pi
        fov_ver = 2 * np.arctan(height / (2 * fy)) * 180.0 / np.pi
        logger.info(f'camera hor fov: {fov_hor:.1f} (deg) ver fov: {fov_ver:.1f} (deg)')

        def get_samples():
            active = True
            sample_num = 1

            while active:
                # Scan according to profile and record targets (if any).
                radar.Trigger()

                # Get object detection results from server (if any). 
                detected_objects = get_detected_objects(stub, desired_labels)
                if not detected_objects:
                    continue

                # Retrieve any targets from the last recording.
                #targets = radar.GetTrackerTargets()
                targets = radar.GetSensorTargets()
                if not targets:
                    continue

                # raw_image ordering: (theta, phi, r)
                raw_image, size_x, size_y, size_z, _ = radar.GetRawImage()
                raw_image_np = np.array(raw_image, dtype=np.float32)
                logger.debug(f'Raw image np shape: {raw_image_np.shape}')

                #targets = get_derived_targets(raw_image_np, size_x, size_y, size_z)

                logger.info(f'Sample number {sample_num} of {num_samples}'.center(60, '-'))
                # Find the detected object closest to each radar target.
                for t, target in enumerate(targets):
                    logger.info(f'Target #{t + 1}:')
                    logger.debug('\nx: {}\ny: {}\nz: {}\namplitude: {}\n'.format(
                        target.xPosCm, target.yPosCm, target.zPosCm, target.amplitude))

                    i, j, k = common.calculate_matrix_indices(
                        target.xPosCm, target.yPosCm, target.zPosCm,
                        size_x, size_y, size_z)
                    logger.debug(f'i: {i}, j: {j}, k: {k}')

                    # Init distance between radar and camera target as a % of radar target depth.
                    # This is used as a threshold to declare correspondence. 
                    current_distance = DETECTION_THRESHOLD_PERCENT * target.zPosCm
                    #current_distance = MAX_TARGET_OBJECT_DISTANCE
                    logger.debug(f'Initial threshold: {current_distance:.1f} (cm)')

                    target_object_close = False

                    for obj in detected_objects:
                        if obj.score < MIN_DETECTED_OBJECT_SCORE:
                            logger.debug(f'Object ({obj.label}) score ({obj.score:.1f}) too low...skipping.')
                            continue

                        # Convert position of detected object's centroid to radar coordinate system.
                        centroid_camera = (width*obj.centroid.x, height*obj.centroid.y)
                        logger.debug(f'Centroid camera: {centroid_camera}')
                        centroid_radar = convert_coordinates(centroid_camera,
                            target.zPosCm, fx, fy, cx, cy)
                        logger.debug(f'Centroid radar: {centroid_radar}')

                        # Calculate distance between detected object and radar target. 
                        distance = compute_distance((target.xPosCm, target.yPosCm), centroid_radar)
                        logger.debug(f'Distance: {distance}')

                        # Find the detected object closest to the radar target.
                        if distance < current_distance:
                            target_object_close = True
                            current_distance = distance
                            current_score = obj.score
                            target_name = obj.label
                            target_position = target.xPosCm, target.yPosCm, target.zPosCm
                            centroid_position = centroid_radar
                            # Calculate 3D to 2D projections of target return signal.
                            # Signal in raw_image_np with shape (size_x, size_y, size_z).
                            # axis 1 and 2 of the matrix (j, k) contain the projections
                            #   represented in angle phi and distance r, respectively.
                            #   These are 2D projections the y-z plane.
                            # axis 0 and 2 of the matrix (i, k) contain the projections
                            #   represented in angle theta and distance r, respectively.
                            #   These are 2D projections the x-z plane.
                            #
                            # projection_yz is the 2D projection of target in y-z plane.
                            projection_yz = raw_image_np[i,:,:]
                            logger.debug(f'Projection_yz shape: {projection_yz.shape}')
                            # projection_xz is the 2D projection of target in x-z plane.
                            projection_xz = raw_image_np[:,j,:]
                            logger.debug(f'Projection_xz shape: {projection_xz.shape}')
                            # projection_xy is 2D projection of target signal in x-y plane.
                            projection_xy = raw_image_np[:,:,k]
                            logger.debug(f'Projection_xy shape: {projection_xy.shape}')
                        else:
                            msg = (
                                f'Found "{obj.label}" with score {obj.score:.1f} at {distance:.1f} (cm)'
                                f' too far from target at z {target.zPosCm:.1f} (cm)...skipping.'
                            )
                            logger.info(msg)

                    if target_object_close:
                        msg = (
                            f'Found "{target_name}" with score {current_score:.1f} at {distance:.1f} (cm)'
                            f' from target at z {target.zPosCm:.1f} (cm)...storing.'
                        )
                        logger.info(msg)

                        yield ((projection_xz, projection_yz, projection_xy),
                            target_name, target_position, centroid_position)

                logger.info('-'*60+'\n')

                if sample_num < num_samples:
                    sample_num += 1
                else:
                    active = False
                    if realtime_plot:
                        print('\n**** Close plot window to continue. ****\n')

        if realtime_plot or save_plot:
            # Animate but do not save data.
            ani = animation.FuncAnimation(fig, update_plot, frames=get_samples,
                repeat=False, interval=100, blit=True)

            try:
                if realtime_plot:
                    plt.show()
                elif save_plot:
                    ani.save(save_plot_path, writer=writer)
            except Exception as e:
                print(f'Unhandled animation exception: {e}')
                pass
        else:
            # Save data but do not animate.
            for data in get_samples():
                projections, target_name, _, _ = data
                samples.append(projections)
                labels.append(target_name)

    return samples, labels