1

我正在尝试通过 Firebase 函数中经过训练的 AutoML 模型为图像提供预测标签。此图像存储在 Google Cloud Storage 中。我尝试以这种方式读取图像:

const gcs = require('@google-cloud/storage')();
const myBucket = gcs.bucket(object.bucket);
const file = myBucket.file(object.name);
const stream = file.createReadStream();

var data = '';
stream.on('error', function(err) {
  console.log("error");
})
.on('data', function(chunk) {
  data = data + chunk;
  console.log("Writing data");
})
.on('end', function() {
});

读完数据后,我将数据转换为“二进制”格式

var encoded = new Buffer(data)
encoded = encoded.toString('binary');

但我将这些编码数据输入“imageBytes”:

const payload = {
  "image": {
    "imageBytes": encoded
  },
};
var formattedName = client.modelPath(project, location, model);

var request = {
  name: formattedName,
  payload: payload,
};

client.predict(request)
.then(responses => {
  console.log("responses:", responses);
  var response = responses[0];

  console.log("response:", response);
})
.catch(err => {
  console.error(err);
});

它会抛出一个错误:

Error: invalid encoding
at Error (native)
at Object.decode (/user_code/node_modules/@google-cloud/automl/node_modules/@protobufjs/base64/index.js:105:19)
at Type.Image$fromObject [as fromObject] (eval at Codegen (/user_code/node_modules/@google-cloud/automl/node_modules/@protobufjs/codegen/index.js:50:33), <anonymous>:9:15)
at Type.ExamplePayload$fromObject [as fromObject] (eval at Codegen (/user_code/node_modules/@google-cloud/automl/node_modules/@protobufjs/codegen/index.js:50:33), <anonymous>:10:20)
at Type.PredictRequest$fromObject [as fromObject] (eval at Codegen (/user_code/node_modules/@google-cloud/automl/node_modules/@protobufjs/codegen/index.js:50:33), <anonymous>:13:22)
at serialize (/user_code/node_modules/@google-cloud/automl/node_modules/grpc/src/protobuf_js_6_common.js:70:23)
at Object.final_requester.sendMessage (/user_code/node_modules/@google-cloud/automl/node_modules/grpc/src/client_interceptors.js:802:37)
at InterceptingCall._callNext (/user_code/node_modules/@google-cloud/automl/node_modules/grpc/src/client_interceptors.js:418:43)
at InterceptingCall.sendMessage (/user_code/node_modules/@google-cloud/automl/node_modules/grpc/src/client_interceptors.js:460:8)
at InterceptingCall._callNext (/user_code/node_modules/@google-cloud/automl/node_modules/grpc/src/client_interceptors.js:424:12)

但是如果我用'base64'编码图像,它会抛出一个错误:

Error: 3 INVALID_ARGUMENT: Provided image is not valid.
at Object.exports.createStatusError (/user_code/node_modules/@google-cloud/automl/node_modules/grpc/src/common.js:87:15)
at Object.onReceiveStatus (/user_code/node_modules/@google-cloud/automl/node_modules/grpc/src/client_interceptors.js:1188:28)
at InterceptingListener._callNext (/user_code/node_modules/@google-cloud/automl/node_modules/grpc/src/client_interceptors.js:564:42)
at InterceptingListener.onReceiveStatus (/user_code/node_modules/@google-cloud/automl/node_modules/grpc/src/client_interceptors.js:614:8)
at callback (/user_code/node_modules/@google-cloud/automl/node_modules/grpc/src/client_interceptors.js:841:24)
code: 3,
metadata: Metadata { _internal_repr: { 'grpc-server-stats-bin': [Object] } },
details: 'Provided image is not valid.' 

我也在 Python 中尝试了本地图像文件预测,它使用“二进制”二进制表示并且效果很好。当我在 Python 中使用“base64”时,它将返回“提供的图像无效”。就像在firebase函数中一样。

我很困惑我是否以错误的方式从 Cloud Storage 读取图像,或者我以错误的方式对图像进行编码。

Firebase 功能中的完整代码:

const automl = require('@google-cloud/automl');
var client = new automl.v1beta1.PredictionServiceClient();
const gcs = require('@google-cloud/storage')();
const myBucket = gcs.bucket(object.bucket);
const file = myBucket.file(object.name);
const stream = file.createReadStream();
var data = '';
stream.on('error', function(err) {
  console.log("error");
})
.on('data', function(chunk) {
  data = data + chunk;
  console.log("Writing data");
})
.on('end', function() {
  var encoded = new Buffer(data)
  encoded = encoded.toString('binary');
  console.log("binary:", encoded);

  const payload = {
    "image": {
      "imageBytes": encoded
    },

  };

  var formattedName = client.modelPath(project, location, model);

  var request = {
    name: formattedName,
    payload: payload,
  };

  client.predict(request)
  .then(responses => {
    console.log("responses:", responses);
    var response = responses[0];

    console.log("response:", response);
  })
  .catch(err => {
    console.error(err);
  });
  stream.destroy();
});

Python中的完整代码:

import sys

from google.cloud import automl_v1beta1
from google.cloud.automl_v1beta1.proto import service_pb2

# Import the base64 encoding library.
import base64


def get_prediction(content, project_id, model_id):
  prediction_client = automl_v1beta1.PredictionServiceClient()

  name = 'projects/{}/locations/us-central1/models/{}'.format(project_id, model_id)
  payload = {'image': {'image_bytes': content }}

  params = {}
  request = prediction_client.predict(name, payload, params)
  return request  # waits till request is returned

if __name__ == '__main__':
  file_path = sys.argv[1]
  project_id = sys.argv[2]
  model_id = sys.argv[3]
  with open(file_path, 'rb') as ff:
    content = ff.read()
    print(content)
    # Encoded as base64
    # content = base64.b64encode(content)

  print(get_prediction(content, project_id,  model_id))
4

1 回答 1

0

我使用 file.download(),它可以工作。

file.download().then(imageData => {
  const image = imageData[0];
  const buffer = image.toString('base64');
  const payload = {
    "image": {
      "imageBytes": buffer
    }
  }
  const request = {
    name: formattedName,
    payload: payload
  };
  client.predict(request).then(result => {
    console.log('predict:', result);
  }).catch(err => console.error(err));
});
于 2018-08-08T01:45:17.943 回答