GoogleのOCRライブラリ Tesseract

急遽OCRを利用する必要があったので、フリーのライブラリを探してみた。 Linux(CentOS)で使えるものが無いか物色する中で、GoogleがOSSとして提供しているライブラリTesseractがあったので、導入から使用方法までを簡単に書いてみる。

導入

バイナリでも落ちているようだけど、ひとまずソースをダウンロードしてコンパイル、インストールすることにした。

下準備

デフォルトのCentOSでは入っていないパッケージをインストールする必要がある。

 leptonicaのインストール

Tesseractは内部でleptonicaを呼び出しているようなので、こちらを先にインストールする必要がある。

 tesseractのインストール

いよいよtesseract本体のインストール。 OCRで解析させたい言語ごとに解析用ファイルをダウンロードしておく必要がある。今回は英語と日本語を使う事にした。 この手順でインストールすると、tesseract本体は/usr/local/share/にインストールされるので、言語ごとの対応ファイルは解凍後、/usr/local/share/tessdataに移動させる。

これでインストールは完了。

解析させる

下記のようにコマンドを叩けば画像ファイル[hogehoge.gif]を解析してfugafuga.txtに、テキストファイルとして結果を吐き出す。

精度を上げる

このままでは、日本語はおろか英語であっても惨憺たるありさまなので、何とか精度向上を図る。

  1. 辞書ファイルを指定する
  2. 画像を拡大する
  3. 画像を二値化する

1.辞書ファイルを指定する

せっかくダウンロードしてきて展開した辞書ファイルがあるので、それで何とかなる内容なら積極的につかっていきましょう。 例えば日本語の辞書ファイルを指定する方法は以下の通り。

また、使用されている文字が限定的な場合は、設定ファイルを用意することで精度を向上させることが可能です。 1とlをよく間違って解析したりするのですが、例えば数字が絶対含まれず、アルファベットのみ使用されている画像を解析するのであれば、下記内容の設定ファイルを作成することで誤解析を減らすことが可能です。

上記の設定ファイルを読み込ませるには下記のように指定します。

2.画像を拡大する

解析する画像の文字が小さいと精度が出ません。いろいろ拡大して、精度の出るサイズになるよう調整してみてください。

3.画像の二値化

アンチエイリアスなどでエッジがぼやけている画像では精度が出ません。なので画像を二値化(白と黒にくっきり分ける)することで精度の向上が期待できます。

大いに参考にさせてもらったサイト

http://magiccastanets.blogspot.jp/2012/06/google-tesseract-ocr-os-centos6.html http://www.slideshare.net/takmin/tesseract-ocr WEB-DB-PRESS-Vol-76

http://qiita.com/hatahata/items/4daddebb5e84ea575332

Phpstorm6 リモートデバッグ

Vagrant + Chef で開発環境を簡単に立ち上げることができるようになったので、Phpstorm6を使ってリモートデバッグできる環境を整えてみたいと思います。

Vagrant+ChefでApache、PHP、MySQLがインストールされていることが前提となりますが、何らかの仮想サーバやリモートサーバでもほぼ同じ作業でOKだと思います。

1.はじめに

まずはサーバにxDebugをインストールしますが、Chefでやっちゃいます。

chef-repoのcookbooksにあるレシピに、definitionsディレクトリがあるので、そこにpeclのDSLを定義します。

上記の例では/chef-repo/cookbooks/myrecipe/definitionsにpecl.rbというファイル名で、下記内容のファイルを作成します。

次に、レシピファイル(今回の例では/chef-repo/cookbooks/myrecipe/recipes/default.rb)に次の一文を追加します。

これで vagrant up すると自動的にxdebugがインストールされます。

2.php.iniの編集

xdebugを有効化するため、php.iniを編集します。

ウチの環境では下記のような設定をphp.iniに追加しました。

Chefを使っているなら、templateかcookbookfilesで処理するといいでしょう。

だがしかし!ここでいろいろハマりました。

「xdebugのマニュアル読みましょうw」というのはひとまず置いといて。

・xdebug.remote_autostart
これが0だと、スクリプトが走っても仮想サーバ側のデバッグ情報がホストOS側に投げられませんでした。

以前、xampp環境でxdebugを使った時はここが0でも上手く動いていたのですが...。

ちなみに、マニュアルにはここが0だと、GETかPOSTまたはCookieが投げられたらデバッグ情報投げるよ、1だと関係なく毎回デバッグ情報投げるよ、みたいに書かれているのですが、ウチの場合は期待通りに動作してくれませんでした。

・xdebug.remote_host
インターネット上の情報を拾ってきて設定を進めていて、最初は下記のような記述にしていたのですが...、

これだとホストOS側にデバッグ情報が送信されてきませんでした。

ここも、以前xamppで環境を作ったときはremote_connect_back = 1で上手く動作していたのですが...。

