【问题标题】:Google vision API is not working after upload image to Firebase将图像上传到 Firebase 后,Google Vision API 无法正常工作
【发布时间】:2021-09-08 10:31:10
【问题描述】:

我使用 google vision API 使用 React-Native 构建了一个图像检测移动应用程序(例如塑料瓶、铝罐、牛奶罐等)。

之前运行良好,并成功得到响应。

但是在我为商店图片添加 Firebase 图片上传功能后,它(google vision api)不起作用。

在我的猜测中,Firebase 图片上传google vision API 似乎相互冲突且不兼容。

或者在我的图片上传功能中,似乎有错误,但我仍然不确定是什么问题。以下是我的代码。

  const takePicture = async () => {
    if (this.camera) {
      const options = { quality: 0.5, base64: true };
      const data = await this.camera.takePictureAsync(options);
      setScannedURI(data.uri)
      imageUploadToFirebase(data)
      // callGoogleVisionApi(data.base64)  //============> After comment image upload function(above line) and if I call vision api here, it works well.
      setIsLoading(true)
    }
  };

  const imageUploadToFirebase = (imageData) => {
    const Blob = RNFetchBlob.polyfill.Blob;    //firebase image upload
    const fs = RNFetchBlob.fs;
    window.XMLHttpRequest = RNFetchBlob.polyfill.XMLHttpRequest;
    window.Blob = Blob;
    const Fetch = RNFetchBlob.polyfill.Fetch
    window.fetch = new Fetch({
      auto: true,
      binaryContentTypes: [
        'image/',
        'video/',
        'audio/',
        'foo/',
      ]
    }).build()
    let uploadBlob = null;
    var path = Platform.OS === "ios" ? imageData.uri.replace("file://", "") : imageData.uri
    var newItemKey = Firebase.database().ref().child('usersummary').push().key;
    var _name = newItemKey + 'img.jpg';
    setIsLoading(true)
    fs.readFile(path, "base64")
      .then(data => {
        let mime = "image/jpg";
        return Blob.build(data, { type: `${mime};BASE64` });
      })
      .then(blob => {
        uploadBlob = blob;
        Firebase.storage()
          .ref("scannedItems/" + _name)
          .put(blob)
          .then(() => {
            uploadBlob.close();
            return Firebase.storage()
              .ref("scannedItems/" + _name)
              .getDownloadURL();
          })
          .then(async uploadedFile => {
            setFirebaseImageURL(uploadedFile)
            // callGoogleVisionApi(imageData.base64)  //============> If I call here, it didn't work.
          })
          .catch(error => {
            console.log({ error });
          });
      });
  }

这是我的 callGoogleVisionApi 函数。

  const callGoogleVIsionApi = async (base64) => {
    let googleVisionRes = await fetch(config.googleCloud.api + config.googleCloud.apiKey, {
      method: 'POST',
      body: JSON.stringify({
        "requests": [{
          "image": { "content": base64 },
          features: [
            { type: "LABEL_DETECTION", maxResults: 30 },
            { type: "WEB_DETECTION", maxResults: 30 }
          ],
        }]
      })
    })
      .catch(err => { console.log('Network error=>: ', err) })
    await googleVisionRes.json()
      .then(googleResp => {
        if (googleResp) {
          let responseArray = googleResp.responses[0].labelAnnotations
          responseArray.map((item, index) => {
            if (item.description != "" && item.description != undefined && item.description != null) {
              newArr.push(item.description)
            }
          })
        } 
      }).catch((error) => {console.log(error)})
  }

注意:如果我在从 google vision api 获得结果后将图像上传到 firebase,则对 vision api 的第二次调用不起作用。

我添加了我的 callGoogleVIsionApi 函数。 (没有 Firebase 图片上传功能也可以正常使用。)

这个问题的解决方法是什么?

