OpenCV2.2をさくらVPS(CentOS 5.5)にインストールして、
PythonバインディングをWSGIアプリケーション(mod_wsgi)から使ってみます。
構築手順はOpenCV – 2.x – Tech Noteに書いておいたので参考までに。
OpenCV2.2からはNumPyを利用したPythonインタフェースを利用できるようになりました。
画像データを通常のNumPy配列(numpy.ndarray)として扱えるので大変便利です。
Pythonバインディング (NumPy利用)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
$ python Python 2.7.1 (r271:86832, Feb 18 2011, 03:06:36) [GCC 4.4.0 20090514 (Red Hat 4.4.0-6)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import cv, numpy as np >>> src = cv.imread("lena.jpg", 0) ## 画像の読み込み >>> src array([[162, 161, 161, ..., 171, 172, 142], [163, 163, 159, ..., 174, 174, 147], [164, 161, 158, ..., 162, 152, 114], ..., [ 51, 51, 53, ..., 84, 92, 93], [ 46, 48, 50, ..., 93, 102, 98], [ 43, 52, 51, ..., 101, 104, 107]], dtype=uint8) >>> type(src) <type 'numpy.ndarray'> ## 画像データは普通のNumPy配列として扱える >>> edge = cv.canny(src, 50, 100, apertureSize=3) ## Cannyエッジ検出 >>> edge array([[ 0, 0, 0, ..., 0, 0, 255], [ 0, 0, 0, ..., 0, 0, 255], [ 0, 0, 0, ..., 0, 255, 255], ..., [ 0, 0, 0, ..., 255, 0, 0], [ 0, 0, 0, ..., 0, 0, 0], [ 0, 0, 0, ..., 0, 0, 0]], dtype=uint8) >>> cv.imwrite("edge.jpg", edge) ## 画像の保存 True ## 以下、NumPyのAPIを利用 >>> src.ndim ## 次元数 2 >>> src.shape ## サイズ (256, 256) >>> np.mean(src) ## 平均 124.20285034179688 >>> np.std(src) ## 標準偏差 47.700710770786252 >>> src2 = cv.imread("lena.jpg", 0) >>> np.corrcoef([src, src2]) ## 相関係数 1 >>> np.fft.fft2(src) ## 二次元離散フーリエ変換(2D-FFT) array([[ 8.13975800e+06 +0.j , -1.17555692e+05+597148.17023819j, 3.87852226e+05-279750.64715102j, ..., -6.25724012e+04-157743.18227329j, 3.87852226e+05+279750.64715102j, -1.17555692e+05-597148.17023819j], [ -5.08489842e+03-306599.82137641j, -4.02887254e+05+393021.01034302j, -2.77225246e+05 +15427.3755807j , ..., 1.65351494e+05+200911.05534033j, -8.82517686e+04+112907.79830223j, 9.31931677e+03+235966.94268805j], [ -1.11658935e+05 -42622.57217756j, -6.81474629e+04 -34350.464984j , 1.69378207e+05-109574.82473126j, ..., 8.95342611e+04+230910.20836995j, -1.80697620e+05 -43628.96408889j, 2.05426782e+05 -14430.49928177j], ..., [ 1.28259331e+05 -55676.36282789j, 1.86000570e+05+174709.80855038j, -1.31625808e+05 -49361.38958211j, ..., 2.49346421e+05 +19823.18594082j, 2.83524889e+04-170858.79741727j, -1.06549248e+04+151597.41214675j], [ -1.11658935e+05 +42622.57217756j, 2.05426782e+05 +14430.49928177j, -1.80697620e+05 +43628.96408889j, ..., -1.34352423e+05-185163.25215583j, 1.69378207e+05+109574.82473126j, -6.81474629e+04 +34350.464984j ], [ -5.08489842e+03+306599.82137641j, 9.31931677e+03-235966.94268805j, -8.82517686e+04-112907.79830223j, ..., -1.18220973e+05+478576.12556064j, -2.77225246e+05 -15427.3755807j , -4.02887254e+05-393021.01034301j]]) |
すばらしいです。
WSGIアプリケーション(mod_wsgi)からの利用
せっかくサーバに入れたのでWebと仲良くさせてみます。
Flaskというフレームワークがモダンで便利らしいので試してみました。
1 2 |
## Flaskに引っ張られて Jinja2, Werkzeug も一緒にインストールされる $ sudo pip install Flask |
Apache + mod_wsgi環境の構築は、
mod_wsgiのインストール – CentOSで環境構築 を参考にさせていただきました。
構成は以下の通り。
- * Apache + mod_wsgi (Webサーバ/WSGI)
- * Flask (Webアプリケーションフレームワーク)
- * Jinja2 (テンプレートエンジン)
- * Werkzeug (WSGIユーティリティライブラリ)
- * OpenCV + NumPy (NumPyインタフェースはv2.2から)
フレームワーク自体ほとんど経験がないので心配でしたが、
公式サイトのチュートリアルを読んでいけばすぐに使えるようになりました。
それだけシンプルで使いやすいフレームワークだと思います。
まずは hello, world 的なものから試してみようと思い、
Cannyエッジ検出をするだけの簡単なデモを作りました。
(HTML5でテンプレートを書いてるのでブラウザが古い人は注意)
Test WSGI Application using OpenCV
実際、Cannyフィルタ程度ならJavaScript(Canvas)だけでも簡単にできるのですが、
今回はOpenCV+WSGIアプリのテストということで;;
WSGIアプリ(Flask)からOpenCVを使う流れとしては、
(画像処理のロジックはAPIをぺたぺた貼ればいいだけなので省略)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
#!/bin/env python from flask import Flask, abort, render_template, request, url_for from werkzeug import secure_filename import cv, numpy as np application = Flask(__name__) application.debug = True ## サービストップ @application.route('/') def index(): return render_template('index.html') ## Cannyエッジ検出 @application.route('/cannyedge/<image>') def canny(image=None): src = cv.imread('/path/to/uploads/' + image) ## apply Canny Edge Detector ... return content ## Starキーポイント検出 @application.route('/starkeypoints/<image>') def star(image=None): src = cv.imread('/path/to/uploads/' + image) ## get Star Keypoints ... return content ## SURF特徴抽出 @application.route('/surf/<image>') def surf(image=None): src = cv.imread('/path/to/uploads/' + image) ## extract SURF ... return content ## 画像ファイルのアップロード @application.route('/upload', methods=['POST']) def upload_file(): f = request.files['file'] f.save('/path/to/uploads/' + secure_filename(f.filename)) ... ## エラーハンドラ @application.errorhandler(404) def notfound(error): return 'not found', 404 if __name__ == '__main__': app.run() |
みたいな感じでURIを公開すればOKです。Flask素敵。
PythonのAPIは
OpenCV 2.2 Python リファレンス — opencv 2.2 documentation
に丁寧にまとめられています。
Pythonバインディングがあって嬉しいのは研究者よりもWeb屋なのでは?
また、クライアント側をFlashで作ってみても良いアプリケーションが作れそうです。
AS3オンリーであほみたいに画像処理しなくて済むのは個人的に嬉しいところ。
一応は簡単なサンプルをいくつか作っていたのですが、
最初はPyAMFを使ってデータのやりとりをしていました。
ただ、古い流儀のRPCなのでクライアント – サーバ間で合意事項が多くて美しくありません。
シンプルなURIのみを公開する方がキレイに作れると思います。(イマドキですし:p)
Flash + Flaskで何か作ったらまた公開します。
———-
* その他の参考サイト
PythonでWebアプリ開発入門のススメ Flask/MongoDB – mizchi log
mod_wsgi: WSGIDaemonProcess – Pyxis 開発ブログ