あと、ウチの環境だけかどうかわかりませんが、xdebugが動作したとき(PHPスクリプトが実行されたとき)にデバッグクライアント(今回の場合はPhpstorm)がデバッグポートを待ち受けていない場合、PHPの実行が非常に遅くなりました。

いろいろ試して気が付いたのですが、どうやらxdebugがデバッグクライアントのポートに接続しにいっても接続先がないため、timeoutするまで延々スクリプトの実行が遅延しているようです。

3.Phpstorm側の設定

Ctrl+Alt+SでPhpstormの設定画面を開きます。

Project SettingsのPHP->Debugを開きます。

中央付近のXdebugのDebug portに9000を設定します。

環境によってはこれだけでOKなのですが、ウチの場合はサーバーと作業フォルダのマッピングが必要でした。

4.ファイルマッピング

完全にローカルPCだけで完結している開発作業ならともかく、Vagrantで立てた仮想サーバとホストOSといった具合にサーバマシンと開発マシンが分かれている場合、サーバ側のファイルが、ローカルのどのファイルに相当するのかをマッピングしてやる必要があります。

まずはCtrl+Alt+Sで設定画面を開きます。

Project SettingsのPHP->Serversを選択。

サーバー情報がまだ追加されてない場合は「+」をクリック、既に仮想サーバが追加されている場合はそれを選択します。

Name: 適当にサーバ名を入力
Host:仮想サーバのIPかアドレス
Port:80(デフォルト)
Debugger:Xdebug
Use path mappings:チェックを入れて、ディレクトリツリーを表示します

File/Directoryに現在のローカル(ホストOS)側のプロジェクトで使用しているディレクトリやファイルが表示されるので、それらがサーバ側のどれに該当するかをAbsolute path on the serverに指定します。

ファイルを1個づつ指定しなくても、ディレクトリ構造が同じであればトップディレクトリをマッピングすればOKですが、もし仮想サーバと作業フォルダで構造が異なっている場合はサブディレクトリ単位またはファイル単位で指定する必要があります。

Absolute path on the serverは、そう書かれているように仮想サーバ(Vagrant)側の絶対パスで指定します。

例えばプロジェクトの作業フォルダが c:\project で、そこにindex.phpを作成したとします。

CentOSなどでyumからApacheをインストールした場合のデフォルトは/var/www/htmlがWebサーバのドキュメントルートになるはずなので

c:\project/var/www/html にディレクトリ単位でマッピングするか、

c:\project\index.php/var/www/html/index.php のようにファイル単位で個別にマッピングするかのどちらかになりますが、多くの場合はディレクトリ単位で指定する方がお手軽に済むでしょう。

以上で設定は完了になります。

あとは、Phpstorm側のリモートデバッグをOn(リモートデバッグスイッチをクリック)にしてブラウザから仮想環境のPHPスクリプトを実行すればブレークポイントで停止するはず!

Cakephp2 DBの変更がmodelに反映されない

データベーステーブルの構造を変更(カラムの追加や変更など)したのに、追加したカラムに対して$result[‘Model’][‘field_added’]とかでアクセスしたら怒られました。

本番環境でのみ発生するので最初悩みましたが...。

Debugモードが0の場合、Cakephpではモデルのキャッシュが結構長い時間有効になっているようで、モデルにテーブルの変更内容が反映されないことが原因でした。

で、ググって見つけたサイトがCakePHPでテーブル構造を変更しても反映されないでしたが、単純に/app/tmp/cache/modelsにある問題のテーブルに該当するキャッシュを消しても解決しませんでした。

んでもって、次に消したキャッシュファイルが、
/app/tmp/cache/persistent/myapp_cake_core_method_cache

これで変更が反映されました。

めでたし、めでたし。

Cakephp2.xでのBlackHoleまとめ

CakePHPでSecurityコンポーネントを使っていると、時折発生するBlackHole。
発生時はエラーログを確認するしか詳細な原因がわからないのですが、多くの場合は以下のどれかに該当するのではないでしょうか。

  • CSRFチェックのトークンがUseOnceなのにフォーム送信後にブラウザの「戻る」とか押してからフォームを再送した。
  • フォームを生成してから30分過ぎた。(トークンのデフォルト有効期限が30分)
  • JavaScriptでHidden項目を書き換えた。
  • JavaScriptで入力項目を追加したり取り去ったりした。

ブラウザの戻るを想定する場合はトークンを複数回使えるように設定しなければいけません。(ただし、セキュリティー的には若干低下します)

複数回使いまわせるようにするにはControllerのbeforeFilterなどで以下のようにcsrfUseOnceをfalseにします。

また、トークンのデフォルト有効期限が短すぎると判断される場合はbeforFilterで

とするか、または$componentsの設定で以下のように設定すると良いでしょう。