【问题讨论】:

  • 看起来在您的 callGoogleVisionAPI 函数中您传递了一个 base64 字符串。您应该在 API 调用中提交图像 URI,而不是 base64 编码的数据。
  • 我添加了我的callGoogleVIsionApi 函数。但实际上,如果没有 Firebase 图片上传功能,它也可以正常工作。
  • 你能读取图像文件并使用以下代码将其转换为base 64:var fs = require('fs'); var imageFile = fs.readFileSync('/path/to/file'); var 编码 = Buffer.from(imageFile).toString('base64');然后将编码后的base 64数据添加到callGoogleVisionApi的"image": { "content": base64 } as "请求列表中:image指定图片文件。可以作为base64编码的字符串发送,云存储文件位置,或作为可公开访问的 URL”,根据 documentation
  • @SatelBill 您的问题解决了吗?您是否尝试过提供给您的解决方案?我们期待有关此问题的一些更新。

标签: javascript firebase react-native google-cloud-firestore google-vision


【解决方案1】:

我找到了原因,但我仍然很好奇为什么。 Fetch blob 和 google vision 似乎相互冲突。 我更改了 Firebase 图片上传功能,效果很好。

以下是我修改后的 Firebase 图片上传功能。

const imageUploadToFirebase = () => {
      var path = Platform.OS === 'ios' ? scannedURI.replace('file://', '') : scannedURI;
      const response = await fetch(path)
      const blob = await response.blob();
      var newItemKey = Firebase.database()
        .ref()
        .child('usersummary')
        .push().key;
      var _name = newItemKey + 'img.jpg';
      Firebase.storage()
        .ref(_name)
        .put(blob)
        .then(() => {
          return Firebase.storage()
            .ref(_name)
            .getDownloadURL();
        })
        .then(async uploadedFile => {
          let image = selectImage(sendItem.name?.toLowerCase());
          sendItem.image = image;
          sendItem.scannedURI = uploadedFile;
          AsyncStorage.getItem('@scanedItemList')
            .then(res => {
              if (res != null && res != undefined && res != '') {
                let result = `${res}#${JSON.stringify(sendItem)}`;
                AsyncStorage.setItem('@scanedItemList', result);
              } else {
                AsyncStorage.setItem(
                  '@scanedItemList',
                  JSON.stringify(sendItem),
                );
              }
            })
            .catch(err => console.log(err));
        })
        .catch(error => {
          console.log({error});
        });
}

【讨论】:

    【解决方案2】:

    我不确定您是否使用@google-cloud/vision 包(在callGoogleVisionApi() 函数中),但据我所知,它是用于服务器端并使用服务帐户进行身份验证。作为此方法的替代方法,您可以将 Cloud Storage Triggers 用于 Cloud 函数,该函数将在上传新文件时触发函数,然后使用 Cloud Vision API。

    【讨论】:

    • 抱歉我的粗心大意。我添加了我的callGoogleVIsionApi 函数。我没有使用任何包。我刚刚使用了谷歌视觉 API。
    • @SatelBill 你能分享一个错误截图吗?我不确定你的意思是它不起作用?
    【解决方案3】:

    Google Vision API 可以使用 base64 编码的图像、可公开访问的 HTTP URI 或 Google 云存储中的 blob。

    为了使用 HTTP URI,您应该从 callGoogleVisionAPI 函数中更改 JSON 负载:

    {
            "requests": [{
              "image": { "content": base64 },
              features: [
                { type: "LABEL_DETECTION", maxResults: 30 },
                { type: "WEB_DETECTION", maxResults: 30 }
              ],
            }]
          }
    

    到这里:

    {
            "requests": [{
              "image": { "source": {"imageUri": 'https://PUBLIC_URI_FOR_THE_IMAGE' }  },
              features: [
                { type: "LABEL_DETECTION", maxResults: 30 },
                { type: "WEB_DETECTION", maxResults: 30 }
              ],
            }]
          }
    

    这里有更好的解释:Make a Vision API request

    【讨论】:

    • 它可以是 base 64 编码的字符串,也可以是 documentation
    • @PriyashreeBhadra-OP 不想使用该解决方案。问题指出图像数据必须上传到 firebase 并且 vision api 必须从中获取(通过 http:// 或 gs:// url)
    猜你喜欢
    • 2018-05-14
    • 2017-04-30
    • 1970-01-01
    • 1970-01-01
    • 2017-12-27
    • 1970-01-01
    • 2019-01-30
    • 1970-01-01
    • 2021-06-16
    相关资源
    最近更新 更多