将图像从网络摄像头发布到 Azure Face Api

Posting An Image from Webcam to Azure Face Api

我正在尝试将我从网络摄像头获取的图像上传到 Microsoft Azure Face Api。我从 canvas.toDataUrl(‘image/png’) 获取包含数据 Uri 的图像。我将内容类型更改为 application/octet-stream,当我将数据 URI 附加到 post 请求时,我收到错误请求 (400) 无效人脸图像。如果我将附加数据更改为 Blob,我将停止接收错误,但我只会返回一个空数组而不是 JSON 对象。如果能为我指明正确的方向,我将不胜感激。

谢谢!

哦,你真幸运,我在 2 天前刚刚(成功!)尝试过这个。

将 base64 编码的 JPEG 发送到人脸 API 效率非常低,编码输出字节与输入字节的比率为 4:3(33% 的开销)。只需发送一个字节数组即可,文档 mention it briefly.

并尝试读取为 JPEG 而不是 PNG,这只会浪费网络摄像头镜头的带宽。

    ...

    var dataUri = canvas.toDataURL('image/' + format);
    var data = dataUri.split(',')[1];
    var mimeType = dataUri.split(';')[0].slice(5)

    var bytes = window.atob(data);
    var buf = new ArrayBuffer(bytes.length);
    var byteArr = new Uint8Array(buf);

    for (var i = 0; i < bytes.length; i++) {
        byteArr[i] = bytes.charCodeAt(i);
    }

    return byteArr;

现在在 $.ajax() 中使用 byteArr 作为您的负载 (data:) for jQuery 或 iDontUnderStandHowWeGotHereAsAPeople() 人们现在使用的任何其他时髦的 JS 框架.

反向时髦的做法是:

var payload = byteArr;

var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://SERVICE_URL');
xhr.setRequestHeader('Content-Type', 'application/octet-stream');
xhr.send(payload);

所以我最终通过将图像作为 blob 对象发送来得到了答案。您首先使用以下方法从 canvas 中获取图像:

let data = canvas.toDataURL('image/jpeg');

之后,您可以通过运行将其重新格式化为blob数据对象:

fetch(data)
  .then(res => res.blob())
  .then(blobData => {
    // attach blobData as the data for the post request
  }

您还需要将 post 请求的内容类型切换为 "application/octet-stream"

扩展 Dalvor 的回答:这是对我有用的 AJAX 调用:

fetch(data)
.then(res => res.blob())
.then(blobData => {
  $.post({
      url: "https://westus.api.cognitive.microsoft.com/face/v1.0/detect",
      contentType: "application/octet-stream",
      headers: {
        'Ocp-Apim-Subscription-Key': '<YOUR-KEY-HERE>'
      },
      processData: false,
      data: blobData
    })
    .done(function(data) {
      $("#results").text(JSON.stringify(data));

    })
    .fail(function(err) {
      $("#results").text(JSON.stringify(err));
    })

完整的演示代码在这里:https://jsfiddle.net/miparnisari/b1zzpvye/

为了节省某人的 6 个小时,我附上了正确的代码。 希望这段代码对你有帮助。

工具

代码

index.tsx

常量和引用

/**
 * Constants
 */
const videoConstraints = {
  width: 1280,
  height: 720,
  facingMode: 'user',
};
/**
 * Refs
 */
const webcamRef = React.useRef<Webcam>(null);

回调函数

const capture = React.useCallback(() => {
  const base64Str = webcamRef.current!.getScreenshot() || '';
  const s = base64Str.split(',');
  const blob = b64toBlob(s[1]);
  callCognitiveApi(blob);
}, [webcamRef]);

渲染中

<Webcam audio={false} ref={webcamRef} screenshotFormat="image/jpeg" videoConstraints={videoConstraints} />
<button onClick={capture}>Capture photo</button>

base64toBlob

感谢creating-a-blob-from-a-base64-string-in-javascript

export const b64toBlob = (b64DataStr: string, contentType = '', sliceSize = 512) => {
  const byteCharacters = atob(b64DataStr);
  const byteArrays = [];

  for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
    const slice = byteCharacters.slice(offset, offset + sliceSize);

    const byteNumbers = new Array(slice.length);
    for (let i = 0; i < slice.length; i++) {
      byteNumbers[i] = slice.charCodeAt(i);
    }

    const byteArray = new Uint8Array(byteNumbers);
    byteArrays.push(byteArray);
  }

  const blob = new Blob(byteArrays, { type: contentType });
  return blob;
};

调用CognitiveApi

import axios from 'axios';

const subscriptionKey: string = 'This_is_your_subscription_key';
const url: string = 'https://this-is-your-site.cognitiveservices.azure.com/face/v1.0/detect';
export const callCognitiveApi = (data: any) => {
  const config = {
    headers: { 'content-type': 'application/octet-stream', 'Ocp-Apim-Subscription-Key': subscriptionKey },
  };
  const response = axios
    .post(url, data, config)
    .then((res) => {
      console.log(res);
    })
    .catch((error) => {
      console.error(error);
    });
};

结果