🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
REST

REST(Representational State Transfer)はwebアプリケーションの構築スタイルの一種です。HTTP GET/POSTによってリクエストを送信し、レスポンスはXMLで返されます。SOAPのようなRPCの構築と比べるとサーバからクライアントを分離することが出来る為、人気です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Azure

Azureは、マイクロソフトのクラウド プラットフォームで、旧称は Windows Azureです。PaaSとIaaSを組み合わせることで、 コンピューティング・ストレージ・データ・ネットワーキング・アプリケーションなど多くの機能を持ちます。

Q&A

解決済

2回答

5463閲覧

JavaScriptで、画像をFaceAPIにアップロードして表情認識したい

shinybull

総合スコア4

REST

REST(Representational State Transfer)はwebアプリケーションの構築スタイルの一種です。HTTP GET/POSTによってリクエストを送信し、レスポンスはXMLで返されます。SOAPのようなRPCの構築と比べるとサーバからクライアントを分離することが出来る為、人気です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Azure

Azureは、マイクロソフトのクラウド プラットフォームで、旧称は Windows Azureです。PaaSとIaaSを組み合わせることで、 コンピューティング・ストレージ・データ・ネットワーキング・アプリケーションなど多くの機能を持ちます。

0グッド

0クリップ

投稿2019/10/19 14:54

前提・実現したいこと

Microsoft FaceAPI を使用して、webページ上に表示された画像を認識したいと思っています。現在は、試験的にインターネット上にある画像を表示していますが、今後画像を表示している領域にはcanvasなどを利用して表示する予定です。
どこかのサーバーにある画像ではなく、PC上でアップロードしたり、処理をしてからFaceAPIに送信したいのですが、うまくいきません。

発生している問題・エラーメッセージ

blobに変換して画像を送信できない

Bad Request (400): Invalid image URL.

FaceAPIは application/octet-stream として送信する必要があるという情報を得たため、face.jsの57行目を application/json から application/octet-stream に変更したら、画像が小さすぎるというエラーが発生

Bad Request (400): Image size is too small.

該当のソースコード

html

1<!DOCTYPE html> 2<html> 3 4<head> 5 <title>Detect Faces Sample</title> 6 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script> 7</head> 8 9<body> 10 <script src="face.js"></script> 11 <h1>Detect Faces:</h1> 12 Enter the URL to an image that includes a face or faces, then click 13 the <strong>Analyze face</strong> button.<br><br> 14 Image to analyze: <input type="text" name="inputImage" id="inputImage" 15 value="https://upload.wikimedia.org/wikipedia/commons/c/c3/RH_Louise_Lillian_Gish.jpg" /> 16 <button onclick="processImage()">Analyze face</button><br><br> 17 <div id="wrapper" style="width:1020px; display:table;"> 18 <div id="jsonOutput" style="width:600px; display:table-cell;"> 19 Response:<br><br> 20 <textarea id="responseTextArea" class="UIInput" style="width:580px; height:400px;"></textarea> 21 </div> 22 <div id="imageDiv" style="width:420px; display:table-cell;"> 23 Source image:<br><br> 24 <img id="sourceImage" width="400" /> 25 </div> 26 </div> 27</body> 28 29</html>

js

