Beispiel #1
0
def main(argv):
    """An example using the API to list and get specific objects."""
    parser = argparse.ArgumentParser()
    parser.add_argument('-s', '--server', help='IP address of external machine learning server.',
                        required=True)
    parser.add_argument('-m', '--model', help='Model file on the server', default='coco_inference')
    parser.add_argument('-c', '--confidence', help='Minimum confidence to return an object.',
                        default=0.7, type=float)
    parser.add_argument('-j', '--input-image-dir', help='Path to a directory of images.')
    parser.add_argument('-n', '--num-runs', help='Number of runs of the image directory to perform',
                        default=1, type=int)
    parser.add_argument('-l', '--model-list', help='List of models to be used.',
                        action='store_true')
    parser.add_argument('-v', '--verbose', help='Print verbose output', action='store_true')
    options = parser.parse_args(argv)

    if options.input_image_dir is None and not options.model_list:
        print('Error: must provide an input image.')
        sys.exit(1)

    if options.model_list and options.input_image_dir is not None:
        print('Error: cannot list models with input image.')
        sys.exit(1)

    if options.model_list:
        channel = grpc.insecure_channel(options.server)
        stub = network_compute_bridge_service_pb2_grpc.NetworkComputeBridgeWorkerStub(channel)
        server_data = network_compute_bridge_pb2.NetworkComputeServerConfiguration(
            service_name='test')
        list_req = network_compute_bridge_pb2.ListAvailableModelsRequest(server_config=server_data)
        response = stub.ListAvailableModels(list_req)

        print('Available models on server at ' + options.server + ' are:')
        for model in response.available_models:
            print('    ' + model)
        sys.exit(0)

    image_paths = []
    for entry in os.scandir(options.input_image_dir):
        if (entry.path.endswith(".jpg") or entry.path.endswith(".png")) and entry.is_file():
            image_paths.append(entry.path)

    image_paths = image_paths * options.num_runs

    start_time = time.perf_counter()
    with mp.Pool() as p:
        latencies = p.starmap(
            _send_request,
            [(options.server, path, options.model, options.confidence, options.verbose)
             for path in image_paths])
        latency_sum = sum(latencies)
        count = len(latencies)

    end_time = time.perf_counter()
    total_time = end_time - start_time
    print(f'Total time: {total_time} seconds.')
    avg_latency = latency_sum / count
    print(f'avg latency: {avg_latency * 1000} ms, fps: {count / total_time} fps')
    def _request_data(self, request, network_compute_bridge_metadata,
                      store_helper):
        """Make the RPC to the network compute bridge worker.

        Args:
            request (bosdyn.api.AcquirePluginDataRequest): Plugin request.
            network_compute_bridge_metadata (google.protobuf.Struct): Metadata containing 
                information needed for the request
            store_helper (bosdyn.client.DataAcquisitionStoreHelper): Helper used to manage storage
                of objects in data acquisition store service.

        Returns:
            The response from the compute request or None if error occurs
        """

        server_config = network_compute_bridge_pb2.NetworkComputeServerConfiguration(
            service_name=self._worker_name)

        try:
            image_service = network_compute_bridge_metadata["image_service"]
            image_source = network_compute_bridge_metadata["image_source"]
        except ValueError:
            errMsg = "Unable to get image service and source info."
            data_id = self._get_data_id(request, kCapabilityImage)
            store_helper.state.add_errors([make_error(data_id, errMsg)])
            _LOGGER.error(errMsg)

        service_source = network_compute_bridge_pb2.ImageSourceAndService(
            image_service=image_service, image_source=image_source)

        try:
            model_name = network_compute_bridge_metadata["model_name"]
            min_confidence = network_compute_bridge_metadata["min_confidence"]
        except ValueError:
            errMsg = "Unable to get model name or confidence value."
            data_id = self._get_data_id(request, kCapabilityObjectInImage)
            store_helper.state.add_errors([make_error(data_id, errMsg)])
            _LOGGER.error(errMsg)

        input_data = network_compute_bridge_pb2.NetworkComputeInputData(
            image_source_and_service=service_source,
            model_name=model_name,
            min_confidence=min_confidence)
        network_compute_request = network_compute_bridge_pb2.NetworkComputeRequest(
            server_config=server_config, input_data=input_data)

        response = self._network_compute_bridge_client.network_compute_bridge_command(
            network_compute_request)
        return response
    def get_capabilities(self):
        """Get list of available data capture options for the network compute bridge worker.

        Returns:
            Array with list of Capabilities corresponding to the available data capture options.
        """

        # Try to get a list of models available from the worker to see if this service is alive.
        while True:
            try:
                server_data = network_compute_bridge_pb2.NetworkComputeServerConfiguration(
                    service_name=self._worker_name)
                list_req = network_compute_bridge_pb2.ListAvailableModelsRequest(
                    server_config=server_data)
                response = self._network_compute_bridge_client.list_available_models_command(
                    list_req)
                break
            except (ExternalServiceNotFoundError, ExternalServerError):
                _LOGGER.exception(
                    'Network compute bridge worker is still unavailable:\n')
                time.sleep(2)
        if response.header.error.message:
            _LOGGER.error(
                "List available models from %s returned with error: %s",
                self._worker_name, response.header.error.message)
        else:
            _LOGGER.info('Available models from %s:', self._worker_name)
            for model in response.available_models:
                _LOGGER.info('   %s', model)

        # Compose the list of data capture options.
        capabilities = []
        _LOGGER.info('Available data capture options:')
        for name in kCapabilityNames:
            _LOGGER.info('   %s', name)
            capabilities.append(
                Capability(name=name,
                           description="Processed {} from {}.".format(
                               name, self._worker_name),
                           channel_name="{}--{}".format(
                               self._worker_name, name)))

        return capabilities