そもそもCSRF対策不要だよ!ってアプリケーションでは、

として、CSRF対策機能をばっさり無くすことも可能ですが、セキュリティー的に問題が残るため、多くの場合はおすすめできません。

あと、JavaScriptでフォームの中身を変更すると、ことごとくBlackHoleに吸い込まれる事がありますが、Securityコンポーネントを有効にするとデフォルトでついてくる機能「FormTamperingPrevention」のおかげです。

Cakeがフォームを生成した時にフォームの内容をまるごとハッシュ化しており、フォーム送信時にフォームの内容に差異が生じていると、フォームを不正に改変されたとみなしてBlackHoleに吸い込んでくれる機能です。

ただし、JavaScriptでHiddenに値をセットしたり、Ajaxを使う場合に項目を動的に追加したりなんかしてもBlackHoleに吸い込んでくれるので、そのような場合は以下の何れかの対策が必要です。

FormTamperingPreventionをまるっと無効にする場合はbeforeFilterで以下のように指定します。

また、特定のフィールドだけFormTamperingPreventionの対象外としたい場合(JavaScriptで値をセットするhidden項目など)は、ViewのFormHelperを用いて以下のように指定することで回避できます。

 

BlackHoleに吸い込まれた時の処理

BlackHoleに吸い込まれた場合、デフォルトではDebugモードにもよりますが、プロダクションモードでは真っ白なページが表示され、404エラーが返されてしまいます。
では実際に何らかの問題が生じてBlackHoleに吸い込まれるべくして吸い込まれた場合、どのようにハンドリングすればスマートでしょうか。

ここはひとまずCakePHPのCookBookにのっとってblackholeメソッドを用意し、そちらに処理を任せるようにしましょう。

上記はCookBookからの引用になります。またblackholeメソッドのパラメータ$typeは以下の値をとるようですが、内容はCookBookのほぼ直訳になります。

  • ‘auth’ フォームバリデーションエラーまたはコントローラ/アクションの不一致によるエラー。
  • ‘csrf’ CSRFエラー
  • ‘get’ HTTPメソッド制限違反
  • ‘post’ HTTPメソッド制限違反
  • ‘put’ HTTPメソッド制限違反
  • ‘delete’ HTTPメソッド制限違反
  • ‘secure’ SSLメソッド制限違反

なので、blackholeメソッド側で$typeを参照し、エラー内容に沿ったメッセージを表示してあげると良さそうです。

タッチデバイス

新しいデバイスが届きました。

ロジクールのタッチパッド「T650」です。image

真ん中の正方形の物体がブツです。

今まで使っていたマウスが古くなり、ゴム製の部分が削れて手や設置面が黒く汚れてくるようになったため買い替えを決意しました。

購入に当たり色々検討したのですが、なるべくキーボードから手をはなさずにカーソル操作ができるデバイスということで、このタッチパッドにしました。

ひと昔前のタッチパッドは非常に使い辛いシロモノで、ノートパソコンにオマケでついてくるパッドのイメージしかありませんでしたが。
AppleのMagic Trackpad(マジ虎)以来、タッチパッドが大きく進化したように思います。

WinユーザーとしてはAppleのマジ虎は憧れでしたが、T650でようやくそれに近い操作感のデバイスがWinでも使えるようになりました。

二本指タップで右クリック。
二本指スワイプで上下左右のスクロール。
三本指スワイプでアプリケーションの切り替えや、デスクトップの表示、戻る、進む。
ピンチ操作で画面のズームイン、ズームアウト。

この辺の操作ができることで、従来のタッチパッドとは比べ物にならない用な操作性を得ることができるようになっています。

もちろん、使い慣れたマウスの方がしっくり来るし、細かい操作はマウスに軍配が上がる気もしますが、私にとっては十分使えるデバイスのようです。

何より、キーボードの手前に配置することで、マウスに握り変えることなくカーソル操作ができるのがとても素晴らしい点です。

また、写真の通りキーボードアームと併用することで、常に手の位置を膝上付近から離す事なくすべての作業を完結できることで、肩の疲れ方がかなり緩和されることが期待されます。

この辺、気になる方は「膝上キーボード」でググってみてください。

i18n

オープンソース系のコードを眺めているとたまに目にする「i18n」の文字。

国際化が行われているソフトウェアでよく出てくるのですが、翻訳関係のファイルを扱う関数やライブラリなんかにこの文字が冠せられてたりします。

最初はあまり気にも留めなかったのですが、ふとしたきっかけで知った「i18n」の意味は「internationalizationの略」というもの。
最初のiと、最後のnの間に18文字あるから「i18n」…なんて雑な略し方なんだよ。

でも、この略し方だと相当長いのでもOKですよね。

