さくらVPSにOpenCVをインストールしてPythonから使う

OpenCV2.2をさくらVPS(CentOS 5.5)にインストールして、
PythonバインディングをWSGIアプリケーション(mod_wsgi)から使ってみます。

構築手順はOpenCV – 2.x – Tech Noteに書いておいたので参考までに。

OpenCV2.2からはNumPyを利用したPythonインタフェースを利用できるようになりました。
画像データを通常のNumPy配列(numpy.ndarray)として扱えるので大変便利です。

Pythonバインディング (NumPy利用)

[python]
$ 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)
## 画像データは普通の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]])
[/python]
すばらしいです。

WSGIアプリケーション(mod_wsgi)からの利用

せっかくサーバに入れたのでWebと仲良くさせてみます。
Flaskというフレームワークがモダンで便利らしいので試してみました。

## 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をぺたぺた貼ればいいだけなので省略)
[python]
#!/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/‘)
def canny(image=None):
src = cv.imread(‘/path/to/uploads/’ + image)
## apply Canny Edge Detector

return content

## Starキーポイント検出
@application.route(‘/starkeypoints/‘)
def star(image=None):
src = cv.imread(‘/path/to/uploads/’ + image)
## get Star Keypoints

return content

## SURF特徴抽出
@application.route(‘/surf/‘)
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()
[/python]
みたいな感じで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 開発ブログ

あわせて読む:

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です