Android загрузка изображения приложения на Python Flask проблема ответа сервера после обнаружения объекта TensorFlow - PullRequest
0 голосов
/ 06 апреля 2020
Приложение

My android захватывает изображение и отправляет его на сервер Python Flask, который выполняет обнаружение объектов с помощью API-интерфейса обнаружения объектов TensorFlow. Мое android приложение использует библиотеку OkHttp java для http-соединения.

Загрузка изображений и обнаружение объектов после этого работает. Единственная проблема, с которой я столкнулся, это то, что я не могу заставить сервер отправить ответ приложению.

Мой android код подключения клиента (здесь нет проблем, просто для справки):

public class Client {

Context context;
AssetManager mngr;

public Client(Context context) {
    mngr = context.getAssets();
    this.context = context;
}
private static final Pattern IP_ADDRESS
        = Pattern.compile(
        "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
                + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
                + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
                + "|[1-9][0-9]|[0-9]))");

public void connectServer() {
    String ip = "192.168.1.4";
    String portNumber = "5000";

    String postUrl = "http://" + ip + ":" + portNumber + "/";

    MultipartBody.Builder multipartBodyBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inPreferredConfig = Bitmap.Config.RGB_565;
    ByteArrayOutputStream stream = new ByteArrayOutputStream();

    try{
        File directoryToStore = context.getExternalFilesDir("Images");
        if (!directoryToStore.exists()) {
            if (directoryToStore.mkdir()) ; //directory is created;
        }
        final File file = new File(directoryToStore, "pic.jpg");
        String myPath = file.getAbsolutePath();

        Bitmap bitmap = BitmapFactory.decodeFile(myPath, options);
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
    } catch (Exception e) {
        e.printStackTrace();
        return;
    }

    byte[] byteArray = stream.toByteArray();

    multipartBodyBuilder.addFormDataPart("image", "pic.jpg", RequestBody.create(MediaType.parse("image/*jpg"), byteArray));

    RequestBody postBodyImage = multipartBodyBuilder.build();

    postRequest(postUrl, postBodyImage);
}

public void postRequest(String postUrl, RequestBody postBody) {

    OkHttpClient client = new OkHttpClient();

    Request request = new Request.Builder()
            .url(postUrl)
            .post(postBody)
            .build();

    client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            // Cancel the post on failure.
            call.cancel();
            Log.d("FAIL", e.getMessage());
        }

        @Override
        public void onResponse(Call call, final Response response) throws IOException {
            try {
                System.out.println("Server's Response\n" + response.body().string());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    });
}
}

Это мой python файл:

############################################# Start of object detection(no problem here, just for reference)
utils_ops.tf = tf.compat.v1
tf.gfile = tf.io.gfile
PATH_TO_LABELS = 'D:\\TensorFlow\\models\\research\\object_detection\\data\\oid_v4_label_map.pbtxt'
category_index = label_map_util.create_category_index_from_labelmap(PATH_TO_LABELS, use_display_name=True)

def run_inference_for_single_image(model, image):
  image = np.asarray(image)
  # The input needs to be a tensor, convert it using `tf.convert_to_tensor`.
  input_tensor = tf.convert_to_tensor(image)
  # The model expects a batch of images, so add an axis with `tf.newaxis`.
  input_tensor = input_tensor[tf.newaxis,...]

  # Run inference
  output_dict = model(input_tensor)

  # All outputs are batches tensors.
  # Convert to numpy arrays, and take index [0] to remove the batch dimension.
  # We're only interested in the first num_detections.
  num_detections = int(output_dict.pop('num_detections'))
  output_dict = {key:value[0, :num_detections].numpy() 
                 for key,value in output_dict.items()}
  output_dict['num_detections'] = num_detections

  # detection_classes should be ints.
  output_dict['detection_classes'] = output_dict['detection_classes'].astype(np.int64)

  # Handle models with masks:
  if 'detection_masks' in output_dict:
    # Reframe the the bbox mask to the image size.
    detection_masks_reframed = utils_ops.reframe_box_masks_to_image_masks(
              output_dict['detection_masks'], output_dict['detection_boxes'],
               image.shape[0], image.shape[1])      
detection_masks_reframed = tf.cast(detection_masks_reframed > 0.5,
                                   tf.uint8)
output_dict['detection_masks_reframed'] = detection_masks_reframed.numpy()

return output_dict

def show_inference(model, image_path):
  # the array based representation of the image will be used later in order to prepare the
  # result image with boxes and labels on it.
  image_np = np.array(Image.open(image_path))
  # Actual detection.
  output_dict = run_inference_for_single_image(model, image_np)
  # Visualization of the results of a detection.
  vis_util.visualize_boxes_and_labels_on_image_array(
      image_np,
      output_dict['detection_boxes'],
      output_dict['detection_classes'],
      output_dict['detection_scores'],
      category_index,
      instance_masks=output_dict.get('detection_masks_reframed', None),
      use_normalized_coordinates=True,
      line_thickness=8)

  name = "Image" + ".jpg"
  img = Image.fromarray(image_np)
  plt.imsave(name,image_np)

####################################################### End of Object detection

app = flask.Flask(__name__)
@app.route('/', methods = ['GET', 'POST'])
def handle_request():
    imagefile = flask.request.files['image']
    filename = werkzeug.utils.secure_filename(imagefile.filename)
    print("\nReceived image File name : " + imagefile.filename)
    imagefile.save(filename)

    model_dir = "D:\\Models\\faster_rcnn_inception_resnet_v2_atrous_oid_v4_2018_12_12"
    model_dir = pathlib.Path(model_dir)/"saved_model"

    model = tf.saved_model.load(str(model_dir))
    model = model.signatures['serving_default']

    PATH_TO_TEST_IMAGES_DIR = pathlib.Path('C:\\Users\\Bhavin\\Desktop\\results')
    TEST_IMAGE_PATHS = sorted(list(PATH_TO_TEST_IMAGES_DIR.glob("*.jpg")))
    TEST_IMAGE_PATHS

    print(model.inputs)
    model.output_dtypes
    model.output_shapes

    for image_path in TEST_IMAGE_PATHS:
      show_inference(model, image_path)

    return "Image Uploaded & Processed Successfully"  # I dont get any response in my android studio debug menu

app.run(host="192.168.1.4", port=5000, debug=True)

Извините за огромный блок кода. Часть обнаружения объекта и часть кода android работают, но я просто для справки. Я прокомментировал соответствующую функцию для соединения в коде python.

...