1makeblob = function (dataURL) { 2 var BASE64_MARKER = ';base64,'; 3 if (dataURL.indexOf(BASE64_MARKER) == -1) { 4 var parts = dataURL.split(','); 5 var contentType = parts[0].split(':')[1]; 6 var raw = decodeURIComponent(parts[1]); 7 return new Blob([raw], { type: contentType }); 8 } 9 var parts = dataURL.split(BASE64_MARKER); 10 var contentType = parts[0].split(':')[1]; 11 var raw = window.atob(parts[1]); 12 var rawLength = raw.length; 13 14 var uInt8Array = new Uint8Array(rawLength); 15 16 for (var i = 0; i < rawLength; ++i) { 17 uInt8Array[i] = raw.charCodeAt(i); 18 } 19 20 return new Blob([uInt8Array], { type: contentType }); 21} 22 23function processImage() { 24 // Replace <Subscription Key> with your valid subscription key. 25 var subscriptionKey = "<Subscription Key>"; 26 27 // NOTE: You must use the same region in your REST call as you used to 28 // obtain your subscription keys. For example, if you obtained your 29 // subscription keys from westus, replace "westcentralus" in the URL 30 // below with "westus". 31 // 32 // Free trial subscription keys are generated in the westcentralus region. 33 // If you use a free trial subscription key, you shouldn't need to change 34 // this region. 35 var uriBase = 36 "https://westcentralus.api.cognitive.microsoft.com/face/v1.0/detect"; 37 38 // Request parameters. 39 var params = { 40 "returnFaceId": "true", 41 "returnFaceLandmarks": "false", 42 "returnFaceAttributes": 43 "age,gender,headPose,smile,facialHair,glasses,emotion," + 44 "hair,makeup,occlusion,accessories,blur,exposure,noise" 45 }; 46 47 // Display the image. 48 var sourceImageUrl = document.getElementById("inputImage").value; 49 document.querySelector("#sourceImage").src = sourceImageUrl; 50 51 // Perform the REST API call. 52 $.ajax({ 53 url: uriBase + "?" + $.param(params), 54 55 // Request headers. 56 beforeSend: function (xhrObj) { 57 xhrObj.setRequestHeader("Content-Type", "application/json"); 58 xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key", subscriptionKey); 59 }, 60 61 processData: false, 62 type: "POST", 63 64 // Request body. 65 // data: '{"url": ' + '"' + sourceImageUrl + '"}', 66 data: makeblob(sourceImageUrl), 67 }) 68 69 .done(function (data) { 70 // Show formatted JSON on webpage. 71 $("#responseTextArea").val(JSON.stringify(data, null, 2)); 72 73 var emodata = (data[0].faceAttributes.emotion); 74 75 }) 76 .fail(function (jqXHR, textStatus, errorThrown) { 77 // Display error message. 78 var errorString = (errorThrown === "") ? 79 "Error. " : errorThrown + " (" + jqXHR.status + "): "; 80 errorString += (jqXHR.responseText === "") ? 81 "" : (jQuery.parseJSON(jqXHR.responseText).message) ? 82 jQuery.parseJSON(jqXHR.responseText).message : 83 jQuery.parseJSON(jqXHR.responseText).error.message; 84 alert(errorString); 85 }); 86};

試したこと

JavaScriptコードは、ほとんどこのサイトからコピペしたものです。
HTMLのコードは、こちらのマイクロソフトのサンプルを元にJSファイルを別ファイルで作成するようにしました。

25行目の <Subscription Key> と、36行目の https://westcentralus.api.cognitive.microsoft.com/face/v1.0/detect は適切なものに書き換えてから実行しました。
ほかのサイトや、ローカルにある画像でも試してみましたが、結果は変わりませんでした。

補足情報(FW/ツールのバージョンなど)

Windows10 Pro
Google Chrome 最新バージョン
バージョン: 77.0.3865.120(Official Build)(64 ビット)
MicrosoftAzureの無料試用版 (今日登録しました。)

参考にしたサイト

クイック スタート:REST API と JavaScript を使用して画像内の顔を検出する - Azure Cognitive Services | Microsoft Docs
FaceAPIを使った感情分析 - Qiita
JavaScript - Computer Vision APIでファイル添付でできるようにしたい|teratail
FaceApiを試す。(ローカルよりファイルをアップロードして結果を取得) - m_shige1979のささやかな抵抗と欲望の日々
Microsofrt AzureのFace APIを使って笑顔をAIに判断してもらおう - Qiita

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

回答にはならないのですが、「FaceAPIを使った感情分析」には、

今回カメラ起動、スクリーンショット取得は割愛します。

も、

送信するためには画像データをbase64にエンコードする必要があります。(ここが一番ハマりました)

の詳細も書かれていない(おそらく makeblob には base64 エンコード後のURLを渡さなければならないのに)ので、参考にするのは難しそうですね。

投稿2019/10/28 07:50

NakamuraYoichi

総合スコア374

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

NakamuraYoichi

2019/10/28 07:52

この方針で行く場合に、足りないところを補う記事が見つかると良いのですが。
NakamuraYoichi

2019/10/28 07:54

別の方針を考えてもよいかもしれません。例えば、まずストレージにアップロードして、そのURLをFace APIに投げるようにするとか(それでできるか分かりませんが)。
guest

0

自己解決

自己解決しました。色々調べてみて、なんとか動くようになりました。

htmlファイルと同じフォルダに、camera.js と、face.js を保存します。
<Subscription Key><My Endpoint String> を適切なものに書き換えれば動作するはずです。

html

html

1 2<!DOCTYPE html> 3<html> 4 5<head> 6 <title>Detect Faces Sample</title> 7 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script> 8</head> 9 10<body> 11 <script src="./face.js"></script> 12 <h1>Detect Faces:</h1> 13 <div id="wrapper" style="width:1020px; display:table;"> 14 <div id="jsonOutput" style="width:600px; display:table-cell;"> 15 Response:<br><br> 16 <textarea id="responseTextArea" class="UIInput" style="width:580px; height:400px;"></textarea> 17 </div> 18 <div id="imageDiv" style="width:420px; display:table-cell;"> 19 Source image:<br><br> 20 <button id="start_btn">映像表示開始</button> 21 <button onclick="copyFrame()">認識実行</button> 22 <video id="video_area" style="background-color: #000" autoplay></video> 23 <canvas id="capture_image"></canvas> 24 </div> 25 </div> 26 <script src="./camera.js"></script> 27</body> 28 29</html> 30 31

face.js

js

1 2function processImage() { 3 // Replace <Subscription Key> with your valid subscription key. 4 var subscriptionKey = "<Subscription Key>"; 5 6 var uriBase = 7 "https://<My Endpoint String>.com/face/v1.0/detect"; 8 9 // Request parameters. 10 var params = { 11 "returnFaceId": "true", 12 "returnFaceLandmarks": "false", 13 "returnFaceAttributes": 14 "age,gender,headPose,smile,facialHair,glasses,emotion," + 15 "hair,makeup,occlusion,accessories,blur,exposure,noise" 16 }; 17 18 // Display the image. 19 var type = 'image/jpeg'; 20 var dataurl = capture_image.toDataURL(type); 21 var bin = atob(dataurl.split(',')[1]); 22 var buffer = new Uint8Array(bin.length); 23 for (var i = 0; i < bin.length; i++) { 24 buffer[i] = bin.charCodeAt(i); 25 } 26 var blob = new Blob([buffer.buffer], { type: type }); 27 28 // Perform the REST API call. 29 $.ajax({ 30 url: uriBase + "?" + $.param(params), 31 32 // Request headers. 33 beforeSend: function (xhrObj) { 34 xhrObj.setRequestHeader("Content-Type", "application/octet-stream"); 35 xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key", subscriptionKey); 36 }, 37 38 processData: false, 39 type: "POST", 40 41 // Request body. 42 data: blob, 43 }) 44 45 .done(function (data) { 46 // Show formatted JSON on webpage. 47 $("#responseTextArea").val(JSON.stringify(data, null, 2)); 48 }) 49 50 .fail(function (jqXHR, textStatus, errorThrown) { 51 // Display error message. 52 var errorString = (errorThrown === "") ? 53 "Error. " : errorThrown + " (" + jqXHR.status + "): "; 54 errorString += (jqXHR.responseText === "") ? 55 "" : (jQuery.parseJSON(jqXHR.responseText).message) ? 56 jQuery.parseJSON(jqXHR.responseText).message : 57 jQuery.parseJSON(jqXHR.responseText).error.message; 58 alert(errorString); 59 }); 60}; 61 62

camera.js

js

1 2const $start = document.getElementById('start_btn'); 3const $video = document.getElementById('video_area'); 4 5$start.addEventListener('click', () => { 6 navigator.mediaDevices.getUserMedia({ video: true, audio: false }) 7 .then(stream => $video.srcObject = stream) 8 .catch(err => alert(`${err.name} ${err.message}`)); 9}, false); 10 11function copyFrame() { 12 var canvas_capture_image = document.getElementById('capture_image'); 13 var cci = canvas_capture_image.getContext('2d'); 14 var va = document.getElementById('video_area'); 15 16 canvas_capture_image.width = va.videoWidth; 17 canvas_capture_image.height = va.videoHeight; 18 cci.drawImage(va, 0, 0); 19 20 processImage(); 21} 22 23

ポイントは、

  • webカメラの映像をcanvasにいったんコピーしてからblobに変換していること
  • application/jsonapplication/octet-stream に書き換え
  • processData: false, を追加

です。

参考:
クイック スタート:REST API と JavaScript を使用して画像内の顔を検出する - Azure Cognitive Services | Microsoft Docs
FaceAPIを使った感情分析 - Qiita
HTML5のWebRTCでPCに接続されたカメラ映像をウェブブラウザー上に表示してコマ画像を保存したい - Qiita
Canvas に描いた画像を png などの形式の Blob に変換する方法: Tender Surrender

投稿2019/11/19 05:25

shinybull

総合スコア4

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問