食べ物の画像にモザイクをかける API と Chrome 拡張を作ってみた [Project Oxford Vision API]

DevelopmentAzure, Project Oxford

飯テロ対策として、食べ物の画像にモザイクをかける API と Chrome 拡張を作ってみました。

Microsoft Project Oxford の Vision API を利用したもので、API 制限等からきちんと公開はしていませんが、API を試したり、コードを見たりはできます。先日話題になった How-Old.net は、Project Oxford の提供する API のうち Face API を利用しています。

Chrome 拡張

Vision API

食べ物の画像にモザイクをかける 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 を追加します。

Vision API

Key の取得

https://dev.projectoxford.ai/Developer にアクセスして、Key を取得します。

Vision API

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

view raw
visionapi.vb
hosted with ❤ by GitHub

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

view raw
ApiController.vb
hosted with ❤ by GitHub

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);
});
});

view raw
custom.js
hosted with ❤ by GitHub

{
"manifest_version": 2,
"name": "食べ物の画像にモザイクをかける拡張",
"version": "1.0",
"content_scripts": [{
"matches": [ "<all_urls>" ],
"js": [ "jquery.min.js", "custom.js" ],
"run_at": "document_start"
}]
}

view raw
manifest.json
hosted with ❤ by GitHub

Chrome のアドレス欄に「chrome://extensions/」を入力。「デベロッパーモード」にチェックを入れて「パッケージ化されていない拡張機能を読み込む」ボタンから、作成したフォルダーを指定すれば、拡張を追加できます。

Chrome Extension

以上で完成です。ただし、モザイク画像がロードされるまで、元の画像が見えるという欠点と、API 制限にすぐひっかかります。お遊びということで。あと、Data URI(data:image で始まる URL)にも対応できていません。

わざわざ Web サービスを作りましたが、Vison API は、JavaScript からも利用できるので、Chrome 拡張のみで完結も可能です。

関連サイト