Beispiel #4
0
def get_obj_and_img(network_compute_client, server, model, confidence,
                    image_sources, label):

    for source in image_sources:
        # Build a network compute request for this image source.
        image_source_and_service = network_compute_bridge_pb2.ImageSourceAndService(
            image_source=source)

        # Input data:
        #   model name
        #   minimum confidence (between 0 and 1)
        #   if we should automatically rotate the image
        input_data = network_compute_bridge_pb2.NetworkComputeInputData(
            image_source_and_service=image_source_and_service,
            model_name=model,
            min_confidence=confidence,
            rotate_image=network_compute_bridge_pb2.NetworkComputeInputData.
            ROTATE_IMAGE_ALIGN_HORIZONTAL)

        # Server data: the service name
        server_data = network_compute_bridge_pb2.NetworkComputeServerConfiguration(
            service_name=server)

        # Pack and send the request.
        process_img_req = network_compute_bridge_pb2.NetworkComputeRequest(
            input_data=input_data, server_config=server_data)

        resp = network_compute_client.network_compute_bridge_command(
            process_img_req)

        best_obj = None
        highest_conf = 0.0
        best_vision_tform_obj = None

        img = get_bounding_box_image(resp)
        image_full = resp.image_response

        # Show the image
        cv2.imshow("Fetch", img)
        cv2.waitKey(15)

        if len(resp.object_in_image) > 0:
            for obj in resp.object_in_image:
                # Get the label
                obj_label = obj.name.split('_label_')[-1]
                if obj_label != label:
                    continue
                conf_msg = wrappers_pb2.FloatValue()
                obj.additional_properties.Unpack(conf_msg)
                conf = conf_msg.value

                try:
                    vision_tform_obj = frame_helpers.get_a_tform_b(
                        obj.transforms_snapshot,
                        frame_helpers.VISION_FRAME_NAME,
                        obj.image_properties.frame_name_image_coordinates)
                except bosdyn.client.frame_helpers.ValidateFrameTreeError:
                    # No depth data available.
                    vision_tform_obj = None

                if conf > highest_conf and vision_tform_obj is not None:
                    highest_conf = conf
                    best_obj = obj
                    best_vision_tform_obj = vision_tform_obj

        if best_obj is not None:
            return best_obj, image_full, best_vision_tform_obj

    return None, None, None
