這兩天掉下來的題目,雖然不是掉在我身上,但貌似不錯玩就摸了一下。而原本要 servey 的對像是 IBM 的 visual-recognition,實際弄了之後發現現階段 ibm 的 api 能做的貌似不多,就順便看看先前玩過的 google cloude vision ,果然有刺激有進步,比三月的時候又強化了不少,用這個機會把心得一併寫一寫。
IBM Visual Recognition
申請
相較 google 的申請流程, IBM 的簡單很多
- 到 http://console.ng.bluemix.net/ 建立帳號,登入後,它會請你選擇 region 及建立你的 Organization / Space 這樣就有一個 30 天免費的測試帳號了。30 天後會發生什麼事 ? 我也不知道 XD
- 在 console 點選上面的 Dashboard , 選擇 「Use Service or API」,再選擇「Visual Recognition」,在說明頁什麼都不用更動,直接按 Create 紐就好。
- 完成後會進入該 Visual Recogntion 的設定/說明主頁,左邊選單有個 Service Credentials 點了之後會顯示類似下面這樣的資訊,把其中的 api_key 抄下來就可以開始 coding 了1234567{"credentials": {"url": "https://gateway-a.watsonplatform.net/visual-recognition/api","note": "It may take up to 5 minutes for this key to become active. This is your previously active free apikey. If you want a different one, please wait 24 hours after unbinding the key and try again.","api_key": "你以為我會讓你看到我的 api key 嗎?"}}
測試
IBM visualt recognition API 的說明在這邊,能玩的說真的不太多,以下簡單請近期最出名的兩位名人協助做 classify / detect face 的測試
- 在專案目錄下執行
npm init
建立 package.json - 執行
npm install watson-developer-cloud --save
安裝必要的模組 - 編輯以下測試程式
ibm_visual_recognition.js 1234567891011121314151617181920212223var watson = require("watson-developer-cloud");var fs = require("fs");var visual_recognition = watson.visual_recognition({api_key: "你以為我會忘了這裡嗎 ?",version_date: "2016-05-20",version: "v3"});var params = {images_file : fs.createReadStream("./imgs/1.jpg")};visual_recognition.classify(params, function(err, res) {if (err)console.log( err );elseconsole.log( JSON.stringify(res, null, 2));});visual_recognition.detectFaces( params, function (err, res) {if (err)console.log( err ) ;elseconsole.log( JSON.stringify(res, null, 2));}); - 執行
npm imb_visual_recogntion
, 結果如下123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354{"custom_classes": 0,"images": [{"classifiers": [{"classes": [{"class": "person","score": 0.999888,"type_hierarchy": "/people"}],"classifier_id": "default","name": "default"}],"image": "1.jpg"}],"images_processed": 1}{"images": [{"faces": [{"age": {"max": 64,"min": 55,"score": 0.564336},"face_location": {"height": 316,"left": 435,"top": 369,"width": 303},"gender": {"gender": "MALE","score": 0.99593},"identity": {"name": "Donald Trump","score": 0.817574,"type_hierarchy": "/people/celebrities/donald trump"}}],"image": "1.jpg"}],"images_processed": 1}
說真的,結果有點讓人失望,像是人臉辨識的部份只認得川普 ? 不怕希婆拉蕊吉你歧視嗎 ?XD 這部份,google 真的要強一點。
想直接看測試結果的,可以到官網,把圖片丟到 try it out 的框框裡玩玩。
IBM 的visual recogntion 另外可以玩的的還有自己訓練分類資料,但我要打電動手頭的測試資料不足,就先不測了,來玩玩 google cloud vision api。
p.s 官方有份 node application (on bluemix) 的原始碼在 Github,如果有使用 bluemix 經驗的,是份不錯的範本,但若是先前沒使用過就直接跳進來看或是執行,可能會對裡頭的 cf (cloud foundry)等名詞、bluemix的執行階層等感到霧殺殺,也會對 api_key 的生成/管理有點疑惑 XD (對,就是我),建議像上面一樣由簡單的 bluemix api 呼叫開始,有點概念後,再建 web/mobile application。
Google Cloud Vision API
申請
講到 google cloud api 的申請天就要黑一邊,很多測試階段必要的動作都得做完(eg, 帳單設定),UX的設計也常讓人找不到東西在那邊 = = 以下簡單摘要申請的流程
- 申請 google 帳號。
- 到 Google Console API 申請一個(測試)專案,在專案名稱下方會有個「專案 ID」,先記下來,之後寫 code 的時候會用到,建立完成後頁面會自動跳到該專案的資料庫設定,這個時候可以選擇要啟用的 google api , 我們要測試的 vision api 在第一類的 Google Cloud API 裡的最後一個,要點開更多才看得到,也可以直接在「搜群所有 API 」中直接輸入 vision。
- 點選 Google Cloud Vision API 後,在該 API 說明的上方有個「啟用」,點它。
- 畫面上會提示需要建立憑証才能使用這個 API,請乖乖的點選「前往憑証」。
- 憑証類型請選擇 Google Cloud Vision API,然後點選「我需要哪些憑証?」(乾,我怎麼會知道 = = ),然後他會跟你說你的API 金鑰,然後點完成。
- 這時候會回到專案的憑證管理主頁,畫面上多了一個「建立憑證」按紐,依在 IT 打滾了十幾年的經驗,接下來應該要按它吧 ??? 按按看 (這段的說明在另一個遙遠的說明頁… https://googlecloudplatform.github.io/google-cloud-node/#/docs/vision/0.3.0/guides/authentication = = ),下拉選單中選「服務帳戶金鑰(Service Account)」。
- 建立服務帳戶金鑰頁面中,服務帳戶類型請選擇「App Engine Default Service Account」,金鑰類型似乎隨便,我是選JSON,最後點選建立,它會讓你下載一個金鑰檔,請好好保管,之後程式執行時也會用到。
如果沒有意外的話,到這邊你的程式應該都寫完了 vision api 的使用設定算告一個段落,有夠煩,G 社你跟IBM學學嘛 !!
p.s 在啟用 API 前, G 社會先檢查你是不是有錢人有合法付費設定,沒有的話會直接跳到帳單設定部份,乖乖繳保護費設定就是了。
測試
Google vsion api 的(Node 版本)說明頁在這邊 ,以下是簡單的執行範例 測試資料的部份依然請出近期世上最紅的兩位名人協助。
- 在專案目錄下執行
npm init
建立 package.json - 執行
npm install --save google-cloud
安裝google cloud 的 node js module (原則上不用全裝,但我執行的時候碰到找不到的錯誤,全裝就解決了) - Happy coding,以下是官方的範例,可以直接在Github
抄襲下載,但是用了在 Mac 上很難裝的 Canvas 模組,後果自負 XD XDgoogle_visual_recognition.js 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384var gcloud = require('google-cloud')({projectId: "<your_project_id>",keyFilename: "<your_credentials_key_file>"});var vision = gcloud.vision();var fs = require('fs');/*** Uses the Vision API to detect faces in the given file.*/function detectFaces(inputFile, callback) {// Make a call to the Vision API to detect the facesvision.detectFaces(inputFile, function (err, faces) {if (err) {return callback(err);}var numFaces = faces.length;console.log('Found ' + numFaces + (numFaces === 1 ? ' face' : ' faces'));callback(null, faces);});}/*** Draws a polygon around the faces, then saves to outputFile.*/function highlightFaces(inputFile, faces, outputFile, Canvas, callback) {fs.readFile(inputFile, function (err, image) {if (err) {return callback(err);}var Image = Canvas.Image;// Open the original image into a canvasvar img = new Image();img.src = image;var canvas = new Canvas(img.width, img.height);var context = canvas.getContext('2d');context.drawImage(img, 0, 0, img.width, img.height);// Now draw boxes around all the facescontext.strokeStyle = 'rgba(0,255,0,0.8)';context.lineWidth = '5';faces.forEach(function (face) {context.beginPath();face.bounds.face.forEach(function (bounds) {context.lineTo(bounds.x, bounds.y);});context.lineTo(face.bounds.face[0].x, face.bounds.face[0].y);context.stroke();});// Write the result to a fileconsole.log('Writing to file ' + outputFile);var writeStream = fs.createWriteStream(outputFile);var pngStream = canvas.pngStream();pngStream.on('data', function (chunk) {writeStream.write(chunk);});pngStream.on('error', console.log);pngStream.on('end', callback);});}// Run the examplefunction main(inputFile, outputFile, callback) {outputFile = outputFile || 'out.png';detectFaces(inputFile, function (err, faces) {if (err) {return callback(err);}console.log('Highlighting...');highlightFaces(inputFile, faces, outputFile, Canvas, function (err) {if (err) {return callback(err);}console.log('Finished!');callback(null, faces);});});}exports.main = main;if (module === require.main) {if (process.argv.length < 3) {console.log('Usage: node google_visual_recognition <inputFile> [outputFile]');process.exit(1);}var inputFile = process.argv[2];var outputFile = process.argv[3];exports.main(inputFile, outputFile, require('canvas'), console.log);} - 執行
node google_visual_recognition test_img.jpg
就可以得到結果如下 如果把 detectFaces 偵測出來的結果 faces[0] (這是川普的臉 XD) 印出來看,會長得像這樣
123456789101112131415161718192021222324{angles: { pan: -25.345671, roll: -15.692808, tilt: -0.48272857 },bounds:{ head: [ [Object], [Object], [Object], [Object] ],face: [ [Object], [Object], [Object], [Object] ] },features:{ confidence: 50.734334999999994,chin: { center: [Object], left: [Object], right: [Object] },ears: { left: [Object], right: [Object] },eyebrows: { left: [Object], right: [Object] },eyes: { left: [Object], right: [Object] },forehead: { x: 541.8797, y: 445.76398, z: -57.465015 },lips: { bottom: [Object], top: [Object] },mouth: { center: [Object], left: [Object], right: [Object] },nose: { bottom: [Object], tip: [Object], top: [Object] } },confidence: 97.719109,blurry: false,dark: false,happy: true,hat: false,mad: false,sad: false,surprised: false}其中有一段 features 屬性描述了這張臉的特徵,雖然只有位置(x,y,z)的資訊,但至少比 IBM 結果多一些可以玩的資訊,
完整的 vision API 一共有 faces, labels, landmarks, logos, properties, safeSearch, text 七大功能,各有獨立的 API 可以呼叫,要是想要
包套一次執行多項偵測,也有個 detect 的 API 可以用,以下是一個包套的範例12345678910111213141516171819202122232425262728293031323334353637383940414243444546var gcloud = require('google-cloud')({projectId: "<your_project_id>",keyFilename: "<your_credentials_key_file>"});var vision = gcloud.vision();var fs = require('fs');/*** Use the detect api of vision*/function detect(inputfile, callback ) {var types = ["faces","labels", "landmarks", "logos", "properties", "safeSearch", "text"];var opts = {types: types,maxResults: 20,verbose : true}vision.detect(inputfile, opts, function(err, detections, apiResponse) {if (err ) {return callback (err);}console.log("Something is over there !!");callback (null, detections);});}// Run the examplefunction main(inputFile, outputFile, callback) {outputFile = outputFile || 'out.png';detect( inputFile, function(err,detections) {if (err){return callback( err ) ;}console.log("Detections : " );console.log( detections );});}exports.main = main;if (module === require.main) {if (process.argv.length < 3) {console.log('Usage: node faceDetection <inputFile> [outputFile]');process.exit(1);}var inputFile = process.argv[2];var outputFile = process.argv[3];exports.main(inputFile, outputFile, console.log);}執行輸出結果如下
123456789101112131415161718192021222324252627282930313233343536373839404142434445{ faces:[ { angles: [Object],bounds: [Object],features: [Object],confidence: 97.719109,blurry: false,dark: false,happy: true,hat: false,mad: false,sad: false,surprised: false },{ angles: [Object],bounds: [Object],features: [Object],confidence: 97.595638,blurry: false,dark: false,happy: true,hat: false,mad: false,sad: false,surprised: false } ],labels:[ { desc: 'person', mid: '/m/01g317', score: 90.005928 },{ desc: 'speech', mid: '/m/09x0r', score: 77.268296 },{ desc: 'award', mid: '/m/02w3hl', score: 57.747811000000006 },{ desc: 'news conference', mid: '/m/01s8fx', score: 51.559496 } ],landmarks: [],logos: [],properties:{ colors:[ '8194da','95121a','610b14','151214','20316b','718ce0','a9b6f8','6d80c8','800b14','6782d4' ] },safeSearch: { adult: false, spoof: false, medical: false, violence: false },text: [ 'we trutkat\n', 'we', 'trutkat' ],errors: [] }faces 的部份就如同第一個範例的輸出結果, label 的結果有點像分類,或是概括的圖片描述,text 比先前三月測試的時候似乎進步不少,至少會出現完整的詞,而非英文字母讓你自己拼了, label 的部份這個例子看起來有點少,但若是丟另一張圖...WOW… Amazing ! 我說結果 !!
|
|
detect 方法中的 option 在文件中沒有明說,請自行翻原始碼中 158~172 行的部份。
如果不想寫程式也想測試這些東西,也可以,直接到官網首頁,有個 Try the API的輸入框,把圖丟進去就可以看到這些結果了……. … …
總結來說,google 除了一開始申請很麻煩外,在執行結果表現的比較好,後續比較有應用發揮的機會,IBM 的既然能識別出名人,那應該也有人臉特徵的功能,就看相關的 API 什麼時候更新或是提供了。
只是啊… 測試的時候有一些些免費的額度不會有感覺,但上線系統連續大量的圖片辨識,這個開銷…. 只能說,小時候不好好發展技術,這公司最後只能仰人鼻息也不是太意外的結果 (嘆