文章が分かりづらかったので、再構築(2018/6/5)
このページについて
このページはハッカソンを迅速にお楽しみいただくために開発した開発レシピ集です。レシピのまとめページはIBM Cloudのビギナー開発者向け「最初のレシピ」集になります。
あくまで個人の活動として掲載しているので、IBM ソーシャル・コンピューティング・ガイドラインに則っています。
すなわち、このサイトの掲載内容は私自身の見解であり、必ずしもIBMの立場、戦略、意見を代表するものではありません。
はじめに
IBM CloudとはIBM社が提供するクラウドサービスです。
クラウドとは・・・と紙で理解するよりは、実際に使って理解したほうが早いです。
そのため、ここでは画像認識サービスであるVisual Recognitionについてレシピとしてまとめます。
Visual Recognitionを試す
「AIとは・・・」とか「この製品とは・・」とか、細かい話の前に使ってみましょう!
Visual Recognitonのデモサイトを触ってみる。
デモサイトでは、IBM社が収集した画像データに基づいて、学習データを準備しなくても画像認識できる機能があるので、何も準備しなくてもお試しができます。
Visual Recognitionのサイトトップはこちら。
https://www.ibm.com/watson/jp-ja/developercloud/visual-recognition.html
こんな画面が出るはずです。
さっそく「デモを試す」をクリックしましょう。
さっそく「デモを試す」という場所に移動したはずです。
ここの「画像認識Visual Recognitionを試してみる(英語)」を選んでください。
デモサイトに来ました。実は下にスクロールできます。
下にスクロールしましょう。
こんな画像が出るはずです。
右上のような「青色の吹き出し(マニュアル)」が出たら「☓ボタン」を押してください。
(我々にはこのサイトがあるので、読まなくてよいです)
とりあえず、動かしてみましょう。
画面下の画像をクリックしてみてください。
そうすると、右側の文字列が変わるはずです。
[electrical device]とか[memory device]とか書いていますね。
これが、画像認識した結果、Visual Recognitionが認識した結果です。
なお、0.69とか書いているのは、Socreといって、認識の確信度みたいなものです。
よく使うパターンとしては100掛けて、69%と表現したりします。
先ほどと同じように、右側の文字が変わりましたね。[person]とか。
ここで、その下にある「Face Model +」の「+」をクリックしてみましょう。
これらはIBMさんが夜なべして画像認識の学習データを取り込んで、何の準備もなくても、これらの機能が使えるように準備してくれていたのです。すごい!
さて、ここで信じられないという人がいるでしょう。
「予め認識しやすい画像だからでしょ!?」
そんな人のために、画像をアップロードしてテストすることが可能です。
画面のカメラマークをクリックしてみてください。
画像のアップロード方法が出てくるので、適宜選んでください。
さすがにこれ以上の説明は割愛します。
Visual Recognition を作ってみる。
「「All, Right!」「わかったわかった!」、デモサイトは完成しているからね。でも、作るの大変なんでしょう?」という方のために、自作の方法を伝授します!
IBM Cloud環境を準備する
IBM Cloudを無料で使うライト・アカウントを作成未済であれば、以下のサイトで登録ください。
IBM Cloud基本的な使い方
何も購入していないと、こんな感じになりますが、何かを購入すると画像は変わってきます。
Visual Recognitionを導入する
ではさっそく、Visual Recognition(無料)を購入しに行きましょう。
リソース設定の画面が出ましたね。
実は、IBM Cloudはネットショッピングの如く、「ショッピング・カート機能」のようなものです。
ではさっそく、検索バーに「Visual」と入力して、Visual Recognitionと追記しましょう。
そうすると、特にボタンを幼くても、「Watson]「Visual Recognition」と出るはずです。
この「Visual Recoginition」をクリックします。
Visual Recognitionの説明画面が出ましたね。
ここをスクロールしてみましょう。
ショッピングカートのごとく、購入する商品が見れます。
今回は「ライト」無料が選ばれていることを確認して、「作成」ボタンを押しましょう。
Visual Recognitionのツール起動のための画面の開き方
Visual Recognition作成されるとこんな画面が出ます。
でも、次からはログインしてこの画面を出さないといけないので、ここで画面の出し方を試しておきましょう。
ダッシュボード画面が出ました。
さきほどと画面の内容が違うと思います。
画面に迷った方は、このダッシュボード画面を起点に操作してください。
このVisual Recognitionの箇所をクリックすると、次の画面に移動できます。
Visual Recognitionツールを使う
例によってマニュアルポップアップが出るので「☓」をクリックして閉じます。
メニューが立ち上がるので、少しテストをしてみましょう。
先程も説明したとおり、顔認識はIBM社が学習データを準備しているため、我々がデータを準備しなくても、すぐ実用化することができます。
今回は、その環境を利用してテストしてみましょう。
右下に「Drag & Drop」という文字があると思います。
この辺のエリアに画像をDrag&Dropしてみましょう。
はい、これでVisual Recognitionの
スマホでも使える顔認識アプリを作ろう!
アプリの環境構築
スマホでも使える顔画像認識アプリを作ります。
今回は、開発を簡単にするために、Node-REDボイラーテンプレート利用します。
まずは、ダッシュボード画面に移動します。
ダッシュボード画面に戻りました。
「あれれ?」いつのまにか、Visual Recognitionとは別のもの(Knowledge CatalogとWatson Studio)が増えていますね。
でも、これは気にしなくていいです。
(説明すると長くなるので今回は割愛します)
Visual Recognitionと同じようにソフトを購入します。
検索バーに「Node-RED」という文字を入力すると、ソフト一覧が変わると思います。
その中で、「Node-RED Starter」があると思うので、クリックしてください。
ロードが遅いとこんな画面が出ますが、操作せずにお待ち下さい。
アプリ名を入力してください。
ここでは「visual-recognition-test-00001」としていますが、ユニークな文字なら何でもいいです。アルファベットと'-'と数字の組み合わせであれば。
多くの方は「0001」を任意の数字にするといいかもしれません。
そうすると「作成ボタン」が押せるようになりますので、クリックしてください。
アプリケーションを動かす環境がセットアップするまで、しばらくお待ち下さい。
1分ぐらいですが、気分的にティータイム推奨。
アプリを実装する
さっそく、アプリを実装しますが、道に迷わないようにダッシュボードからの移動方法を説明します。
ダッシュボードには、先ほどつけた「visual-recognition-test-00001」という行が増えていると思います。
アプリを作るので、ここをクリックします。
そうすると、先程購入したVisual Recognitionが出てきます。
ここにマウスカーソルをあてると・・・
カーソルが当たると「Connect」というボタンが出るので、クリックしてください。
次の画面の「接続」ボタンを押します。
こうすることで、これから作るアプリの環境と、購入したVisual Recognitionが関連付けられます。
関連付けることで、アプリを作るとき、普段はプログラムしなくてはならないVisual Recognitionの細かい設定プログラムを一切考えなくても開発できるようになります。
関連付けを有効化するため、初期化処理を実行します。
色々記述がありますが、要は「再ステージ」は、「色々アップデートされたので、パソコンを再起動するイメージ」で考えておけばいいです。
「パソコンの再起動のイメージ」なので、少し時間がかかります。
クリックした後の画面を見ると、赤線の当たりが「再ステージング中」となっており、アイコンがぐーるぐーるしていると思います。
ぐーるぐーるが終わると、こんな感じになります。
ここで「経路」というボタンをクリックしてみてください。
開かれたメニューのリンクをクリックします。
そうすると、別ウィンドウが開かれるはずです。
別ウィンドウに出た画面を開くと、開発環境の初期設定画面が出ます。
(次からは出なくなるので、1回目だけの作業だと思って下さい)
次にusernameとpasswordを入れる画面が出ます。
このusernameとpasswordは次回も使うので、メモしておいてください!!!!
これらの値は何でもいいですが、IBM CloudのログインID/パスワードだと覚えやすそうですね(責任は持ちませんが)。
usernameとpasswordを入力したら、「NEXT」ボタンを押してください。
次に色々説明する画面がありますが、特に気にせず「NEXT」ボタンを押してください。
これで環境ができました。
おつかれさまでした。
アプリ開発画面のログインについて
先ほど流れで初期設定を終えたとき、あるいは、(補足)の画面で「経路」を選択したとき、このような画面になります。
これはアプリを開発する画面の初期画面になります。
さっそく、右側にある「Go to your Node-RED flow editor」をクリックしてみましょう。
*補足
次からは、先程あった「経路」ボタンの「URL」をクリックしても同じ画面になります。
さっきのURLの画面は以下のやつ。困ったら、前の工程から同じ画面を探してみてください。
ログイン画面が出ました。
先程、登録したusernameとpasswordを入力して、「ログイン」ボタンを押してみましょう。
アプリを開発する
ログインすると、こんな画面が出てきます。
これがアプリを開発する画面です。
そうするとメニューが出てくるので、下記のようにマウスカーソルを合わせて、「クリップボード」をクリックしてください。
こんな画面が出てきました。
赤線の枠線に以下の文字列をコピーしてください。
[{"id":"a9c22725.da4bc8","type":"tab","label":"画像認識サンプル","disabled":false,"info":""},{"id":"e3c35cdd.d33ce","type":"template","z":"a9c22725.da4bc8","name":"写真アップロード","field":"payload","fieldType":"msg","format":"html","syntax":"mustache","template":"<!DOCTYPE html>\n<html lang=\"ja\" class=\"no-js\">\n<head>\n <meta charset=\"UTF-8\" />\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no\" />\n <title>Watson Visual Recognition on Node-RED</title>\n <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css\">\n</head>\n<body>\n<div class=\"container-fluid\">\n <div class=\"col-sm-12\">\n <p>Watson Visual Recognition on Node-RED</p>\n </div>\n\n <div class=\"panel panel-success col-sm-12\">\n <div class=\"panel-heading\">\n Select an image file\n </div>\n\n <div class=\"panel-body\" style=\"height:300px;\">\n <div class=\"row\">\n <form id=\"src_image\" action=\"\" method=\"post\" enctype=\"multipart/form-data\">\n <input class=\"btn btn-info btn-ls\" type=\"file\" name=\"imagedata\" accept=\"image/*\" />\n </form>\n </div>\n\n <div class=\"row\">\n <div class=\"btn btn-danger btn-ls\" onclick=\"callVisualRecognition()\"/>\n Analyze\n </div>\n </div>\n\n <div class=\"row\">\n <div class=\"preview\">\n </div>\n </div>\n </div>\n\n <div class=\"panel-footer\" style=\"height:100px;\">\n <div id=\"result\"></div>\n </div>\n\n </div>\n</div>\n\n<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js\"></script>\n<script src=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js\"></script>\n\n<script type=\"text/javascript\">\n // Node-REDのWeb API連携\n var callVisualRecognition = function() {\n\n // フォームデータを取得\n var formdata = new FormData($('#src_image').get(0));\n\n console.log(formdata);\n\n // POSTでアップロード\n $.ajax({\n url : \"./face1-post\",\n type : \"POST\",\n data : formdata,\n cache : false,\n contentType : false,\n processData : false,\n dataType : \"html\"\n })\n .done(function(data, textStatus, jqXHR) {\n var result_element = document.getElementById('result');\n\n var objResult = JSON.parse(data);\n\n // 子ノードを全削除\n if (result_element.hasChildNodes()){\n for (var i=result_element.childNodes.length-1; i>=0; i--) {\n result_element.removeChild(result_element.childNodes[i]);\n }\n }\n\n // 年齢\n var age;\n age = document.createTextNode(\"age=\"+objResult.images[0].faces[0].age.min +\"~\"+objResult.images[0].faces[0].age.max+\"(\"+objResult.images[0].faces[0].age.score+\")\");\n var ageBox = document.createElement('p');\n ageBox.appendChild(age);\n result_element.appendChild(ageBox);\n\n // gender\n gender = document.createTextNode(\"gender=\"+objResult.images[0].faces[0].gender.gender+\"(\"+objResult.images[0].faces[0].gender.score+\")\");\n var genderBox = document.createElement('p');\n genderBox.appendChild(gender);\n result_element.appendChild(genderBox);\n\n console.log(objResult);\n })\n .fail(function(jqXHR, textStatus, errorThrown) {\n // 通信エラー\n // do nothing\n return;\n })\n .always(function(data) {\n // do nothing\n });\n }\n</script>\n\n<script>\n$(function(){\n //画像ファイルプレビュー表示のイベント追加 fileを選択時に発火するイベントを登録\n $('form').on('change', 'input[type=\"file\"]', function(e) {\n var file = e.target.files[0],\n reader = new FileReader(),\n $preview = $(\".preview\");\n t = this;\n\n // 画像ファイル以外の場合は何もしない\n if(file.type.indexOf(\"image\") < 0){\n return false;\n }\n\n // ファイル読み込みが完了した際のイベント登録\n reader.onload = (function(file) {\n return function(e) {\n //既存のプレビューを削除\n $preview.empty();\n // .prevewの領域の中にロードした画像を表示するimageタグを追加\n $preview.append($('<img>').attr({\n src: e.target.result,\n height: \"150px\",\n class: \"preview\",\n title: file.name\n }));\n };\n })(file);\n\n reader.readAsDataURL(file);\n });\n});\n\n</script>\n</body>\n</html>\n","x":330,"y":80,"wires":[["9cb0b56a.e22928"]]},{"id":"cacbb4de.1cf6b8","type":"http in","z":"a9c22725.da4bc8","name":"[GET] /face1","url":"/face1","method":"get","upload":false,"swaggerDoc":"","x":130,"y":80,"wires":[["e3c35cdd.d33ce"]]},{"id":"9cb0b56a.e22928","type":"http response","z":"a9c22725.da4bc8","name":"http response","x":539.5,"y":80,"wires":[]},{"id":"3bf9c4b0.873fac","type":"function","z":"a9c22725.da4bc8","name":"jpeg抽出","func":"var buf = msg.req.body;\nvar SOI = new Buffer(\"FFD8\",\"hex\");\nvar EOI = new Buffer(\"FFD9\",\"hex\");\nvar iSOI = 0;\nvar file = \"\";\n\nfor (var i=0 ; i<=buf.length ; i++) {\n if(SOI.equals(buf.slice(i,i+2))) {\n iSOI = i;\n }\n if(EOI.equals(buf.slice(i,i+2))) {\n file = buf.slice(iSOI,i+2);\n break;\n }\n }\n\nmsg.file = file;\nreturn msg;","outputs":1,"noerr":0,"x":300,"y":140,"wires":[["7f7844c9.9f5b0c"]]},{"id":"d88ef886.f00af8","type":"http in","z":"a9c22725.da4bc8","name":"[POST] /face1-post","url":"/face1-post","method":"post","upload":false,"swaggerDoc":"","x":125,"y":128,"wires":[["3bf9c4b0.873fac"]]},{"id":"7f7844c9.9f5b0c","type":"function","z":"a9c22725.da4bc8","name":"parse","func":"msg.payload = msg.file;\nreturn msg;","outputs":1,"noerr":0,"x":290,"y":200,"wires":[["a04c732d.6fe69"]]},{"id":"39150e99.319ec2","type":"json","z":"a9c22725.da4bc8","name":"","property":"payload","action":"str","pretty":true,"x":490,"y":260,"wires":[["e6746519.664be8","7d7e65a4.d5d25c"]]},{"id":"39a7ec11.2b0d24","type":"debug","z":"a9c22725.da4bc8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"result","x":570,"y":160,"wires":[]},{"id":"e6746519.664be8","type":"http response","z":"a9c22725.da4bc8","name":"http response","x":620,"y":280,"wires":[]},{"id":"7d7e65a4.d5d25c","type":"debug","z":"a9c22725.da4bc8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":610,"y":220,"wires":[]},{"id":"480df1d.1309f1","type":"function","z":"a9c22725.da4bc8","name":"parse","func":"msg.payload = msg.result;\nreturn msg;","outputs":1,"noerr":0,"x":450,"y":320,"wires":[["39150e99.319ec2"]]},{"id":"49251648.c24de8","type":"template","z":"a9c22725.da4bc8","name":"写真アップロード","field":"payload","fieldType":"msg","format":"html","syntax":"mustache","template":"<!DOCTYPE html>\n<html lang=\"ja\" class=\"no-js\">\n<head>\n <meta charset=\"UTF-8\" />\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no\" />\n <title>Watson Visual Recognition on Node-RED</title>\n <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css\">\n</head>\n<body>\n<div class=\"container-fluid\">\n <div class=\"col-sm-12\">\n <p>Watson Visual Recognition on Node-RED</p>\n </div>\n\n <div class=\"panel panel-success col-sm-12\">\n <div class=\"panel-heading\">\n Select an image file\n </div>\n\n <div class=\"panel-body\" style=\"height:300px;\">\n <div class=\"row\">\n <form id=\"src_image\" action=\"\" method=\"post\" enctype=\"multipart/form-data\">\n <input class=\"btn btn-info btn-ls\" type=\"file\" name=\"imagedata\" accept=\"image/*\" />\n </form>\n </div>\n\n <div class=\"row\">\n <div class=\"btn btn-danger btn-ls\" onclick=\"callVisualRecognition()\"/>\n Analyze\n </div>\n </div>\n\n <div class=\"row\">\n <div class=\"preview\">\n </div>\n </div>\n </div>\n\n <div class=\"panel-footer\" style=\"height:100px;\">\n <div id=\"result\"></div>\n </div>\n\n </div>\n</div>\n\n<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js\"></script>\n<script src=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js\"></script>\n\n<script type=\"text/javascript\">\n // Node-REDのWeb API連携\n var callVisualRecognition = function() {\n\n // フォームデータを取得\n var formdata = new FormData($('#src_image').get(0));\n\n console.log(formdata);\n\n // POSTでアップロード\n $.ajax({\n url : \"./cust1-post\",\n type : \"POST\",\n data : formdata,\n cache : false,\n contentType : false,\n processData : false,\n dataType : \"html\"\n })\n .done(function(data, textStatus, jqXHR) {\n var result_element = document.getElementById('result');\n\n var objResult = JSON.parse(data);\n console.log(objResult);\n\n // 子ノードを全削除\n if (result_element.hasChildNodes()){\n for (var i=result_element.childNodes.length-1; i>=0; i--) {\n result_element.removeChild(result_element.childNodes[i]);\n }\n }\n\n // classifierId+name\n var classifier;\n classifier = document.createTextNode(\"classifierId=\"+objResult.images[0].classifiers[0].classifier_id+\", classifierName=\"+objResult.images[0].classifiers[0].name);\n var classifierBox = document.createElement('p');\n classifierBox.appendChild(classifier);\n result_element.appendChild(classifierBox);\n\n // classes\n var classes;\n classes = document.createTextNode(\"className=\"+objResult.images[0].classifiers[0].classes[0].class +\", score=\"+objResult.images[0].classifiers[0].classes[0].score );\n var classesBox = document.createElement('p');\n classesBox.appendChild(classes);\n result_element.appendChild(classesBox);\n })\n .fail(function(jqXHR, textStatus, errorThrown) {\n // エラー\n var error;\n error = document.createTextNode(\"error=\"+data);\n var errorBox = document.createElement('p');\n errorBox.appendChild(error);\n result_element.appendChild(errorBox);\n return;\n })\n .always(function(data) {\n // do nothing\n });\n }\n</script>\n\n<script>\n$(function(){\n //画像ファイルプレビュー表示のイベント追加 fileを選択時に発火するイベントを登録\n $('form').on('change', 'input[type=\"file\"]', function(e) {\n var file = e.target.files[0],\n reader = new FileReader(),\n $preview = $(\".preview\");\n t = this;\n\n // 画像ファイル以外の場合は何もしない\n if(file.type.indexOf(\"image\") < 0){\n return false;\n }\n\n // ファイル読み込みが完了した際のイベント登録\n reader.onload = (function(file) {\n return function(e) {\n //既存のプレビューを削除\n $preview.empty();\n // .prevewの領域の中にロードした画像を表示するimageタグを追加\n $preview.append($('<img>').attr({\n src: e.target.result,\n height: \"150px\",\n class: \"preview\",\n title: file.name\n }));\n };\n })(file);\n\n reader.readAsDataURL(file);\n });\n});\n\n</script>\n</body>\n</html>\n","x":330,"y":420,"wires":[["42ac763b.d26cc8"]]},{"id":"6c8788b1.6a9388","type":"http in","z":"a9c22725.da4bc8","name":"[GET] /cust1","url":"/cust1","method":"get","upload":false,"swaggerDoc":"","x":130,"y":420,"wires":[["49251648.c24de8"]]},{"id":"42ac763b.d26cc8","type":"http response","z":"a9c22725.da4bc8","name":"http response","x":539.5,"y":420,"wires":[]},{"id":"eb0058cc.eccc88","type":"function","z":"a9c22725.da4bc8","name":"jpeg抽出","func":"var buf = msg.req.body;\nvar SOI = new Buffer(\"FFD8\",\"hex\");\nvar EOI = new Buffer(\"FFD9\",\"hex\");\nvar iSOI = 0;\nvar file = \"\";\n\nfor (var i=0 ; i<=buf.length ; i++) {\n if(SOI.equals(buf.slice(i,i+2))) {\n iSOI = i;\n }\n if(EOI.equals(buf.slice(i,i+2))) {\n file = buf.slice(iSOI,i+2);\n break;\n }\n }\n\nmsg.file = file;\nreturn msg;","outputs":1,"noerr":0,"x":300,"y":480,"wires":[["ec132d76.00162"]]},{"id":"2cb99d1b.d0c382","type":"http in","z":"a9c22725.da4bc8","name":"[POST] /cust1-post","url":"/cust1-post","method":"post","upload":false,"swaggerDoc":"","x":125,"y":468,"wires":[["eb0058cc.eccc88"]]},{"id":"ec132d76.00162","type":"function","z":"a9c22725.da4bc8","name":"parse","func":"msg.payload = msg.file;\nreturn msg;","outputs":1,"noerr":0,"x":250,"y":540,"wires":[["d77b5a8d.d821a8"]]},{"id":"8b72a21d.04572","type":"json","z":"a9c22725.da4bc8","name":"","property":"payload","action":"str","pretty":true,"x":490,"y":600,"wires":[["cb27a8df.97c158","4f41385b.c698c8"]]},{"id":"44ab232b.6cc57c","type":"debug","z":"a9c22725.da4bc8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"result","x":570,"y":500,"wires":[]},{"id":"cb27a8df.97c158","type":"http response","z":"a9c22725.da4bc8","name":"http response","x":620,"y":620,"wires":[]},{"id":"4f41385b.c698c8","type":"debug","z":"a9c22725.da4bc8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","x":610,"y":560,"wires":[]},{"id":"643f16c0.7ae348","type":"function","z":"a9c22725.da4bc8","name":"parse","func":"msg.payload = msg.result;\nreturn msg;","outputs":1,"noerr":0,"x":450,"y":660,"wires":[["8b72a21d.04572"]]},{"id":"d77b5a8d.d821a8","type":"function","z":"a9c22725.da4bc8","name":"Visual Recognitionカスタム認識の設定","func":"msg.params = {};\nmsg.params.classifier_ids = \"DefaultCustomModel_1898051895\";\nmsg.params.threshold = \"0.2\";\nreturn msg;","outputs":1,"noerr":0,"x":230,"y":600,"wires":[["b4bbc2d6.cc09"]]},{"id":"b4bbc2d6.cc09","type":"visual-recognition-v3","z":"a9c22725.da4bc8","name":"Detect Custom","apikey":"","image-feature":"classifyImage","lang":"ja","x":280,"y":660,"wires":[["643f16c0.7ae348","44ab232b.6cc57c"]]},{"id":"a04c732d.6fe69","type":"visual-recognition-v3","z":"a9c22725.da4bc8","name":"","apikey":"","vr-service-endpoint":"https://gateway.watsonplatform.net/visual-recognition/api","image-feature":"detectFaces","lang":"","x":190,"y":280,"wires":[["480df1d.1309f1","39a7ec11.2b0d24"]]},{"id":"9327753a.fb1ab","type":"http in","z":"a9c22725.da4bc8","name":"","url":"/test","method":"get","upload":false,"swaggerDoc":"","x":140,"y":20,"wires":[["fd43d664.f36e48"]]},{"id":"fd43d664.f36e48","type":"template","z":"a9c22725.da4bc8","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"ホームページ出来た!","output":"str","x":300,"y":20,"wires":[["c6e31e84.746b28"]]},{"id":"c6e31e84.746b28","type":"http response","z":"a9c22725.da4bc8","name":"","statusCode":"","headers":{},"x":480,"y":20,"wires":[]}]
タブが増えました。
さっそく、追加された「画像認識サンプル」タブを押してみましょう。
なんか、フロー図みたいなのができていますね。
赤枠線で囲っている範囲が、今回利用するアプリのプログラムです。
時代はもう、文字列を並べて作るだけがプログラムではないのです。
このプログラム環境を「Node-RED」というツールです。
(余談)Node−REDはIBMさんだけのものではなく、みんなのもの(オープンソース)です。なので、中身は個人でも見たり、修正したりできます。
興味が出た方は「Node-RED User Group Japan」へ!
https://nodered.jp/
では、ベースができたところで、アプリを開発します。
「Visual Recognition」という部品をダブルクリックしてください。
すると右側になにか出てきましたね。
「Service Endpoint」というものをクリックしてください。
先程、空白になっていた「Service Endpoint」に文字が入っていることを確認してください。
(Service Endpontは、最近、設定不要になったみたいです。設定が出てこなければ何もしなくて良いです)
さて、プログラムが出来たところで、プログラムをシステムに反映させましょう。
反映のことを「デプロイ(配置)」といいます。
これで開発は完了です。
おつかれさまでした。
アプリを動かす
さっそくアプリを動かしてみましょう。
Webアプリなので、アドレス(URL)を指定すると、アプリを動かすことが出来ます。
URLですが、参考になるのは先程の開発環境です。
この赤線を引いたアドレス(URL)の部分を修正します。
アドレス(赤線)をコピーして、新規タブを作成するボタン(赤線で囲ったボタン)を押します。
新しいタブに「(元々のアドレス)」を貼り付けます。
アドレスは、
https://visual-recognition-test-00001.mybluemix.net/red/#flow/ほにゃほにゃ
です。
次に、
より右の文字を削除して、「test」と追記します。
こんな感じです。
こんな感じになります。
入力が終わったら、キーボードの「エンター」キーを押して、画面を表示してみてください。
ホームページができました!
次に
https://visual-recognition-test-00001.mybluemix.net/
より右の文字を削除して、「face1」と追記します。
こんな感じになります。
入力が終わったら、キーボードの「エンター」キーを押して、画面を表示してみてください。
アプリ画面が出ました!
ここで、ファイルを選択するボタンを押してみましょう。
ファイル選択画面。Windowsなら違うはずです。
この選択で、JPGのファイルを選択してください。
他の画像ではアプリは動きませんので注意してください!
ロード出来ていることを確認して、「Analyze」ボタンを押します。
処理がうまくいくと、画面のグレー部分に、画像認識の結果が出ると思います。
(応用編)Custom画像認識を作る
メニューのServiceを選び、Watson Serciceを選びます。
出てきたVisual RecognitionサービスのLaunch ボタンを押してください。
プロジェクト作成がでてくるので、必要事項を入れてCreateします。
カスタムデータモデルを作るのですが、右側のZipファイルをアップロードする必要があります。
テスト用ならGoogle先輩にライセンスフリーの画像を探してもらいましょう!
Zipがアップできると、add-modelというのが出るので、それを追加します。
登録できた画像を学習させるため、Trainボタンを押します。
画面は誤ってボタンをおした後の画面です。
アプリを試す。
顔画像の認識に使った、Node-REDのフローに、今回用のフローがあります。
このなかで、「Visual Recognitionカスタム認識の設定」をダブルクリックします。
カスタムで作成したクラスIDに修正し、「完了」ボタンを押します。
処理が終わったら、完了です。
稼働確認する
顔画像認識アプリと同じですが、アドレス(URL)が違います。
URLの最後を[/cust1]に変更してアクセスしてみてください。
アプリは顔画像認識アプリと同じなので、操作説明は割愛します。
(おまけ)画像へのURL指定で、画像認識を行う。
あまり使いませんが、画像へのURLを指定して、画像認識させるサンプルプログラムも掲載しておきます。
[{"id":"3e4c0e0e.1d0542","type":"tab","label":"画像認識サンプル(URL)","disabled":false,"info":""},{"id":"28864629.0d428a","type":"http in","z":"3e4c0e0e.1d0542","name":"","url":"/face_url","method":"get","upload":false,"swaggerDoc":"","x":90,"y":60,"wires":[["3db8b82a.44e688"]]},{"id":"3db8b82a.44e688","type":"change","z":"3e4c0e0e.1d0542","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.url","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":260,"y":60,"wires":[["5bc91c85.e031e4"]]},{"id":"5bc91c85.e031e4","type":"visual-recognition-v3","z":"3e4c0e0e.1d0542","name":"","apikey":"","vr-service-endpoint":"https://gateway-a.watsonplatform.net/visual-recognition/api","image-feature":"detectFaces","lang":"en","x":390,"y":140,"wires":[["db4b187f.b63378","6264edb9.2baef4"]]},{"id":"db4b187f.b63378","type":"http response","z":"3e4c0e0e.1d0542","name":"","statusCode":"","headers":{},"x":550,"y":60,"wires":[]},{"id":"6264edb9.2baef4","type":"debug","z":"3e4c0e0e.1d0542","name":"","active":true,"tosidebar":true,"console":true,"tostatus":false,"complete":"result","x":630,"y":160,"wires":[]},{"id":"93c6d1e9.77ed6","type":"http in","z":"3e4c0e0e.1d0542","name":"","url":"/general_url","method":"get","upload":false,"swaggerDoc":"","x":100,"y":220,"wires":[["fba9c35.38ff34"]]},{"id":"fba9c35.38ff34","type":"change","z":"3e4c0e0e.1d0542","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"payload.url","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":320,"y":200,"wires":[["8ee3aa49.914d48"]]},{"id":"dfbfab37.ea34a8","type":"visual-recognition-v3","z":"3e4c0e0e.1d0542","name":"","apikey":"","vr-service-endpoint":"https://gateway-a.watsonplatform.net/visual-recognition/api","image-feature":"classifyImage","lang":"en","x":310,"y":360,"wires":[["ab5d1a51.d6a5f8","5aac1ae8.536514"]]},{"id":"ab5d1a51.d6a5f8","type":"http response","z":"3e4c0e0e.1d0542","name":"","statusCode":"","headers":{},"x":550,"y":260,"wires":[]},{"id":"5aac1ae8.536514","type":"debug","z":"3e4c0e0e.1d0542","name":"","active":true,"tosidebar":true,"console":true,"tostatus":false,"complete":"result","x":550,"y":360,"wires":[]},{"id":"8ee3aa49.914d48","type":"function","z":"3e4c0e0e.1d0542","name":"Visual Recognitionカスタム認識の設定","func":"msg.params = {};\nmsg.params.classifier_ids = \"default\";\nmsg.params.threshold = \"0.2\";\nreturn msg;","outputs":1,"noerr":0,"x":210,"y":280,"wires":[["dfbfab37.ea34a8"]]}]
それでは!