Beispiel #5
0
def main(argv):
    """An example using the API to list and get specific objects."""
    parser = argparse.ArgumentParser()
    bosdyn.client.util.add_common_arguments(parser)
    parser.add_argument('-i', '--image-source', help='Image source on the robot to use.')
    parser.add_argument(
        '-q', '--image-source-service', help=
        'Image *service* for the image source to use.  Defaults to the main image service if not provided.',
        default='')
    parser.add_argument('-s', '--service',
                        help='Service name of external machine learning server in the directory.',
                        required=False)
    parser.add_argument('-m', '--model', help='Model file on the server')
    parser.add_argument('-c', '--confidence', help='Minimum confidence to return an object.',
                        default=0.5, type=float)
    parser.add_argument('-j', '--input-image',
                        help='Path to an image to use instead of an image source.')
    parser.add_argument(
        '-l', '--model-list',
        help='List all available network compute servers and their provided models.',
        action='store_true')
    parser.add_argument('-r', '--disable-rotation',
                        help='Disable rotation of images (to align with horizontal)',
                        action='store_true')
    options = parser.parse_args(argv)

    if options.image_source is not None and options.input_image is not None:
        print('Error: cannot provide both an input image and an image source.')
        sys.exit(1)

    if options.model_list and (options.image_source is not None or options.input_image is not None):
        print('Error: cannot list models with input image source or input image.')
        sys.exit(1)

    if options.image_source is None and options.input_image is None and options.model_list == False:
        default_image_source = 'frontleft_fisheye_image'
        print('No image source provided so defaulting to "' + default_image_source + '".')
        options.image_source = default_image_source

    # Create robot object with a world object client
    sdk = bosdyn.client.create_standard_sdk('IdentifyObjectClient')
    robot = sdk.create_robot(options.hostname)
    robot.authenticate(options.username, options.password)

    #Time sync is necessary so that time-based filter requests can be converted
    robot.time_sync.wait_for_sync()

    #Create the network compute client
    network_compute_client = robot.ensure_client(NetworkComputeBridgeClient.default_service_name)

    directory_client = robot.ensure_client(
        bosdyn.client.directory.DirectoryClient.default_service_name)

    robot_state_client = robot.ensure_client(RobotStateClient.default_service_name)
    robot_command_client = robot.ensure_client(RobotCommandClient.default_service_name)
    robot.time_sync.wait_for_sync()

    if options.model_list:
        server_service_names = get_all_network_compute_services(directory_client)

        print('Found ' + str(len(server_service_names)) +
              ' available service(s).  Listing their models:')
        print('------------------------------------')

        for service in server_service_names:
            print('    ' + service)
            server_data = network_compute_bridge_pb2.NetworkComputeServerConfiguration(
                service_name=service)
            list_req = network_compute_bridge_pb2.ListAvailableModelsRequest(
                server_config=server_data)
            response = network_compute_client.list_available_models_command(list_req)

            if response.header.error.message:
                print('        Error message: {}'.format(response.header.error.message))
            else:
                for model in response.available_models:
                    print('        ' + model)
        sys.exit(0)

    # A service name must be provided if not doing a directory list.
    if options.service is None or len(options.service) == 0:
        print('Error: --service must be provided for operations other than --model-list')
        sys.exit(1)

    server_data = network_compute_bridge_pb2.NetworkComputeServerConfiguration(
        service_name=options.service)

    if options.image_source is not None:
        if options.model is None:
            print('Error: you must provide a model.')
            sys.exit(1)

        img_source_and_service = network_compute_bridge_pb2.ImageSourceAndService(
            image_source=options.image_source, image_service=options.image_source_service)

        input_data = network_compute_bridge_pb2.NetworkComputeInputData(
            image_source_and_service=img_source_and_service, model_name=options.model,
            min_confidence=options.confidence)
    else:
        # Read the input image.
        image_in = cv2.imread(options.input_image)
        if image_in is None:
            print('Error: failed to read "' + options.input_image + '".  Does the file exist?')
            sys.exit(1)

        rgb = cv2.cvtColor(image_in, cv2.COLOR_BGR2RGB)

        success, im_buffer = cv2.imencode(".jpg", rgb)

        if not success:
            print('Error: failed to encode input image as a jpg.  Abort.')
            sys.exit(1)

        height = image_in.shape[0]
        width = image_in.shape[1]

        image_proto = image_pb2.Image(format=image_pb2.Image.FORMAT_JPEG, cols=width, rows=height,
                                      data=im_buffer.tobytes(),
                                      pixel_format=image_pb2.Image.PIXEL_FORMAT_RGB_U8)

        input_data = network_compute_bridge_pb2.NetworkComputeInputData(
            image=image_proto, model_name=options.model, min_confidence=options.confidence)

    if options.disable_rotation:
        input_data.rotate_image = network_compute_bridge_pb2.NetworkComputeInputData.ROTATE_IMAGE_NO_ROTATION
    else:
        input_data.rotate_image = network_compute_bridge_pb2.NetworkComputeInputData.ROTATE_IMAGE_ALIGN_HORIZONTAL

    process_img_req = network_compute_bridge_pb2.NetworkComputeRequest(
        input_data=input_data, server_config=server_data)

    response = network_compute_client.network_compute_bridge_command(process_img_req)

    if len(response.object_in_image) <= 0:
        print('No objects found')
    else:
        print('Got ' + str(len(response.object_in_image)) + ' objects.')

    if options.image_source is not None:
        # We asked for an image to be taken, so the return proto should have an image in it.
        dtype = np.uint8
        img = np.frombuffer(response.image_response.shot.image.data, dtype=dtype)
        if response.image_response.shot.image.format == image_pb2.Image.FORMAT_RAW:
            img = img.reshape(response.image_response.shot.image.rows,
                              response.image_response.shot.image.cols)
        else:
            img = cv2.imdecode(img, -1)
    else:
        # To save bandwidth, the network_compute_bridge service won't re-send us back our own
        # image.
        img = image_in

    # The image always comes back in the raw orientation.  Rotate it to horizontal so that we can
    # visualize it the same as it was processed.
    img, rotmat = rotate_image_nocrop(img, response.image_rotation_angle)

    # Convert to color for nicer drawing
    if len(img.shape) < 3:
        img = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)

    # Draw bounding boxes in the image for all the detections.
    for obj in response.object_in_image:
        print(obj)
        conf_msg = wrappers_pb2.FloatValue()
        obj.additional_properties.Unpack(conf_msg)
        confidence = conf_msg.value

        polygon = []
        min_x = float('inf')
        min_y = float('inf')
        for v in obj.image_properties.coordinates.vertexes:
            # If we are rotating the output image, make sure to rotate the bounding box points
            # as well
            x, y = rotate_point(v.x, v.y, rotmat)
            polygon.append([x, y])
            min_x = min(min_x, x)
            min_y = min(min_y, y)

        polygon = np.array(polygon, np.int32)
        polygon = polygon.reshape((-1, 1, 2))
        cv2.polylines(img, [polygon], True, (0, 255, 0), 2)

        caption = "{} {:.3f}".format(obj.name, confidence)
        cv2.putText(img, caption, (int(min_x), int(min_y)), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
                    (0, 255, 0), 2)

    cv2.imwrite('identify_object_output.jpg', img)
