isk-daemonを使ってみる

オープンソースの類似画像検索エンジンisk-daemonを使ってみたので、その際の手順やはまりどころなどを書いておきます。
現時点では、isk-daemonはあまりメンテされていないようで、面倒な点が多々あり「使ってみよう」という方は覚悟しておいたほうがいいかもしれません。
クライアントについては、XML-RPC/JSON-RPC/SOAPが使えますが、今回はPythonXML-RPCを使いました。
使用したOSはUbuntu7.10です。Pythonのバージョンは2.5.1です。Windowsでも動かせるのですが、必要なモジュールやファイルパスの設定などで面倒な部分があるので今回は避けました。

  • 準備

動作に必要なパッケージをインストールしておきます。

python2.5
libmagick
libmagick++

Ubuntuの場合だとaptで、

python2.5
libmagick9
libmagick9-dev
libmagick++9c2a
libmagick++9-dev

あたりをインストールすればよいです。
isk-daemonの起動時にlibmagickのライブラリがロードできないエラーが出た場合は、soファイルの場所をチェックする。エイリアスを作ったりしてロードできるようにしてやればよい。

isk-daemonのサイトのDownloadからSourceForgeへ行ってダウンロードします。
http://server.imgseek.net/category/download/
今回使用したバージョンは0.6.2です。isk-daemonは0.6.2からオープンソースになったみたいです。
ダウンロードが終わったら、アーカイブを展開しておきます。

  • _imgdb.soの入手

isk-daemonの0.6.2のChangeLogに試用に関するコードを削除したとあるのですが、アーカイブに入っている"_imgdb.so"のバイナリは古いバージョンのものでした。最新のものを入手する必要があります。
ソースコードの入手とビルドの方法については次のページにあります(英語)。
http://server.imgseek.net/category/source/
SVNhttps://imgseek.svn.sourceforge.net/svnroot/imgseek/trunk/net.imgseek.imgdbからソースをチェックアウトしてきます。
ビルドにはpython-devやコンパイラが必要ですので、インストールしておいてください。
今回は、

python2.5-dev
g++

をインストールしておきました。
"src/net/imgseek/imgdb/core"ディレクトリにビルド用のスクリプトがあるので、実行します。

$ python build-python.py build

buildディレクトリの下にシステムタイプの名前のディレクトリがあり、その中にimgdb.soが作成されています。
imgdb.soをisk-daemonのimgSeekLibディレクトリにコピーし、ファイル名を"_imgdb.so"に変更します。
また、ソースの確認はしていませんがロードできない関数がimgSeekLib/imgdb.pyにあったので、コメントアウトしておきます。

#mostPopularKeywords = _imgdb.mostPopularKeywords
  • settings.pyの編集

isk-daemonのルートにsettings.pyという名前の設定ファイルがあるので、編集します。
databasePathにデータベースファイルのパスを指定します。
登録したデータを自動的に保存したい場合はautomaticSaveをTrueにしておきます。saveIntervalに設定した間隔(秒)で自動的に保存されるようになります。
startAsDaemonをTrueにするとデーモン動作させられるのですが、TwistedのDocumentRootの設定がカレントディレクトリからの相対で書かれているので、isk-daemon.pyを修正する必要があります。

isk-daemon.pyを実行してisk-daemonを起動します。

$ python isk-daemon.py
  • isk-daemonの管理画面でデータベースを作成する

http://localhost:31128/にブラウザでアクセスするとAjaxを使った管理画面が表示されます。
http://tokibito.orz.hm/static/img/isk-daemon_admin.png
画面左の『Databases』メニューを選択し、『Create new』タブからデータベースID(半角数字)を入力して『Add』ボタンをクリックします。これでデータベースが作成されます。
データベースIDはAPIの利用時に指定する必要があるので、メモしておくとよいです。

  • APIを利用する

APIリファレンス(英語)は次のページにあります。
http://server.imgseek.net/category/documentation/api/
また、isk-serverのアーカイブのdocディレクトリに、java/php/pythonのクライアントのサンプルコードがあるので、参考になるかと思います。

  • APIでデータベースに画像を登録する

まず検索を行うために画像をデータベースに登録する*1必要があります。
Pythonでの場合の例だと次の通り。

from xmlrpclib import ServerProxy

dbId = 1   # データベースID
id = 1     # データベース上での画像の識別ID(任意)
filepath = '/var/www/example.com/htdocs/foo.png'
fileurl = 'http://example.com/foo.png'

server = ServerProxy('http://localhost:31128/RPC')
# サーバ上のローカルファイル指定の場合
server.addImg(dbId, id, filepath)
# インターネット上のファイルの場合
server.addImg(dbId, id, fileurl, True)
  • APIで画像を検索する

画像の検索では、データベース上の画像の識別IDを指定し、対象の画像と類似する画像のID一覧を取得できます。

from xmlrpclib import ServerProxy

dbId = 1      # データベースID
id = 1        # 検索する画像の識別ID
numres = 10   # 取得する検索結果の数-1

server = ServerProxy('http://localhost:31128/RPC')
results_list = server.queryImgDb(dbId, id, numres)
for result_id, result_ratio in results_list:
    print 'ID: %d, Ratio: %f' % (result_id, result_ratio)

実行例.

ID: 11, Ratio: 99.741603
ID: 1, Ratio: 99.741603
ID: 1182, Ratio: 32.820870
ID: 83, Ratio: 32.097147
ID: 136, Ratio: 29.387254
ID: 298, Ratio: 27.346831
ID: 388, Ratio: 26.226296
ID: 54, Ratio: 26.049704
ID: 53, Ratio: 26.049704
ID: 755, Ratio: 24.954222
ID: 123, Ratio: 24.647017
  • 画像の実体をどう扱うか

isk-daemonは、画像のメタデータのみをデータベースに保存するため、画像ファイルの管理は完全に切り離されています。
実際にこのエンジンを用いてアプリを作成する場合、RDBMSなどを使ってisk-daemon上のIDとファイルのパスを結びつけるような形にすればよいです。

*1:実際は画像のメタデータが登録されます。