食べ物の画像にモザイクをかける API と Chrome 拡張を作ってみた [Project Oxford Vision API]
飯テロ対策として、食べ物の画像にモザイクをかける API と Chrome 拡張を作ってみました。
Microsoft Project Oxford の Vision API を利用したもので、API 制限等からきちんと公開はしていませんが、API を試したり、コードを見たりはできます。先日話題になった How-Old.net は、Project Oxford の提供する API のうち Face API を利用しています。
Chrome 拡張
食べ物の画像にモザイクをかける Web サービス
画像 URL を指定すると、食べ物の画像の場合、モザイク処理された画像が返ってきます。
http://foodtero.azurewebsites.net/api/?url=http://upload.wikimedia.org/wikipedia/ja/thumb/f/fc/Soy_ramen.jpg/260px-Soy_ramen.jpg
利用している Visio API は、1分に20回、月に5,000回までの制限があるので、エラーになった場合は、そのままの画像を返します。皆さん自身で API Key を取得して実装してみてください。
Vision API
Vison APIs は、以下の機能があります。
- 画像認識
- サムネイルの生成
- OCR
今回は、画像認識を利用して、画像のカテゴリーが「食べ物」場合、モザイクをかけて返すという Web サービスにしてみました。Vison API では、86のカテゴリーに分類できます。
公式のデモはこちら。
アダルトコンテンツ、Racy コンテンツ(水着とか)の判別、背景・前景のカラーやアクセントカラー抽出などもできます。
Vision API を使ってみる
現在 Beta 版で無料で利用できます(呼び出し制限を緩和しようとも、無料版しかないのでできません)。また、Azure Market での購入が必要で、Azure アカウントが必要です。API は、RESTful API で、プラットフォームを選びません。
リクエスト URL: https://api.projectoxford.ai/vision/v1/analyses[?visualFeatures]
詳細は、Microsoft Project Oxford API Reference 参照。
Azure Marketplace でサービスの選択
Azure ポータルから、Marketplace の Vision API を追加します。
Key の取得
https://dev.projectoxford.ai/Developer にアクセスして、Key を取得します。
SDK のダウンロード、コードサンプル
.NET/Android の SDK が用意されています。その他の言語も ドキュメント のサンプルコードなどを見れば簡単に使えます。
Visual Basic で、SDK のライブラリを利用すれば、画像認識は次のように書けます。
Dim client = New VisionServiceClient("**key**") | |
Dim result = Await client.AnalyzeImageAsync("画像 URL") ' 画像の Stream も指定可能 | |
If result.Categories IsNot Nothing AndAlso result.Categories.Any AndAlso | |
result.Categories.First.Name.StartsWith("food_") Then | |
' (画像のカテゴリーが食べ物の場合) | |
End If |
Web サービスを作る
ASP.NET で Web サービスを作ります。
コントローラーのコードです。ルーティングを変更する以外は、他に書くコードはありません。
Imports System.Drawing | |
Imports System.Net | |
Imports Microsoft.ProjectOxford.Vision | |
Public Class ApiController | |
Inherits System.Web.Mvc.Controller | |
Async Function Index(url As String) As Threading.Tasks.Task(Of ActionResult) | |
If url Is Nothing Then | |
Return New HttpStatusCodeResult(HttpStatusCode.BadRequest) | |
End If | |
Dim result As Contract.AnalysisResult | |
Try | |
' API 呼び出し | |
Dim client = New VisionServiceClient("0b1ff4ab7a634bb0a6f7d532659f5d77") | |
If Uri.IsWellFormedUriString(url, UriKind.Absolute) Then | |
result = Await client.AnalyzeImageAsync(url) | |
Else | |
Return New HttpStatusCodeResult(HttpStatusCode.BadRequest) | |
End If | |
Catch cEx As ClientException | |
Return FileStream(url) | |
Catch ex As Exception | |
Return FileStream(url) | |
End Try | |
If result.Categories IsNot Nothing AndAlso result.Categories.Any AndAlso | |
result.Categories.First.Name.StartsWith("food_") Then ' 画像のカテゴリーが食べ物 | |
' モザイク画像作成 | |
Dim webClient = New WebClient | |
Dim inBmp = New Bitmap(webClient.OpenRead(url)) | |
Dim tmpBmp = New Bitmap(inBmp.Width \ 10, inBmp.Height \ 10) | |
Dim outBmp = New Bitmap(inBmp.Width, inBmp.Height) | |
Using g = Graphics.FromImage(tmpBmp) | |
g.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor | |
g.DrawImage(inBmp, 0, 0, tmpBmp.Width, tmpBmp.Height) | |
End Using | |
Using g = Graphics.FromImage(outBmp) | |
g.InterpolationMode = Drawing2D.InterpolationMode.NearestNeighbor | |
g.DrawImage(tmpBmp, 0, 0, outBmp.Width, outBmp.Height) | |
End Using | |
Response.ContentType = "image/png" | |
outBmp.Save(Response.OutputStream, Imaging.ImageFormat.Png) | |
Return New EmptyResult | |
Else | |
Return FileStream(url) | |
End If | |
End Function | |
Private Function FileStream(url As String) As ActionResult | |
Try | |
Dim req = HttpWebRequest.CreateHttp(url) | |
Dim res = DirectCast(req.GetResponse, HttpWebResponse) | |
Response.ContentType = res.ContentType | |
res.GetResponseStream.CopyTo(Response.OutputStream) | |
Catch ex As WebException | |
If ex.Status = System.Net.WebExceptionStatus.ProtocolError Then | |
Dim r = DirectCast(ex.Response, System.Net.HttpWebResponse) | |
Response.StatusCode = r.StatusCode | |
End If | |
End Try | |
Return New EmptyResult | |
End Function | |
End Class |
Chrome の拡張を作る
試しに Chrome 拡張を作ってみます。img の URL を、作った API の URL に差し替えます。
フォルダーに、custom.js、manifest.json、jquery.min.js を作ります。
$(function() { | |
$('img').each(function(){ | |
this.src = "http://foodtero.azurewebsites.net/api/?url=" + encodeURIComponent(this.src); | |
}); | |
}); |
{ | |
"manifest_version": 2, | |
"name": "食べ物の画像にモザイクをかける拡張", | |
"version": "1.0", | |
"content_scripts": [{ | |
"matches": [ "<all_urls>" ], | |
"js": [ "jquery.min.js", "custom.js" ], | |
"run_at": "document_start" | |
}] | |
} |
Chrome のアドレス欄に「chrome://extensions/」を入力。「デベロッパーモード」にチェックを入れて「パッケージ化されていない拡張機能を読み込む」ボタンから、作成したフォルダーを指定すれば、拡張を追加できます。
以上で完成です。ただし、モザイク画像がロードされるまで、元の画像が見えるという欠点と、API 制限にすぐひっかかります。お遊びということで。あと、Data URI(data:image で始まる URL)にも対応できていません。
わざわざ Web サービスを作りましたが、Vison API は、JavaScript からも利用できるので、Chrome 拡張のみで完結も可能です。