Beispiel #6
0
def _send_request(server, image_path, model, confidence, verbose=False):
    start = time.time()

    channel = grpc.insecure_channel(server)
    stub = network_compute_bridge_service_pb2_grpc.NetworkComputeBridgeWorkerStub(channel)
    server_data = network_compute_bridge_pb2.NetworkComputeServerConfiguration(service_name='test')
    # Read the input image.
    image_in = cv2.imread(image_path)
    if image_in is None:
        print('Error: failed to read "' + image_path + '".  Does the file exist?')
        sys.exit(1)

    rgb = cv2.cvtColor(image_in, cv2.COLOR_BGR2RGB)

    success, im_buffer = cv2.imencode(".jpg", rgb)

    if not success:
        print('Error: failed to encode input image as a jpg.  Abort.')
        sys.exit(1)

    height = image_in.shape[0]
    width = image_in.shape[1]

    image_proto = image_pb2.Image(format=image_pb2.Image.FORMAT_JPEG, cols=width, rows=height,
                                  data=im_buffer.tobytes(),
                                  pixel_format=image_pb2.Image.PIXEL_FORMAT_RGB_U8)

    input_data = network_compute_bridge_pb2.NetworkComputeInputData(image=image_proto,
                                                                    model_name=model,
                                                                    min_confidence=confidence)

    process_img_req = network_compute_bridge_pb2.NetworkComputeRequest(
        input_data=input_data, server_config=server_data)

    response = stub.NetworkCompute(process_img_req)
    end = time.time()
    latency = end - start
    print(f'latency: {latency * 1000} ms')

    if verbose:
        if len(response.object_in_image) <= 0:
            print('No objects found')
        else:
            print('Got ' + str(len(response.object_in_image)) + ' objects.')

        # Draw bounding boxes in the image for all the detections.
        for obj in response.object_in_image:
            print(obj)
            conf_msg = wrappers_pb2.FloatValue()
            obj.additional_properties.Unpack(conf_msg)
            confidence = conf_msg.value

            polygon = []
            min_x = float('inf')
            min_y = float('inf')
            for v in obj.image_properties.coordinates.vertexes:
                polygon.append([v.x, v.y])
                min_x = min(min_x, v.x)
                min_y = min(min_y, v.y)

            polygon = np.array(polygon, np.int32)
            polygon = polygon.reshape((-1, 1, 2))
            cv2.polylines(image_in, [polygon], True, (0, 255, 0), 2)

            caption = "{} {:.3f}".format(obj.name, confidence)
            cv2.putText(image_in, caption, (int(min_x), int(min_y)), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
                        (0, 255, 0), 2)

        cv2.imwrite(append_str_to_filename(image_path, 'detections'), image_in)
    return latency