例えばタイの首都、バンコクの正式名称。
英語表記だと「Krung­thep­maha­nakhon­ Amon­rattana­kosin­ Mahinthar­ayutthay­a Maha­dilok­phop Noppha­ratratchathani­burirom­ Udom­ratchaniwet­mahasat­han­ Amon­phiman­awatan­sathit Sakkathatiya­witsanukamprasit」なので、途中のスペースを削ると全部で212文字。

…ということは「k210t」でOK!

いやー、タイの人に怒られそうだわ。

Nginx

ちょっと前からあちこちのブログでも名前の挙がるNginx(エンジンエックスと読むらしい)は、ロシアで開発が始まったハイパフォーマンスなオープンソースのWebサーバ。

ここ最近まではWebアプリケーションの開発といえばLinux+Apacheが定番だったけど、Webアプリケーションがよりリッチになって、膨大な数のアクセスを捌く必要が出てくると、もはやApacheでは追いつかないという状況も多いらしい。

そんなごっついWebサイトを運営するかどうかはともかく、低リソース消費のWebサーバなら低コストのサーバを使って同じパフォーマンスを出すことが可能になるわけで、結果として運用コストを下げることにつながるはず!

そんなカッコいいNginxを使ってみたいんだけど、また一から勉強するのはめんどくさい時間が無いなぁという今日この頃。

誰か僕に、Nginxについて、手取り足取り教えてよ!

電子書籍と紙の本

先日うちに来た友人が「本は電子じゃなくて紙で読みたい」と言っておられましたが、僕の場合は可能であれば技術書は電子書籍で購入しますし、紙の本を買った場合は適当なタイミングで自分でPDF化(自炊)して保存しております。

オライリーの本なんかは、公式サイトからPDF版またはepub版を直接購入することが可能なので、たぶんもうこの出版社の紙の本は買わないだろうなぁと思っとります。

自分の思う電子書籍のメリットは以下の2点。
1.かさばらない&デカくても重くない
2.キーワード検索できる
3.電子書籍形式で販売されていれば、Download & Go ですぐ読める

特に技術書や資料などでは2番のメリットは非常に大きい。

小説や漫画なんかは単語を検索するという機会も少ないと思うので、電子書籍である必要性はあまり無いかもしれませんね。

逆に、電子書籍に足りないものは、「パラパラめくる」という紙の本独自のインターフェイス。
本ってのはついついパラパラめくりたくなるんですが、僕だけでしょうか?

本を読んでいると、もう「めくる」という行為が遺伝子に染みついてるんじゃないかと思うくらいに、本をめくって読みたくなります。

電子書籍であっても「めくる」行為ができないことでフラストレーションを感じることがよくあって、「パラパラめくる」インターフェイスを既存のデバイスでどうにか実現できないかな?
なんて考えちゃうときもあります。

こういうページ検索手法は非論理的だし非効率だけど、すごく本能的な動作のように思えるで、それができないことが電子書籍のデメリットかなぁ。

本をめくるときに指先が覚えている「大体この辺!」っていう感覚と、パラパラとページをはじくスピードに連動して、一瞬だけ目に飛び込む刹那的なページ情報から目的のページを特定する人間の動作を、何とか電子書籍で実現できないもんだろうか。
(誰かエロい人、作って!)

まぁ、あえて不便なインターフェイスを必死になって実装するってどうよ?って気もしますが...。

そのうち時代が流れて電子書籍的な“何か”が一般化した時には、「本をめくる」という行為も過去の遺物となる日が、はたして来るものなのでしょうか。

MySQL+Spiderがクラッシュした際の復活方法

MySQL+Spiderの組み合わせで運用している場合、Spiderノードがメモリ不足によりクラッシュする場合がある。
よくある。とくにシステム構築中のテスト稼働や大量データの移行時、パラメータチューニング中など…。

ところがこれが発生すると、通常のrestartやstop~startが効かなくなる。
sockが無いとか、pid fileが腐ってると言われたりして、まったくMySQL起動しなくなる。

そんな時の解決方法として下記手段を用いているが、それでも復活しない場合もある...。

1.まずはsockファイルを作成

内容はブランクでよいので、このまま保存してviを閉じる。

2.pidファイルを作成
pidファイルが無くなっているか腐っている場合が多いので、こちらもブランクのファイルを作成。
パスやpidファイル名は適宜変更。
(startする際にpidファイルに関するエラーメッセージが表示されるので、エラーメッセージに表示されるpidファイル名を利用するとよい)

3.上記で作成したファイルの権限を変更

4.mysqld_safeを起動させ、その間にmysqldをスタート
ターミナルを2つ用意して、まずはmysql_safeを起動。

その間に別のターミナルでMySQLサーバを起動します。

これで起動するときがあります。
それでも無理な時はサーバを窓から投げ捨ててください...。

歴戦のDBAとかではないのでこのような対処療法しか知りません。
どなたか、もっと良い方法をご存知の方は是非教えていただきたい。