2014-12-06
2014-11-24
railsのログに情報を追加する
railsのログに情報を簡単に追加する方法として
config.log_tags
を利用する方法があります。
config/environment/develpment.rb
や
config/environment/production.rb
に以下のように書くとセッションIDとリモートIPをログに追加できます。
ここでふと、このlog_tagsにはどんなものが記載できるのだろう?と思ってみたわけです。
調べてみたところ、log_tagsで記載した内容が、実際にログにタグとして追加する処理は以下のcompute_tagsの部分で行っているようです。
https://github.com/rails/rails/blob/21a71cd5d8f266252278a63316a99cc403a32cad/railties/lib/rails/rack/logger.rb#L57
Sybolとして指定したものは、requestオブジェクトのメソッドとして呼ばれるようです。なのでrequestオブジェクトのメソッドがここで指定できる候補になります。
実際に、以下のようにuser_agentを追加してみたら
以下のようなログが出力されました。
[a0b386ac-c108-4820-be22-4fbf8d14a1e8] [10.10.10.10] [Mozilla/5.0(Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36] Processing by WelcomeController#index as HTML
log_tagsで指定できるのは、Symbol以外にProcも指定できて、この場合はProcオブジェクトにrequestオブジェクトを引数として渡されて処理されるようです。
またそれ以外に、文字列を指定した場合は、その文字列が単純にセットされるようです。
ただrequestのメソッドならば、なんでもSymbolで指定したり、Proc内で処理できるわけではなさそうです。sessionなどは処理できませんでした。
どうも、通常は、ログの処理よりもセッションの処理の方が後に行われるようで、sessionを指定してもログの処理の段階ではセッションの処理がまだ行われていないことが原因のようです。
なので、以下のサイトで紹介されているように、処理の順番を入れ替えることでsessionも扱えるようになるようです。
http://threetreeslight.com/post/51883603368/rails-id-ip
config.log_tags
を利用する方法があります。
config/environment/develpment.rb
や
config/environment/production.rb
に以下のように書くとセッションIDとリモートIPをログに追加できます。
config.log_tags = [ :uuid, :remote_ip ]
ここでふと、このlog_tagsにはどんなものが記載できるのだろう?と思ってみたわけです。
調べてみたところ、log_tagsで記載した内容が、実際にログにタグとして追加する処理は以下のcompute_tagsの部分で行っているようです。
https://github.com/rails/rails/blob/21a71cd5d8f266252278a63316a99cc403a32cad/railties/lib/rails/rack/logger.rb#L57
Sybolとして指定したものは、requestオブジェクトのメソッドとして呼ばれるようです。なのでrequestオブジェクトのメソッドがここで指定できる候補になります。
実際に、以下のようにuser_agentを追加してみたら
config.log_tags = [ :uuid, :remote_ip, :user_agent ]
以下のようなログが出力されました。
[a0b386ac-c108-4820-be22-4fbf8d14a1e8] [10.10.10.10] [Mozilla/5.0(Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36] Processing by WelcomeController#index as HTML
log_tagsで指定できるのは、Symbol以外にProcも指定できて、この場合はProcオブジェクトにrequestオブジェクトを引数として渡されて処理されるようです。
またそれ以外に、文字列を指定した場合は、その文字列が単純にセットされるようです。
ただrequestのメソッドならば、なんでもSymbolで指定したり、Proc内で処理できるわけではなさそうです。sessionなどは処理できませんでした。
どうも、通常は、ログの処理よりもセッションの処理の方が後に行われるようで、sessionを指定してもログの処理の段階ではセッションの処理がまだ行われていないことが原因のようです。
なので、以下のサイトで紹介されているように、処理の順番を入れ替えることでsessionも扱えるようになるようです。
http://threetreeslight.com/post/51883603368/rails-id-ip
2014-11-06
rubyで一時的にワーニングなしで定数を変更する
rubyで定義済みの定数の値を変更するとワーニングが出力されます。
これは本来ありがたい仕様だと思うのですが、
今回、どーしても一時的に定数を書き換えたいケースがでました。
ワーニングが出るだけで動きに支障はないので、そのままでもよかったのですが
なんとなくワーニングが消せないかなぁと調べてみました。
以下のような感じでできました。
一時的な変更と言うより、一回削除して再作成です。
これでクラスやモジュールに定義されている定数をワーニングなしで一時的に置き換えることができました。
ちなみにグローバルに定義している定数の場合は、以下のような感じです。
これは本来ありがたい仕様だと思うのですが、
今回、どーしても一時的に定数を書き換えたいケースがでました。
ワーニングが出るだけで動きに支障はないので、そのままでもよかったのですが
なんとなくワーニングが消せないかなぁと調べてみました。
以下のような感じでできました。
一時的な変更と言うより、一回削除して再作成です。
class A MOGE="momomo" end p A::MOGE -> "momomo" muga = A::MOGE A.send :remove_const, :MOGE A::MOGE = "mimimi" p A::MOGE -> "mimimi" A.send :remove_const, :MOGE A::MOGE = muga p A::MOGE -> "momomo"
これでクラスやモジュールに定義されている定数をワーニングなしで一時的に置き換えることができました。
ちなみにグローバルに定義している定数の場合は、以下のような感じです。
HOGE = "hohoho" p HOGE -> hohoho" fuga = HOGE Object.send :remove_const, :HOGE HOGE="hihihi" p HOGE -> "hihihi" Object.send :remove_const, :HOGE HOGE = fuga p HOGE -> "hohoho"
2014-09-25
Raspberry Piで音声合成してしゃべらせてみる
Raspberry Piで音声合成を試してみます。
以下を参考にしています。
http://shokai.org/blog/archives/6893
Raspberry Piで音が出るようにするには、以下を参照ください。
Raspberry Piで録音再生をしてみる
音声合成にはopen-jtalkというものを利用します。
まずはopen-jtalkをインストールします。
sudo apt-get install open-jtalk hts-voice-nitech-jp-atr503-m001 open-jtalk-mecab-naist-jdic
デフォルトとは別の音声データを用意します。
wget http://downloads.sourceforge.net/project/mmdagent/MMDAgent_Example/MMDAgent_Example-1.3.1/MMDAgent_Example-1.3.1.zip
unzip MMDAgent_Example-1.3.1.zip
sudo cp -R MMDAgent_Example-1.3.1/Voice/* /usr/share/hts-voice/
以下を参考にしています。
http://shokai.org/blog/archives/6893
Raspberry Piで音が出るようにするには、以下を参照ください。
Raspberry Piで録音再生をしてみる
音声合成にはopen-jtalkというものを利用します。
まずはopen-jtalkをインストールします。
sudo apt-get install open-jtalk hts-voice-nitech-jp-atr503-m001 open-jtalk-mecab-naist-jdic
デフォルトとは別の音声データを用意します。
wget http://downloads.sourceforge.net/project/mmdagent/MMDAgent_Example/MMDAgent_Example-1.3.1/MMDAgent_Example-1.3.1.zip
unzip MMDAgent_Example-1.3.1.zip
sudo cp -R MMDAgent_Example-1.3.1/Voice/* /usr/share/hts-voice/
ここまでくれば、音声合成はもう少しです。
open-jtalkで実際にしゃべらせるには、なんか面倒なコマンドを打つ必要があるようです。
それを簡単にするためのスクリプトが公開されているので使わせていただきます。
wget https://gist.githubusercontent.com/shokai/2892965/raw/jsay
chmod 755 jsay
ちなみにスクリプト内の最初の方でcdしている部分を変更することで声を変えることができるようです。
試してみます。
./jsay だめよー。だめだめ
い~~じゃないの~~
2014-09-24
Raspberry Piで録音再生をしてみる
Raspberry Piで録音と再生をしてみます。
以下を参考にしています。
http://cubic9.com/Devel/%C5%C5%BB%D2%B9%A9%BA%EE/RaspberryPi/%C6%FC%CB%DC%B8%EC%B2%BB%C0%BC%C7%A7%BC%B1/
今回、録音再生するために使ったのは、以下のものになります。
Raspberry PiにUSB接続して、これにスピーカやマイクを接続して使います。
まずは、機器を使えるようにします。いろいろ作業用に事前にrootになっておきます。
sudo su -
まずは接続されていることを確認します。
lsusb
とコマンドをうって
Bus 001 Device 006: ID 0d8c:013a C-Media Electronics, Inc.
みたいのが出ていれば、きちんと認識されています。
音関連モジュールの優先度を確認します。
cat /proc/asound/modules
---------------
0 snd_bcm2835
1 snd_usb_audio
---------------
変更の仕方を検索すると以下の部分のコメントアウトして
#options snd-usb-audio index=-2
options snd_bcm2835 index=-2
を追加してsnd_bcm2835の優先度を下げる方法と
options snd-usb-audio index=0
を追加してsnd-usb-audioの優先度をあげる方法の2通りがある感じです。
今回はsnd-usb-audio優先度をあげてみます。
---------------
再起動したら、またrootになっておきます。
sudo su -
cat /proc/asound/modules
としてUSBオーディオが優先されていることを確認します。
---------------
---------------
とりあえず音が出るかを確認してみます。mplayerというを使ってみます。
apt-get install mplayer
とりあえず最初から入っているmp3ファイルを探してみます。
find / -name *.mp3
見つけたファイルを再生して音が出ることを確認してみます。
mplayer /usr/share/scratch/Media/Sounds/Vocals/Sing-me-a-song.mp3
ちなみに音がなっている間に*を押すと音量が上がり、/を押すと下がるようです。
いよいよ録音を試して見ます。
まず、マイクの感度を最大にしておきます。
amixer sset Mic 16
録音は以下のような感じです。
arecord -r 16000 -f S16_LE test.wav
マイクでしゃべり終わったらcrtl+Cを押すと録音が完了します。
録音したものの再生は以下の感じです。
aplay test.wav
以下を参考にしています。
http://cubic9.com/Devel/%C5%C5%BB%D2%B9%A9%BA%EE/RaspberryPi/%C6%FC%CB%DC%B8%EC%B2%BB%C0%BC%C7%A7%BC%B1/
今回、録音再生するために使ったのは、以下のものになります。
Raspberry PiにUSB接続して、これにスピーカやマイクを接続して使います。
まずは、機器を使えるようにします。いろいろ作業用に事前にrootになっておきます。
sudo su -
まずは接続されていることを確認します。
lsusb
とコマンドをうって
Bus 001 Device 006: ID 0d8c:013a C-Media Electronics, Inc.
みたいのが出ていれば、きちんと認識されています。
音関連モジュールの優先度を確認します。
cat /proc/asound/modules
---------------
0 snd_bcm2835
1 snd_usb_audio
---------------
となっていれば、内蔵オーディオが優先されているので、USBで接続したものの優先度をあげる設定が必要です。
変更は、以下のファイルに対して行います。
/etc/modprobe.d/alsa-base.conf変更の仕方を検索すると以下の部分のコメントアウトして
#options snd-usb-audio index=-2
options snd_bcm2835 index=-2
を追加してsnd_bcm2835の優先度を下げる方法と
options snd-usb-audio index=0
を追加してsnd-usb-audioの優先度をあげる方法の2通りがある感じです。
今回はsnd-usb-audio優先度をあげてみます。
vi /etc/modprobe.d/alsa-base.conf
---------------
# options snd-usb-audio index=-2
options snd-usb-audio index=0---------------
設定を変更したら再起動します。
reboot再起動したら、またrootになっておきます。
sudo su -
cat /proc/asound/modules
としてUSBオーディオが優先されていることを確認します。
---------------
0 snd_usb_audio
1 snd_bcm2835---------------
apt-get install mplayer
とりあえず最初から入っているmp3ファイルを探してみます。
find / -name *.mp3
見つけたファイルを再生して音が出ることを確認してみます。
mplayer /usr/share/scratch/Media/Sounds/Vocals/Sing-me-a-song.mp3
ちなみに音がなっている間に*を押すと音量が上がり、/を押すと下がるようです。
いよいよ録音を試して見ます。
まず、マイクの感度を最大にしておきます。
amixer sset Mic 16
録音は以下のような感じです。
arecord -r 16000 -f S16_LE test.wav
マイクでしゃべり終わったらcrtl+Cを押すと録音が完了します。
録音したものの再生は以下の感じです。
aplay test.wav
2014-08-12
Windows Updateで80072EE2エラーが出たとき
最近Windows Updateをすると80072EE2エラーが出てとまってしまっていました。
調べると以下のサイトの対応をとるとよい感じでした。
http://capacitor.blog.fc2.com/blog-entry-137.html
しかし、この対応を行ってもエラーが出続けていました。
マイクロソフトのサイトが混んでいることが原因で出ることもあると書いてあったのを見た気がしたので、しばらく様子を見ていたのですが全然復旧しませんでした。
というわけで本格的に原因を調べてみました。
どうやら
調べると以下のサイトの対応をとるとよい感じでした。
http://capacitor.blog.fc2.com/blog-entry-137.html
しかし、この対応を行ってもエラーが出続けていました。
マイクロソフトのサイトが混んでいることが原因で出ることもあると書いてあったのを見た気がしたので、しばらく様子を見ていたのですが全然復旧しませんでした。
というわけで本格的に原因を調べてみました。
[スタート]-[ファイル名を指定して実行] から %windir% を実行して開いたディレクトリにあるWindows Update.log
がWindows Updateのログになっているようなので、このファイルを見てみました。
私の場合は、
WSUS server
という記載があって、マイクロソフトのものでないサーバをさしている状態になっていました。
どうやらずいぶん昔にWindowsUpdateを別のサーバから取得するような設定にしていて、そのサーバが、ここ最近知らないうちに倒れていたようです。
そのため、WindowsUpdateの情報を取得しようとしたけどタイムアウトが起きて、エラーが出ていたようです。
というわけで、WindowsUpdateの取得先をデフォルトに戻すようにします。
レジストリを修正する必要があります。
変更内容は、以下のとおりです。
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate
の下の
WUServer
と
WUStatusServer
をそれぞれ空白に変更します。
そして
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU
の下の
UseWUServer
を0に変更します。
そしてWindows Updateサービスを再起動します。
これで私の場合は、エラーが解消されました。
2014-08-05
mysqlで監査ログを設定する
MySQLでもデータベースの操作ログを取ったほうがよいのかなぁと思ってしまう今日この頃です。
というわけで、どのようにすれば監査ログを残せるのかを調べました。
Enterprise Editionには、監査の機能があるようですが、今回はEnterprise Editionのことは対象外です。
他にMcAfeeがMySQL用の監査ツールを提供しているようなので、こちらの使い方になります。
以下はすべてrootユーザで行うものとします。
まずはインストールです。
https://bintray.com/mcafee/mysql-audit-plugin/release
から自分の環境にあったものをダウンロードします。
今回の環境は、64bitCentOS6上のMySQL5.6とします。
ファイルを取得して、zip解凍してプラグイン用のディレクトリにコピーをします。
wget http://dl.bintray.com/mcafee/mysql-audit-plugin/1.0.5/audit-plugin-mysql-5.6-1.0.5-479-linux-x86_64.zip
unzip audit-plugin-mysql-5.6-1.0.5-479-linux-x86_64.zip
cp audit-plugin-mysql-5.6/lib/libaudit_plugin.so /usr/lib64/mysql/plugin/
の
vi /etc/logrotate.d/mysql-audit-log-rotate
上記で利用する.my.cnfも作成します。
vi /root/.my.cnf
というわけで、どのようにすれば監査ログを残せるのかを調べました。
Enterprise Editionには、監査の機能があるようですが、今回はEnterprise Editionのことは対象外です。
他にMcAfeeがMySQL用の監査ツールを提供しているようなので、こちらの使い方になります。
以下はすべてrootユーザで行うものとします。
まずはインストールです。
https://bintray.com/mcafee/mysql-audit-plugin/release
から自分の環境にあったものをダウンロードします。
今回の環境は、64bitCentOS6上のMySQL5.6とします。
ファイルを取得して、zip解凍してプラグイン用のディレクトリにコピーをします。
wget http://dl.bintray.com/mcafee/mysql-audit-plugin/1.0.5/audit-plugin-mysql-5.6-1.0.5-479-linux-x86_64.zip
unzip audit-plugin-mysql-5.6-1.0.5-479-linux-x86_64.zip
そして設定です。
/etc/my.cnfの
[mysqld]セクションに以下を追加します。
------------------------------------------------
# McAfee Audit-Plugin
plugin-load=AUDIT=libaudit_plugin.so
audit_json_file = On
------------------------------------------------
他にも設定できる項目はあるのですが、とりあえず最低限動くようにするには上記でよさそうです。
他の項目に関しては、以下を参照してください。
設定が完了したらmysqlを再起動です。
service mysqld restart
プラグインが設定されているかの確認は、以下を実行してaudit系の設定が表示されればOKです。
mysql> SHOW VARIABLES LIKE 'audit_%';
これで監査ログが
/var/lib/mysql/mysql-audit.json
に出力されることになります。
出力されるログの内容に関しては以下が参考になります。
監査ログは、いっぱい出力されるのでファイルサイズが大きくなっていきます。
なので以下の設定をして必要なものだけに絞るのがよいかと思います。
audit_record_cmds:ロギング操作を限定する
audit_record_objs:ロギングしたいオブジェクトを限定する
audit_whitelist_users:ログキングしないユーザを限定する
それでも大きくなり続けるのは、なんとなくいやだったので、ログローテートを設定します。
以下のようにしてみました。
とりあえず毎日ローテートして30日分残すことにしてみました。
とりあえず毎日ローテートして30日分残すことにしてみました。
-----------------------------------
/var/lib/mysql/mysql-audit.json {
daily
rotate 30
missingok
compress
delaycompress
sharedscripts
postrotate
if test -x /usr/bin/mysqladmin && \
/usr/bin/mysqladmin ping &>/dev/null
then
/usr/bin/mysql --defaults-extra-file=/root/.my.cnf -e "set global audit_json_file_flush=ON"
fi
endscript
}
-----------------------------------
上記で利用する.my.cnfも作成します。
vi /root/.my.cnf
-----------------------------------
[mysql]
password = xxxxxxxx
user = root
-----------------------------------
chmod 600 /root/.my.cnf
ログローテートの確認です。2回目のlsでログが増えていることを確認します。
ls -l /var/lib/mysql/mysql-audit.json*
logrotate -f /etc/logrotate.d/mysql-audit-log-rotate
ls -l /var/lib/mysql/mysql-audit.json*
監査ログはこんな感じで残せるようにできたけど、監査ログを確認して異常を検知する方法がよくわからないので、監査ログを活用する方法をちゃんと理解したいところです。
2014-07-09
dockerでcentosの日本語環境コンテナを作ってみる
Dockerをいろいろいじっていたら、なんかiconvの変換がうまくいかないというエラーに出くわしました。
たしかに
locale -a
とすると
となんか少ないです。
そして
iconv -l
としても
とこちらも少ないです。
でなんか初期状態のcentosのコンテナは日本語関連の設定がされていないような感じなので、日本語環境のコンテナを作ってみました。
Dockerfileは以下のような感じです。
この設定のどこまでが本当に必要で足りないものが本当にないのかがいまいちわかりませんが、locale -aの結果とiconv -lの結果が普通な感じはなりました。
たしかに
locale -a
とすると
C POSIX
となんか少ないです。
そして
iconv -l
としても
10646-1:1993, 10646-1:1993/UCS4, ANSI_X3.4-1968, ANSI_X3.4-1986, ANSI_X3.4, ASCII, CP367, CSASCII, CSUCS4, IBM367, ISO-10646, ISO-10646/UCS2, ISO-10646/UCS4, ISO-10646/UTF-8, ISO-10646/UTF8, ISO-IR-6, ISO-IR-193, ISO646-US, ISO_646.IRV:1991, OSF00010020, OSF00010100, OSF00010101, OSF00010102, OSF00010104, OSF00010105, OSF00010106, OSF05010001, UCS-2, UCS-2BE, UCS-2LE, UCS-4, UCS-4BE, UCS-4LE, UCS2, UCS4, UNICODEBIG, UNICODELITTLE, US-ASCII, US, UTF-8, UTF8, WCHAR_T
とこちらも少ないです。
でなんか初期状態のcentosのコンテナは日本語関連の設定がされていないような感じなので、日本語環境のコンテナを作ってみました。
Dockerfileは以下のような感じです。
この設定のどこまでが本当に必要で足りないものが本当にないのかがいまいちわかりませんが、locale -aの結果とiconv -lの結果が普通な感じはなりました。
2014-07-04
dockerでsshを利用する
dockerのCentOSの初期イメージは、ものすごくシンプルな内容で最低限のものしか入っていないようです。
まずはsshを利用できるようにしてみました。
とりあえずパスワードでお手軽に入れるものを試してみました。
用意したDockerfileは以下のような感じです。
これを用意したら、まずはイメージを作成します。
docker build -t centos/sshd .
コンテナを起動します。
docker run -d -P --name test_sshd centos/sshd
ssh用に割り当てられたポートを確認します。
docker port test_sshd 22
上記で49153が割り当てられていたとしてsshで入ってみます。
ssh tomato@localhost -p 49153
無事に接続できました。
コンテナが不要になったら以下で停止します。
docker stop test_sshd
まずはsshを利用できるようにしてみました。
とりあえずパスワードでお手軽に入れるものを試してみました。
用意したDockerfileは以下のような感じです。
これを用意したら、まずはイメージを作成します。
docker build -t centos/sshd .
コンテナを起動します。
docker run -d -P --name test_sshd centos/sshd
ssh用に割り当てられたポートを確認します。
docker port test_sshd 22
上記で49153が割り当てられていたとしてsshで入ってみます。
ssh tomato@localhost -p 49153
無事に接続できました。
コンテナが不要になったら以下で停止します。
docker stop test_sshd
2014-07-02
DockerをCentOSにインストールしてみた
最近、Dockerという仮想環境構築ツールといえばよいのか、どうかの話題を良く見るのでCentOS(64bit版)にインストールしてみました。
CentOSのバージョンが6.5以上であることを確認しておきます。
cat /etc/redhat-release
CentOS release 6.5 (Final)
でインストールはEPELを利用してインストールします。
sudo yum -y install http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
sudo yum -y install docker-io
設定変更をしておきます。
sudo vi /etc/sysconfig/docker
以下のように変更します。
-------------------
other_args="--exec-driver=lxc --selinux-enabled"
-------------------
dockerの起動は以下のような感じで起動時に自動起動するようにもしておきます。
sudo service docker start
sudo chkconfig docker on
root以外のユーザでdockerを動かしたい場合は、そのユーザをdockerグループに入れます。
以下ではユーザtomatoでdockerを動かすようにする例です。
sudo gpasswd -a tomato docker
とにかく動くことを試すら以下のような感じで。
docker run centos /bin/echo "Hello World"
シェルを利用してみるなら以下のような感じで。
docker run -i -t centos /bin/bash
以下が参考になりました。
http://momijiame.tumblr.com/post/70679588212/centos-6-5-docker
ちょっと、いじってみようと思っています。
CentOSのバージョンが6.5以上であることを確認しておきます。
cat /etc/redhat-release
CentOS release 6.5 (Final)
でインストールはEPELを利用してインストールします。
sudo yum -y install http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
sudo yum -y install docker-io
設定変更をしておきます。
sudo vi /etc/sysconfig/docker
以下のように変更します。
-------------------
other_args="--exec-driver=lxc --selinux-enabled"
-------------------
dockerの起動は以下のような感じで起動時に自動起動するようにもしておきます。
sudo service docker start
sudo chkconfig docker on
root以外のユーザでdockerを動かしたい場合は、そのユーザをdockerグループに入れます。
以下ではユーザtomatoでdockerを動かすようにする例です。
sudo gpasswd -a tomato docker
とにかく動くことを試すら以下のような感じで。
docker run centos /bin/echo "Hello World"
シェルを利用してみるなら以下のような感じで。
docker run -i -t centos /bin/bash
以下が参考になりました。
http://momijiame.tumblr.com/post/70679588212/centos-6-5-docker
ちょっと、いじってみようと思っています。
2014-06-05
Raspberry Piにつないだカメラの画像をfluentdに送ってみる
Raspberry Piにつないだカメラで撮影した静止画のデータを別のマシンのfluentdに送って、保存してもらうことを試して見ました。
Raspberry Piでカメラ画像を処理するのにはOpenCVを使ってみます。
Raspberry PiでOpenCVを使えるようにする方法は、以下を参照してください。
Raspberry PiでOpenCVをrubyで使ってみた
そして、画像でデータを受け取るfluentdの方の設定については以下を参照してください。
fluentdに画像データを送ってみる
ここでは、Raspberry Piでカメラデータを取得して、fluentdにデータを送る部分を紹介します。
Raspberry Piでfluentdにデータを送れるようにするためにfluent-loggerをインストールします。
sudo gem install fluent-logger
カメラ画像をfluentdに送るプログラムは以下のような感じです。
vi send_image.rb
これで
ruby send_image.rb
とすれば画像データをfluentdに送って、fluentd側では指定したディレクトリに画像を溜め込んでいきます。
そして、ため込んだ静止画データを利用して動画を作ってみたいと思ったわけです。
タイムラプスとかいうやつです。
ここからはRaspberry Pi側ではなく、fluentdが動いている側での作業になります。
静止画を動画に変換するためにffmpegを利用してみます。
なので、まずはインストールです。
yum --enablerepo=rpmforge install ffmpeg
Raspberry Piでカメラ画像を処理するのにはOpenCVを使ってみます。
Raspberry PiでOpenCVを使えるようにする方法は、以下を参照してください。
Raspberry PiでOpenCVをrubyで使ってみた
そして、画像でデータを受け取るfluentdの方の設定については以下を参照してください。
fluentdに画像データを送ってみる
ここでは、Raspberry Piでカメラデータを取得して、fluentdにデータを送る部分を紹介します。
Raspberry Piでfluentdにデータを送れるようにするためにfluent-loggerをインストールします。
sudo gem install fluent-logger
カメラ画像をfluentdに送るプログラムは以下のような感じです。
vi send_image.rb
require 'opencv'
require 'fluent-logger'
require 'base64'
log = Fluent::Logger::FluentLogger.new(nil, :host=>'fluentdが起動しているホスト', :port=>24224)
cap = OpenCV::CvCapture.open
loop do
#撮影間隔を以下のsleepで調整
sleep 1
img = cap.query
#おくる画像のサイズを指定する場合は、以下のコメントをとる
#img = img.resize OpenCV::CvSize.new 640, 360
mat = img.to_CvMat
data = Base64.encode64(mat.encode('.jpg').pack('C*'))
unless log.post("exec_test.image", {"sender"=>"raspberry pi","image_data"=>data})
p log.last_error # You can get last error object via last_error method
end
end
これで
ruby send_image.rb
とすれば画像データをfluentdに送って、fluentd側では指定したディレクトリに画像を溜め込んでいきます。
そして、ため込んだ静止画データを利用して動画を作ってみたいと思ったわけです。
タイムラプスとかいうやつです。
ここからはRaspberry Pi側ではなく、fluentdが動いている側での作業になります。
静止画を動画に変換するためにffmpegを利用してみます。
なので、まずはインストールです。
yum --enablerepo=rpmforge install ffmpeg
ffmpegで静止画を動画に変換するには、ファイルに連番がついていないといけない模様です。
今回は、データを受け取った時間でファイル名が決まるようにしていたので、そのままでは使えません。
なので以下でファイル名を連番に変換します。
c=1 ; for i in *.jpg ; do ln $i img`printf %06d $c`.JPG ; c=$((c+1)) ; done
ファイル名を連番にできたら、以下を実行して動画に変換します。
ffmpeg -r 15 -i img%06d.JPG out.avi
ネットワークさえつながればRaspberry Piのディスク容量を気にすることなく、いっぱい撮影をすることができるようになります。
データの送る方法としてfluentdを利用するのが最適なのか?という疑問はありますけどね。
2014-06-04
fluentdに画像データを送ってみる
fluentdの使い方として適切でないような気がするのですが、画像データをfluentdに送って処理してもらうことを試しました。
ちなみにfluentdのインストール方法は、以下を参照してください。
centosにfluentdをインストールしてrubyでデータを投げてみた
imageデータを受け取って、指定したフォルダに保存してくれるpluginもある気配です。
https://github.com/bash0C7/fluent-plugin-imagefile
でも今回はデータを受け取ったら、プログラムを起動させて、そのプログラムに処理させる設定をしてみようと思います。
まずは試しに簡単なプログラムを起動させてみます。
起動させるプログラムやデータを保存する場所を準備します。
mkdir -p /var/td-agent/bin
mkdir -p /var/td-agent/tmp
mkdir -p /var/td-agent/data/test
fluentdから起動されるプログラムを作ります。
fluentdはプログラムを呼び出す際に、受け取ったデータをファイルにしてプログラムに渡すようです。
vi /var/td-agent/bin/out_test.rb
所有者情報を変更しておきます。
chown -R td-agent:td-agent /var/td-agent
fluetndには、以下のような設定を追加します。
vi /etc/td-agent/td-agent.conf
---------------------------
<match exec_test.**>
type exec
command /usr/local/bin/ruby /var/td-agent/bin/out_test.rb
time_key got_at
format json
flush_interval 5s
buffer_path /var/td-agent/tmp/buf
</match>
---------------------------
プログラムを実行させるにはtypeをexecにします。
実行させるプログラムはcommandで指定して、データを受け渡す際に受け取った時間をtime_kleyで指定したkeyに設定することができるようです。
そして、受け渡すファイルの形式をformatで選択します。jsonを選択した場合は、1行が一つのjsonデータになるようで、一つのファイルが一つのjsonになるわけではないようです。
flush_intervalで実行するプログラムの間隔を指定することになり、buffer_pathにプログラムに受け渡すファイルが一時的に格納されるようです。
設定後に設定を反映させます。
/etc/init.d/td-agent reload
テストで以下を実行してみます。
curl -X POST -d 'json={"json":"message"}' http://localhost:8888/exec_test.test
するとjsonデータが
/var/td-agent/data/test/hoge.txt
に保存されていることを確認できます。
ここで画像を受け取って保存できるようにプログラムを修正してみます。
vi /var/td-agent/bin/out_test.rb
画像データを投げるプログラムは以下のような感じです。
vi image_send.rb
aaa.jpgを用意してimage_send.rbを実行すると
/var/td-agent/data/test/xxxxxxx.jp
としてaaa.jpgと同じものが保存されます。
ちなみにfluentdのインストール方法は、以下を参照してください。
centosにfluentdをインストールしてrubyでデータを投げてみた
imageデータを受け取って、指定したフォルダに保存してくれるpluginもある気配です。
https://github.com/bash0C7/fluent-plugin-imagefile
でも今回はデータを受け取ったら、プログラムを起動させて、そのプログラムに処理させる設定をしてみようと思います。
まずは試しに簡単なプログラムを起動させてみます。
起動させるプログラムやデータを保存する場所を準備します。
mkdir -p /var/td-agent/bin
mkdir -p /var/td-agent/tmp
mkdir -p /var/td-agent/data/test
fluentdから起動されるプログラムを作ります。
fluentdはプログラムを呼び出す際に、受け取ったデータをファイルにしてプログラムに渡すようです。
vi /var/td-agent/bin/out_test.rb
open("/var/td-agent/data/test/hoge.txt", "w") {|f|
f.write ARGV
f.write File.new(ARGV[0]).read
}
所有者情報を変更しておきます。
chown -R td-agent:td-agent /var/td-agent
fluetndには、以下のような設定を追加します。
vi /etc/td-agent/td-agent.conf
---------------------------
<match exec_test.**>
type exec
command /usr/local/bin/ruby /var/td-agent/bin/out_test.rb
time_key got_at
format json
flush_interval 5s
buffer_path /var/td-agent/tmp/buf
</match>
---------------------------
プログラムを実行させるにはtypeをexecにします。
実行させるプログラムはcommandで指定して、データを受け渡す際に受け取った時間をtime_kleyで指定したkeyに設定することができるようです。
そして、受け渡すファイルの形式をformatで選択します。jsonを選択した場合は、1行が一つのjsonデータになるようで、一つのファイルが一つのjsonになるわけではないようです。
flush_intervalで実行するプログラムの間隔を指定することになり、buffer_pathにプログラムに受け渡すファイルが一時的に格納されるようです。
設定後に設定を反映させます。
/etc/init.d/td-agent reload
テストで以下を実行してみます。
curl -X POST -d 'json={"json":"message"}' http://localhost:8888/exec_test.test
するとjsonデータが
/var/td-agent/data/test/hoge.txt
に保存されていることを確認できます。
ここで画像を受け取って保存できるようにプログラムを修正してみます。
vi /var/td-agent/bin/out_test.rb
require 'json'
require 'base64'
inf = open(ARGV[0])
inf.each do |l|
data = JSON.parse l
file_name=data['got_at'] + ".jpg"
File.open("/var/td-agent/data/test/#{file_name}", 'wb') {|f|
f.write Base64.decode64(data["image_data"])
}
end
画像データを投げるプログラムは以下のような感じです。
vi image_send.rb
require 'fluent-logger'
require 'base64'
filename='aaa.jpg'
image=File.new(filename).read
image_data=Base64.encode64(image)
log = Fluent::Logger::FluentLogger.new(nil, :host=>'localhost', :port=>24224)
unless log.post("exec_test.image", {"file_name"=>filename,"image_data"=>image_data})
p log.last_error # You can get last error object via last_error method
end
aaa.jpgを用意してimage_send.rbを実行すると
/var/td-agent/data/test/xxxxxxx.jp
としてaaa.jpgと同じものが保存されます。
2014-06-03
centosにfluentdをインストールしてrubyでデータを投げてみた
ログをいい感じにいろいろ何かをしてくれる
fluentd
の話題をよく聞くような気がしたのでcentosにインストールしてみました。
まずは準備です。
vi /etc/security/limits.conf
に以下を追加します。
---------------
root soft nofile 65536
root hard nofile 65536
* soft nofile 65536
* hard nofile 65536
---------------
追加したら
reboot
再起動後
ulimit -n
として
65535
となることを確認します。
そして
vi /etc/sysctl.conf
以下を追加します。
---------------
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 10240 65535
---------------
そして設定を反映させます。
sysctl -w
fluentdをインストールします。
インストールの仕方にはいくつかあるのですが、以下の手段でインストールします。
curl -L http://toolbelt.treasuredata.com/sh/install-redhat.sh | sh
これでfluentdがtd-agentという名前でインストールされます。
fluentdの起動は以下のとおりです。
/etc/init.d/td-agent start
設定ファイルは以下になります。
/etc/td-agent/td-agent.conf
インストールされて正しく動くことを確認です。
curl -X POST -d 'json={"json":"message"}' http://localhost:8888/debug.test
以下を実行して上記のjsonの内容が出力されていることを確認します。
cat /var/log/td-agent/td-agent.log
fluentdがインストールできたので、rubyからデータを投げて見ます。
rubyからデータを投げるためにfluent-loggerを利用してみます。
他にもいくつかgemがありそうな気配ではあります。
まずはインストール
gem install fluent-logger
データを投げるプログラムを作ります。
vi test.rb
ruby test.rb
を実行して、以下に投げたjsonデータが出てきていることを確認します。
cat /var/log/td-agent/td-agent.log
fluentd
の話題をよく聞くような気がしたのでcentosにインストールしてみました。
まずは準備です。
vi /etc/security/limits.conf
に以下を追加します。
---------------
root soft nofile 65536
root hard nofile 65536
* soft nofile 65536
* hard nofile 65536
---------------
追加したら
reboot
再起動後
ulimit -n
として
65535
となることを確認します。
そして
vi /etc/sysctl.conf
以下を追加します。
---------------
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 10240 65535
---------------
そして設定を反映させます。
sysctl -w
fluentdをインストールします。
インストールの仕方にはいくつかあるのですが、以下の手段でインストールします。
curl -L http://toolbelt.treasuredata.com/sh/install-redhat.sh | sh
これでfluentdがtd-agentという名前でインストールされます。
fluentdの起動は以下のとおりです。
/etc/init.d/td-agent start
設定ファイルは以下になります。
/etc/td-agent/td-agent.conf
インストールされて正しく動くことを確認です。
curl -X POST -d 'json={"json":"message"}' http://localhost:8888/debug.test
以下を実行して上記のjsonの内容が出力されていることを確認します。
cat /var/log/td-agent/td-agent.log
fluentdがインストールできたので、rubyからデータを投げて見ます。
rubyからデータを投げるためにfluent-loggerを利用してみます。
他にもいくつかgemがありそうな気配ではあります。
まずはインストール
gem install fluent-logger
データを投げるプログラムを作ります。
vi test.rb
require 'fluent-logger'
log = Fluent::Logger::FluentLogger.new(nil, :host=>'localhost', :port=>24224)
unless log.post("debug.aaaa", {"agent"=>"foo","bbbb"=>"cccc"})
p log.last_error # You can get last error object via last_error method
end
ruby test.rb
を実行して、以下に投げたjsonデータが出てきていることを確認します。
cat /var/log/td-agent/td-agent.log
2014-05-04
Raspberry PiでOpenCVをrubyで使ってみた
Rapberry PiでUSBカメラを使う際にmotionを使うのを試してみたのですが、さらに画像からいろいろ認識するとかも試してみたいと思ってみました。
ちなみにmotionを利用する方法に関しては、以下をご覧ください。
Raspberry Piに大人の科学マガジンUSB特撮カメラをつないでみた
Raspberry PiにつないだUSBカメラの画像をブラウザから確認するものをrubyで作ってみた
画像から顔やらなんやらを認識するにはOpenCVを利用するわけです。
OpenCVは
sudo apt-get install libopencv-dev
でもインストールできるのですが、インストールされるバージョンは2.3系のものが入るようです。
OpenCVをrubyから使おうと思ったりする場合は、ruby-opencvというものを利用するのですが、こちらは2.4系を必要とします。
今回はrubyで利用するので、apt-getを利用せずにインストールします。
OpenCVは、以下のようにインストールします。
コンパイルに必要になるものを準備します。以下がすべて本当に必要なのかはよくわかりません。
sudo apt-get install build-essential libboost1.46-all-dev libqt4-dev libgtk2.0-dev pkg-config opencl-headers libjpeg-dev libopenjpeg-dev libjasper-dev libjasper-runtime libpng12-dev libpng++-dev libpng3 libpnglite-dev libtiff-dev libtiff-tools pngtools zlib1g-dev zlib1g-dbg v4l2ucp python autoconf libeigen2-dev cmake openexr gstreamer-plugins-* freeglut3-dev libglui-dev libavc1394-dev libdc1394-22-dev libdc1394-utils libxine-dev libxvidcore-dev libva-dev libssl-dev libv4l-dev libvo-aacenc-dev libvo-amrwbenc-dev libvorbis-dev libvpx-dev
ソースを取得して展開します。今回は2.4.9を持ってきました。
wget http://downloads.sourceforge.net/project/opencvlibrary/opencv-unix/2.4.9/opencv-2.4.9.zip
unzip opencv-2.4.9.zip
cd opencv-2.4.9
コンパイルします。cmakeで指定したパラメータの意味は正直よく分かりません。そしてmakeはすごく時間がかかります。
mkdir build
cd build
cmake -DBUILD_DOCS=ON -DBUILD_EXAMPLES=ON -DCMAKE_BUILD_TYPE=RELEASE -DWITH_TBB=OFF -DWITH_GTK=ON -DWITH_OPENGL=ON -DWITH_QT=OFF -DINSTALL_C_EXAMPLES=ON -DWITH_OPENCL=OFF -DWITH_CUDA=OFF -DWITH_OPENNI=OFF -DWITH_UNICAP=ON -DWITH_V4L=ON -DWITH_XINE=ON ..
make
インストールします。
sudo make install
そして、ruby-opencvをインストールします。
sudo gem install ruby-opencv
ここまでのものが正しくインストールされたことを確認します。
以下のソースを実行してoutput.jpgにカメラ画像が保存されていればOKです。
カメラ画像から顔認識して顔の部分を四角で囲ってみます。カメラ画像はwebsocketを利用してブラウザで確認できるようにします。
rubyでwebsocketを利用するためem-websocketをインストールします。
sudo gem install em-websocket
で以下のソースを実行します。
実行したらwebsocketで画像を受け取るクライアントを用意します。とりあえず以下のhtmlを用意してブラウザで見れるようにします。
サーバ側においてもいいし、手元のPCにファイルとして用意してもよいのでブラウザから開くと顔認識した画像が見れるはずです。
ブラウザはchromeでしか試していないです。
ちなみに処理はすごく遅いです。体感的には2秒ぐらいで1回画面が切り替わる感じです。
以下がすごく参考になりました。
http://naohiro7.hatenablog.com/entry/2013/04/22/142243
http://shokai.org/blog/archives/8627
ちなみにmotionを利用する方法に関しては、以下をご覧ください。
Raspberry Piに大人の科学マガジンUSB特撮カメラをつないでみた
Raspberry PiにつないだUSBカメラの画像をブラウザから確認するものをrubyで作ってみた
画像から顔やらなんやらを認識するにはOpenCVを利用するわけです。
OpenCVは
sudo apt-get install libopencv-dev
でもインストールできるのですが、インストールされるバージョンは2.3系のものが入るようです。
OpenCVをrubyから使おうと思ったりする場合は、ruby-opencvというものを利用するのですが、こちらは2.4系を必要とします。
今回はrubyで利用するので、apt-getを利用せずにインストールします。
OpenCVは、以下のようにインストールします。
コンパイルに必要になるものを準備します。以下がすべて本当に必要なのかはよくわかりません。
sudo apt-get install build-essential libboost1.46-all-dev libqt4-dev libgtk2.0-dev pkg-config opencl-headers libjpeg-dev libopenjpeg-dev libjasper-dev libjasper-runtime libpng12-dev libpng++-dev libpng3 libpnglite-dev libtiff-dev libtiff-tools pngtools zlib1g-dev zlib1g-dbg v4l2ucp python autoconf libeigen2-dev cmake openexr gstreamer-plugins-* freeglut3-dev libglui-dev libavc1394-dev libdc1394-22-dev libdc1394-utils libxine-dev libxvidcore-dev libva-dev libssl-dev libv4l-dev libvo-aacenc-dev libvo-amrwbenc-dev libvorbis-dev libvpx-dev
ソースを取得して展開します。今回は2.4.9を持ってきました。
wget http://downloads.sourceforge.net/project/opencvlibrary/opencv-unix/2.4.9/opencv-2.4.9.zip
unzip opencv-2.4.9.zip
cd opencv-2.4.9
コンパイルします。cmakeで指定したパラメータの意味は正直よく分かりません。そしてmakeはすごく時間がかかります。
mkdir build
cd build
cmake -DBUILD_DOCS=ON -DBUILD_EXAMPLES=ON -DCMAKE_BUILD_TYPE=RELEASE -DWITH_TBB=OFF -DWITH_GTK=ON -DWITH_OPENGL=ON -DWITH_QT=OFF -DINSTALL_C_EXAMPLES=ON -DWITH_OPENCL=OFF -DWITH_CUDA=OFF -DWITH_OPENNI=OFF -DWITH_UNICAP=ON -DWITH_V4L=ON -DWITH_XINE=ON ..
make
インストールします。
sudo make install
そして、ruby-opencvをインストールします。
sudo gem install ruby-opencv
ここまでのものが正しくインストールされたことを確認します。
以下のソースを実行してoutput.jpgにカメラ画像が保存されていればOKです。
カメラ画像から顔認識して顔の部分を四角で囲ってみます。カメラ画像はwebsocketを利用してブラウザで確認できるようにします。
rubyでwebsocketを利用するためem-websocketをインストールします。
sudo gem install em-websocket
で以下のソースを実行します。
実行したらwebsocketで画像を受け取るクライアントを用意します。とりあえず以下のhtmlを用意してブラウザで見れるようにします。
サーバ側においてもいいし、手元のPCにファイルとして用意してもよいのでブラウザから開くと顔認識した画像が見れるはずです。
ブラウザはchromeでしか試していないです。
ちなみに処理はすごく遅いです。体感的には2秒ぐらいで1回画面が切り替わる感じです。
以下がすごく参考になりました。
http://naohiro7.hatenablog.com/entry/2013/04/22/142243
http://shokai.org/blog/archives/8627
2014-03-09
rubyを2.0にあげたらrailsのfixturesで読み込む値が変わってた
Rails3.2とruby1.9.3で作ったもののrubyを2.0系にあげてみたところ、rake specが失敗するようになってしまいました。
失敗するのは、日時関連の処理だったので、timezone関係のものがおかしいのかなぁと思ったのですが、fixturesでテストデータを読み込んだ動作が1.9と2.0で違っていました。
具体的には、fixturesで
さらに調べたらYAM.loadで読み込んだ時点で違っていました。
rails cでコンソールを立ち上げてそれぞれのバージョンで比較した結果は、以下のとおりです。
1.9.3
2.0.0
YAML.loadが定義されているところを調査してみました。
1.9.3
2.0.0
なんかloadが定義されている場所が違いました。
調べてみると以下のようなことでした。
http://qiita.com/udzura/items/ec4c5b83db94363c9cdf
Syckは古いもののようで、2.0.0からはなくなったようです。
1.9.3でもPsychがデフォルトのようなのですが、railsがSyckがあればそちらを優先している気配です。
今回の例は、あくまでもrails cでコンソールを利用している場合で、railsを利用しないでpryで実行すると1.9.3でも2.0.0でも動きはPsychの動きをしていました。
ちなみに以下のように1.9.3でもPsychを指定すれば2.0.0と同じ動きをします。
で、今回は、"2014-01-25 22:57:09"を日本時間のつもりで書いていたのに、違う解釈をされたのが困ったのでした。
これを解決するには、日付は以下のようにすることで1.9.3でも2.0.0でも同じ動きをするようになります。
[1] pry(main)> a = "aaa: 2014-01-25 22:57:09 +09:00"
失敗するのは、日時関連の処理だったので、timezone関係のものがおかしいのかなぁと思ったのですが、fixturesでテストデータを読み込んだ動作が1.9と2.0で違っていました。
具体的には、fixturesで
aaa: 2014-01-25 22:57:09と書いていたところが、おかしかったようです。
さらに調べたらYAM.loadで読み込んだ時点で違っていました。
rails cでコンソールを立ち上げてそれぞれのバージョンで比較した結果は、以下のとおりです。
1.9.3
[1] pry(main)> a = "aaa: 2014-01-25 22:57:09"
=> "aaa: 2014-01-25 22:57:09"
[2] pry(main)> YAML.load(a)
=> {"aaa"=>"2014-01-25 22:57:09"}
[3] pry(main)> YAML.load(a)["aaa"].class
=> String
2.0.0
[1] pry(main)> a = "aaa: 2014-01-25 22:57:09"
=> "aaa: 2014-01-25 22:57:09"
[2] pry(main)> YAML.load(a)
=> {"aaa"=>2014-01-26 07:57:09 +0900}
[3] pry(main)> YAML.load(a)["aaa"].class
=> Time
YAML.loadが定義されているところを調査してみました。
1.9.3
[1] pry(main)> YAML.method(:load) => #<Method: Syck.load>
2.0.0
[1] pry(main)> YAML.method(:load) => #<Method: Psych.load>
なんかloadが定義されている場所が違いました。
調べてみると以下のようなことでした。
http://qiita.com/udzura/items/ec4c5b83db94363c9cdf
Syckは古いもののようで、2.0.0からはなくなったようです。
1.9.3でもPsychがデフォルトのようなのですが、railsがSyckがあればそちらを優先している気配です。
今回の例は、あくまでもrails cでコンソールを利用している場合で、railsを利用しないでpryで実行すると1.9.3でも2.0.0でも動きはPsychの動きをしていました。
ちなみに以下のように1.9.3でもPsychを指定すれば2.0.0と同じ動きをします。
[1] pry(main)> YAML::ENGINE.yamler = 'psych'
=> "psych"
[2] pry(main)> a = "aaa: 2014-01-25 22:57:09"
=> "aaa: 2014-01-25 22:57:09"
[3] pry(main)> YAML.load(a)
=> {"aaa"=>2014-01-26 07:57:09 +0900}
[4] pry(main)> YAML.load(a)["aaa"].class
=> Time
で、今回は、"2014-01-25 22:57:09"を日本時間のつもりで書いていたのに、違う解釈をされたのが困ったのでした。
これを解決するには、日付は以下のようにすることで1.9.3でも2.0.0でも同じ動きをするようになります。
aaa: 2014-01-25 22:57:09 +09:00
[1] pry(main)> a = "aaa: 2014-01-25 22:57:09 +09:00"
=> "aaa: 2014-01-25 22:57:09 +09:00"
[2] pry(main)> YAML.load(a)
=> {"aaa"=>2014-01-25 22:57:09 +0900}
[3] pry(main)> YAML.load(a)["aaa"].class
=> Time
2014-02-21
LinuxからSQL Serverに接続して時間がかかるクエリーを実行するとセッションが切れてしまうときのこと
SQL Serverに接続するLinux上のRailsアプリケーションで、時間がかかるクエリーを実行したら
だいたい40秒後ぐらいに
のようなエラー出たのです。
ちなみに接続先は、SQL Server 2005で、接続にはfreetds 0.91を利用しています。
railsからはtiny_tdsとactiverecord_sqlserver_adapterを利用しています。
同じクエリーをwindows上ののSQLServer Management Studioから実行すれば、時間はかかるけどきちんと結果がかえってくるので、タイムアウトの設定かなぁと思って、
database.ymlにtimeoutを記述してみたものの、タイムアウトを短くする分には効くのですが、長く設定してもダメでした。
Railsの方からどうにかすれば何とかなるかなぁと思っていたのですが、
Railsを使わずにlinux上でSQL serverに接続するtsqlを使ってみたら、こちらでもエラーが出るのがわかったので、どうもRailsは関係なさそうです。
こんな感じで接続して
tsql -S server -U uuu -P ppp
クエリーを実行したら、やはり40秒後ぐらい以下のエラーが出てクエリーが失敗したのです。
freetdsは、接続情報をダンプできるので、ダンプさせたところ以下のように出ました。
ダンプ内容を見てもさっぱりわからなかったので、tcpdumpを以下のような感じで実行してみました。
tcpdump host server and port 1433 -Xn
すると、SQL Server側からクエリー実行30秒後ぐらいから1秒おきに10回ぐらいパケットがきて、最後にサーバー側から切断要求が来ていることがわかりました。
tsqlで出たエラーメッセージの内容どおりということでした。
でSQL Serverから出ているのはなんだろう?と思って調べていたらkeep aliveでした。
SQL Serverのkeep aliveを調べていたら以下がありました。
http://msdn.microsoft.com/ja-jp/library/ms190771.aspx
Microsoft SQL Server 構成マネージャでkeep aliveの設定を見ると確かに30秒と1秒間隔が設定されていました。
なので、こちらの値を変えれば住むのですが、値を変更したらSQL Serverのサービスの再起動が必要になるようで、ちょっと再起動がすぐにはできないので、この方法は見送ります。
keep aliveに対して、linux側が返答をしないのがいけないので、返答するようにする方法を調べていたら、以下のページを見つけました。
http://permalink.gmane.org/gmane.comp.db.tds.freetds/13296
どうもlinux側のkeep alive設定をどうのこうのとあったので、ためしにSQL Server側のkeep alive設定とあわせるように以下のように設定してみました。
sysctl -w net.ipv4.tcp_keepalive_time=30
sysctl -w net.ipv4.tcp_keepalive_intvl=1
すると切断されないようになりました。
tcpdumpで見てもきちんとkeep aliveに対して返答をかけていました。
ただデフォルト値が
net.ipv4.tcp_keepalive_time=7200
net.ipv4.tcp_keepalive_intvl=75
なので今回の設定は小さくしすぎな気がします。
SQL Serverだけ見ればよいのですが、他への影響が心配なので、この方法も見送ります。
SQL Serverだけに対してkeep aliveの値を変えたいなぁと思ってたどりついたのが、freetdsのソースを変更することでした。
以下にページでsocketにkeep aliveを設定する方法が書いてあったので、これを真似します。
http://d.hatena.ne.jp/iww/20081030/setsockopt
socketのopen処理は
src/tds/net.c
で書かれているのを見つけました。SO_KEEPALIVEだけはifdefでくくられて記載されていたのでifdefを取って以下のように書き換えてコンパイルしました。
これでkeep aliveに対してちゃんと返答を返すようになりました。
といろいろ調べましたが、実際に取った対応は、遅かったクエリーをチューニングして速くする対応を行いました。
遅いSQLに対してはチューニングがするのが正しい対応だと思うのですが、
railsのmigraionをsql serverに対して実行するときに、大きな既存テーブルに対して何かしらの変更を加えるとやはり問題が起こることがあるのがわかったので、そのうちfreetdsの方の変更もしないとダメかなぁと思っています。
だいたい40秒後ぐらいに
CONNECTION RETRY: ActiveRecord::ConnectionAdapters::SQLServerAdapter retry #0. TinyTds::Error: DBPROCESS is dead or not enabled: EXEC sp_executesql N'*******; SELECT @@ROWCOUNT AS AffectedRows'
のようなエラー出たのです。
ちなみに接続先は、SQL Server 2005で、接続にはfreetds 0.91を利用しています。
railsからはtiny_tdsとactiverecord_sqlserver_adapterを利用しています。
同じクエリーをwindows上ののSQLServer Management Studioから実行すれば、時間はかかるけどきちんと結果がかえってくるので、タイムアウトの設定かなぁと思って、
database.ymlにtimeoutを記述してみたものの、タイムアウトを短くする分には効くのですが、長く設定してもダメでした。
Railsの方からどうにかすれば何とかなるかなぁと思っていたのですが、
Railsを使わずにlinux上でSQL serverに接続するtsqlを使ってみたら、こちらでもエラーが出るのがわかったので、どうもRailsは関係なさそうです。
こんな感じで接続して
tsql -S server -U uuu -P ppp
クエリーを実行したら、やはり40秒後ぐらい以下のエラーが出てクエリーが失敗したのです。
Error 20004 (severity 9):
Read from the server failed
OS error 104, "接続が相手からリセットされました"
freetdsは、接続情報をダンプできるので、ダンプさせたところ以下のように出ました。
(util.c:156):Changed query state from READING to DEAD (util.c:331):tdserror(0x1585150, 0x15853b0, 20004, 104) (util.c:361):tdserror: client library returned TDS_INT_CANCEL(2) (util.c:384):tdserror: returning TDS_INT_CANCEL(2) (token.c:555):processing result tokens. marker is 0() (token.c:122):tds_process_default_tokens() marker is 0() (token.c:125):leaving tds_process_default_tokens() connection dead
ダンプ内容を見てもさっぱりわからなかったので、tcpdumpを以下のような感じで実行してみました。
tcpdump host server and port 1433 -Xn
すると、SQL Server側からクエリー実行30秒後ぐらいから1秒おきに10回ぐらいパケットがきて、最後にサーバー側から切断要求が来ていることがわかりました。
tsqlで出たエラーメッセージの内容どおりということでした。
でSQL Serverから出ているのはなんだろう?と思って調べていたらkeep aliveでした。
SQL Serverのkeep aliveを調べていたら以下がありました。
http://msdn.microsoft.com/ja-jp/library/ms190771.aspx
Microsoft SQL Server 構成マネージャでkeep aliveの設定を見ると確かに30秒と1秒間隔が設定されていました。
なので、こちらの値を変えれば住むのですが、値を変更したらSQL Serverのサービスの再起動が必要になるようで、ちょっと再起動がすぐにはできないので、この方法は見送ります。
keep aliveに対して、linux側が返答をしないのがいけないので、返答するようにする方法を調べていたら、以下のページを見つけました。
http://permalink.gmane.org/gmane.comp.db.tds.freetds/13296
どうもlinux側のkeep alive設定をどうのこうのとあったので、ためしにSQL Server側のkeep alive設定とあわせるように以下のように設定してみました。
sysctl -w net.ipv4.tcp_keepalive_time=30
sysctl -w net.ipv4.tcp_keepalive_intvl=1
すると切断されないようになりました。
tcpdumpで見てもきちんとkeep aliveに対して返答をかけていました。
ただデフォルト値が
net.ipv4.tcp_keepalive_time=7200
net.ipv4.tcp_keepalive_intvl=75
なので今回の設定は小さくしすぎな気がします。
SQL Serverだけ見ればよいのですが、他への影響が心配なので、この方法も見送ります。
SQL Serverだけに対してkeep aliveの値を変えたいなぁと思ってたどりついたのが、freetdsのソースを変更することでした。
以下にページでsocketにkeep aliveを設定する方法が書いてあったので、これを真似します。
http://d.hatena.ne.jp/iww/20081030/setsockopt
socketのopen処理は
src/tds/net.c
で書かれているのを見つけました。SO_KEEPALIVEだけはifdefでくくられて記載されていたのでifdefを取って以下のように書き換えてコンパイルしました。
len = 1; setsockopt(tds->s, SOL_SOCKET, SO_KEEPALIVE, (const void *) &len, sizeof(len)); len = 30; setsockopt(tds->s, IPPROTO_TCP, TCP_KEEPIDLE, (const void *) &len, sizeof(len)); len = 1; setsockopt(tds->s, IPPROTO_TCP, TCP_KEEPINTVL, (const void *) &len, sizeof(len)); len = 10; setsockopt(tds->s, IPPROTO_TCP, TCP_KEEPCNT, (const void *) &len, sizeof(len));
これでkeep aliveに対してちゃんと返答を返すようになりました。
といろいろ調べましたが、実際に取った対応は、遅かったクエリーをチューニングして速くする対応を行いました。
遅いSQLに対してはチューニングがするのが正しい対応だと思うのですが、
railsのmigraionをsql serverに対して実行するときに、大きな既存テーブルに対して何かしらの変更を加えるとやはり問題が起こることがあるのがわかったので、そのうちfreetdsの方の変更もしないとダメかなぁと思っています。
2014-02-17
twitter-bootstrap-railsをproduction環境でエラーが出たとき
railsでbootstrapを使うために
twitter-bootstrap-rails
を使ってみました。
developmentでは何の問題もなく使えていたのですが、
productionでは、
ActionView::Template::Error (undefined local variable or method ` bootstrap_flash' for #<#<Class:0x00000004abf460>:0x000000051a9690>):
みたいなエラーが出て使えなかったのです。
調べてみると
helperにbootstrap_flashを追加すればよいみたいな感じなのですが
今回使っている
twitter-bootstrap-rails
のバージョンは2.2.8で
twitter-bootstrap-rails-2.2.8/app/helpers/flash_block_helper.rb
にhelperがちゃんと用意されていました。
これをapp/helperにコピーすれば動くのですが、
それでは、いまいちです。
エラーが出た原因ですが、
Gemfileの書き方がいけませんでした。
最初は、
group :assets do gem "twitter-bootstrap-rails" end
とassetsグループの中に入れていたのですが、これがダメでした。
groupにいれずに普通に
gem "twitter-bootstrap-rails"
と書いておけばOKでした。
やれやれです。
2014-02-12
結ばない靴ひもを調べてみた
最近、靴ひもがめんどくさいのです。
荷物が多い状態で靴を脱ぐことが多いので、靴ひもの靴を買わないことが多くなっていました。
でも最近、結ばなくてもよい靴ひもなるものがイロイロでているようです。
なので調べてみました。
大きくわけると、
①短いゴムっぽいものをいっぱい使う系
②ゴツゴツつきの紐っぽいもの
があるようです。
①短いゴムっぽいものをいっぱい使う系
こちらはカラーバリエーションも豊富で色を組み合わせる楽しみもある感じです。
以下のようにいろいろあるのですが、HICKEISが有名な気配です。
HICKIES(http://www.hickies.jp/)
X-tie(http://x-tie.jp/)
SPINNS Footbeans(http://www.footbeans.com/)
U-LACE(http://u-lace.jp/)
②ゴツゴツつきの紐っぽいもの
こちらもなんとなく実用性が高そうな気配がします。
CATERPYRUNが有名な気配です。
CATERPYRUN(http://caterpyrun.com/)
Xtenex(http://xtenex.jp/)
ちょっとキニナルので、どれか買って最近履いてなかった靴に使ってみようかなぁと悩み中です。
荷物が多い状態で靴を脱ぐことが多いので、靴ひもの靴を買わないことが多くなっていました。
でも最近、結ばなくてもよい靴ひもなるものがイロイロでているようです。
なので調べてみました。
大きくわけると、
①短いゴムっぽいものをいっぱい使う系
②ゴツゴツつきの紐っぽいもの
があるようです。
①短いゴムっぽいものをいっぱい使う系
こちらはカラーバリエーションも豊富で色を組み合わせる楽しみもある感じです。
以下のようにいろいろあるのですが、HICKEISが有名な気配です。
HICKIES(http://www.hickies.jp/)
X-tie(http://x-tie.jp/)
SPINNS Footbeans(http://www.footbeans.com/)
U-LACE(http://u-lace.jp/)
②ゴツゴツつきの紐っぽいもの
こちらもなんとなく実用性が高そうな気配がします。
CATERPYRUNが有名な気配です。
CATERPYRUN(http://caterpyrun.com/)
Xtenex(http://xtenex.jp/)
ちょっとキニナルので、どれか買って最近履いてなかった靴に使ってみようかなぁと悩み中です。
2014-01-29
RailsでSQL Serverを使っているときにエンコードエラーが出たとき
RailsでSQL Serverを使っているときに
incompatible character encodings: ASCII-8BIT and UTF-8 (RuntimeError)
みたいなエラーが出てマジックコメント書いてささっと解決さと思ったのにすでにマジックコメントが書いてあってどういうことだろう・・・と思ったわけです。
こんなエラーが出ていますが、ただ単に利用するテーブルに権限がないだけで、権限を振ればOKだったりすることがあります。
私の場合既存システムのDBのデータをselectしたいなぁと思ったときに、そのテーブルへのselect権を付け忘れていてエラーが出たのでした。
紛らわしいエラーですね。
2014-01-15
Railsのmigrationにchangeとup/downの両方を書いてみると
Railsのmigrationにchangeとup/downの両方を書いてみると
changeの方しか実行しませんでした。
そういうものらしいです。
changeの方しか実行しませんでした。
そういうものらしいです。
2014-01-14
gemを作成したけどrubygemsに登録を行うrake releaseをしないようにガードする
gemを作ったら、gemのディレクトリでrake releaseをするとrubygemsに登録がされます。
(rubygemsにアカウントがなかれば、登録はされません)
とてもお手軽でよいのですが、ローカル用で公開する気がないものをうっかり登録してしまう可能性もなくはないです。
うっかりrake releaseを防止するためにrake releaseで行われる動作を変更しておけば安心です。
手順は以下のとおりです。
gemのディレクトリのRakefileに以下を追加します。
これでうっかりrake releaseを行ってもputsされるだけになります。
本当は、rake release自体を削除したかったのですが、やり方がわかりませんでした・・・
(rubygemsにアカウントがなかれば、登録はされません)
とてもお手軽でよいのですが、ローカル用で公開する気がないものをうっかり登録してしまう可能性もなくはないです。
うっかりrake releaseを防止するためにrake releaseで行われる動作を変更しておけば安心です。
手順は以下のとおりです。
gemのディレクトリのRakefileに以下を追加します。
Bundler::GemHelper.install_tasks
#以下を追加
t = Rake.application.lookup('release')
t.clear
t.instance_variable_set('@full_comment', nil)
desc 'Please keep this for internal use only.'
task :release do
puts "Please keep this for internal use only."
end
これでうっかりrake releaseを行ってもputsされるだけになります。
本当は、rake release自体を削除したかったのですが、やり方がわかりませんでした・・・
2014-01-13
Raspberry Pi上でrubyでOCR
先日、CentOS上でrubyでOCRを試しました。
試した内容は、rubyでOCRをご覧ください。
なので、今度はRaspberry PiでrubyでOCRをして見ます。
CentOSと同じようにtesseract-ocrを利用します。
試した内容は、rubyでOCRをご覧ください。
なので、今度はRaspberry PiでrubyでOCRをして見ます。
CentOSと同じようにtesseract-ocrを利用します。
ということで、まずtesseract-ocrをインストールします。
CentOSより簡単で以下でOKです。
sudo apt-get install libtesseract3 libtesseract-dev tesseract-ocr
sudo apt-get install tesseract-ocr-eng tesseract-ocr-jpn
以下でインストールされたことを確認できます。
tesseract -v
で、お次はrubyで使えるようにするtesseract-ocrをインストールするわけですが、こちらを利用するには、leptonicaが必要になりました。tesseract-ocrを単独で動かす分にはなしでもOKでした。
なのでleptonicaをインストールします。
コンパイルに結構、時間がかかります。
wget http://leptonica.googlecode.com/files/leptonica-1.69.tar.gz
tar xvzf leptonica-1.69.tar.gz
cd leptonica-1.69
./configure
make
sudo make install
ここまで済んだら、gemをインストールします。
gem install tesseract-ocr
これでCentOSで実行した以下のテストコードが実行できるようになりました。
ちなみにleptonicaをインストールしないでtesseract-ocrを利用したら
なんかエラーが起きたよ
/tmp/.ffi-inline-1000/87da260298e169d1e5d4e8952649b2811b81311e.log
を見てね。みたいなことを言われて、logを見ると以下のようにleptonicaのヘッダーがないといわれてしまいました。
g++ -shared -fPIC -o /tmp/.ffi-inline-1000/87da260298e169d1e5d4e8952649b2811b81311e.so /tmp/.ffi-inline-1000/87da260298e169d1e5d4e8952649b2811b81311e.cpp -llept 2>>/tmp/.ffi-inline-1000/87da260298e169d1e5d4e8952649b2811b81311e.log
/tmp/.ffi-inline-1000/87da260298e169d1e5d4e8952649b2811b81311e.cpp:1:34: fatal error: leptonica/allheaders.h: そのようなファイルやディレクトリはありません
compilation terminated.
2014-01-12
xperiaでgoogleカレンダーの同期に失敗するときの対策
xpeiraで複数のgoogleカレンダーを同期させているときに、
googleカレンダー同期が失敗しました
しましたとか言われてしまいました。
カレンダーデータを初期化して再読み込みすればOKみたいなことが紹介されていることが多いのですが、私の場合はダメで、ある特定のカレンダーを同期すると問題になっていました。
その特定のカレンダーの同期をはずせば、問題なく動作していたのです。
さらにgaraxyでは、まったく問題なく同期できていたのです。
ちょっと家族もxperiaを使うようになって、まったく同じ現象だったので、どうも私の端末特有の問題ではなさそうなので、ちゃんと調べてみました。
根本原因かどうかわからないのですが、
カレンダーに繰り返し設定がされているイベントがあって、その繰り返しイベントで特定の日を除外設定をしているものがあるとダメなことがわかりました。
なので、繰り返し設定だけで除外日がまったくないようにイベントを変更したら問題なく動くようになりました。
xperiaの問題なのか、androidのバージョンの問題なのかはわからないのですけどね。
googleカレンダー同期が失敗しました
しましたとか言われてしまいました。
カレンダーデータを初期化して再読み込みすればOKみたいなことが紹介されていることが多いのですが、私の場合はダメで、ある特定のカレンダーを同期すると問題になっていました。
その特定のカレンダーの同期をはずせば、問題なく動作していたのです。
さらにgaraxyでは、まったく問題なく同期できていたのです。
ちょっと家族もxperiaを使うようになって、まったく同じ現象だったので、どうも私の端末特有の問題ではなさそうなので、ちゃんと調べてみました。
根本原因かどうかわからないのですが、
カレンダーに繰り返し設定がされているイベントがあって、その繰り返しイベントで特定の日を除外設定をしているものがあるとダメなことがわかりました。
なので、繰り返し設定だけで除外日がまったくないようにイベントを変更したら問題なく動くようになりました。
xperiaの問題なのか、androidのバージョンの問題なのかはわからないのですけどね。
2014-01-09
rubyでOCR
rubyで画像上の文字を取得するOCRをやってみした。
OCRのライブラリとしてtesseract-ocrを利用します。
なので、まずはtesseract-ocrを導入する必要があります。
環境は、CentOS6の場合です。
まず必要となるものをyumで入れておきます。
yum -y install autoconf automake libtool
yum -y install libpng-devel libjpeg-devel libtiff-devel zlib-devel
そしてLeptonica という画像解析ライブラリが必要なようなので、これをダウンロードしてコンパイルします。
wget http://leptonica.googlecode.com/files/leptonica-1.69.tar.gz
tar xvzf leptonica-1.69.tar.gz
cd leptonica-1.69
./configure
make
make install
cd ..
いよいよtesseract-ocrと解析に利用する辞書(?)をダウンロードしてコンパイルします。
辞書は英語と日本語のものを入れます。
wget http://tesseract-ocr.googlecode.com/files/tesseract-ocr-3.02.02.tar.gz
tar xvzf tesseract-ocr-3.02.02.tar.gz
wget http://tesseract-ocr.googlecode.com/files/tesseract-ocr-3.02.eng.tar.gz
wget http://tesseract-ocr.googlecode.com/files/tesseract-ocr-3.02.jpn.tar.gz
tar xvzf tesseract-ocr-3.02.eng.tar.gz
tar xvzf tesseract-ocr-3.02.jpn.tar.gz
cd tesseract-ocr
./autogen.sh
./configure
make
make install
mv tessdata/*.traineddata /usr/local/share/tessdata/
利用できるかどうか試してみます。
tesseract-ocrの中にphototest.tifという画像ファイルがあるので、これから文字を取得してみます。
tesseract phototest.tif out
cat out.txt
out.txtになんか文字が出ていればOKです。
なんかいい感じに文字が認識されているように見えます。
日本語辞書も入っていることを確認します。
tesseract phototest.tif out -l jpn
cat out.txt
こちらも何か文字がでればOKです。
こちらは内容は、いけてない感じになります。
ここまでは以下が参考になりました。
http://www.psi-net.co.jp/blog/?p=1080
そしてrubyで使うためのgemをインストールします。
gem install tesseract-ocr
rubyから使ってみます。
以下の画像をOCRにかけてみます。
rubyでocrを使うサンプルは以下のとおりです。
実際の出力は、以下のとおりです。
認識レベルは、なんかちょっとザンネンな感じです。
認識レベルを上げるにはどんな調整をすればよいのかは、よくわかっていません。
rubyでocrを利用することに関しては、以下が参考になりました。
http://schima.hatenablog.com/entry/2013/10/16/203616
OCRのライブラリとしてtesseract-ocrを利用します。
なので、まずはtesseract-ocrを導入する必要があります。
環境は、CentOS6の場合です。
まず必要となるものをyumで入れておきます。
yum -y install autoconf automake libtool
yum -y install libpng-devel libjpeg-devel libtiff-devel zlib-devel
そしてLeptonica という画像解析ライブラリが必要なようなので、これをダウンロードしてコンパイルします。
wget http://leptonica.googlecode.com/files/leptonica-1.69.tar.gz
tar xvzf leptonica-1.69.tar.gz
cd leptonica-1.69
./configure
make
make install
cd ..
いよいよtesseract-ocrと解析に利用する辞書(?)をダウンロードしてコンパイルします。
辞書は英語と日本語のものを入れます。
wget http://tesseract-ocr.googlecode.com/files/tesseract-ocr-3.02.02.tar.gz
tar xvzf tesseract-ocr-3.02.02.tar.gz
wget http://tesseract-ocr.googlecode.com/files/tesseract-ocr-3.02.eng.tar.gz
wget http://tesseract-ocr.googlecode.com/files/tesseract-ocr-3.02.jpn.tar.gz
tar xvzf tesseract-ocr-3.02.eng.tar.gz
tar xvzf tesseract-ocr-3.02.jpn.tar.gz
cd tesseract-ocr
./autogen.sh
./configure
make
make install
mv tessdata/*.traineddata /usr/local/share/tessdata/
利用できるかどうか試してみます。
tesseract-ocrの中にphototest.tifという画像ファイルがあるので、これから文字を取得してみます。
tesseract phototest.tif out
cat out.txt
out.txtになんか文字が出ていればOKです。
なんかいい感じに文字が認識されているように見えます。
日本語辞書も入っていることを確認します。
tesseract phototest.tif out -l jpn
cat out.txt
こちらも何か文字がでればOKです。
こちらは内容は、いけてない感じになります。
ここまでは以下が参考になりました。
http://www.psi-net.co.jp/blog/?p=1080
そしてrubyで使うためのgemをインストールします。
gem install tesseract-ocr
rubyから使ってみます。
以下の画像をOCRにかけてみます。
rubyでocrを使うサンプルは以下のとおりです。
実際の出力は、以下のとおりです。
==== 画像全体から文字を取得します 加順ス 卜ですー メイリ赫すー ーF^ゴシックを 使ってみました〝 ーF“明朝で†〟 ヒロシで†〟 メ 赤し丶字での 古 琶 メイリ祀す〟 茗 で 麦 ==== 画像のメイリオの部分のみ 伽R折ス 卜です〟 メイリ祀す〟 ==== 画像のゴシックの部分のみ ーP^ゴシツクを 使ってみましナこ〝 ==== 画像の明朝の部分のみ ーPA明朝です〟 ヒロシです〟 ==== 画像の赤いメイリオの部分のみ 赤し`字での メイリ祀す〟 ==== 画像の縦書きメイリオの部分のみ メ縦 ィ管 リ實 オで で 麦 ==== 画像の富士山の上のメイリオの部分のみ \ ` '/ f ~ j での 丿 イリ村す~ / ==== 認識した一文字ずつの情報 0 | text=加 pos=(x:28 y:44 w:23 h:12) 1 | text=順 pos=(x:52 y:44 w:42 h:13) 2 | text=ス pos=(x:94 y:44 w:16 h:13) 3 | text=卜 pos=(x:115 y:43 w:11 h:14) 4 | text=で pos=(x:126 y:45 w:16 h:12) 5 | text=す pos=(x:143 y:43 w:15 h:14) 6 | text=ー pos=(x:159 y:53 w:5 h:4) 7 | text=メ pos=(x:29 y:76 w:14 h:13) 8 | text=イ pos=(x:45 y:75 w:14 h:14) 9 | text=リ pos=(x:63 y:75 w:11 h:14) 10 | text=赫 pos=(x:76 y:75 w:32 h:14) 11 | text=す pos=(x:109 y:75 w:15 h:14) 12 | text=ー pos=(x:125 y:85 w:5 h:4) 13 | text=ー pos=(x:385 y:84 w:6 h:11) 14 | text=F pos=(x:393 y:84 w:7 h:11) 15 | text=^ pos=(x:400 y:84 w:8 h:11) 16 | text=ゴ pos=(x:410 y:83 w:14 h:13) 17 | text=シ pos=(x:426 y:84 w:13 h:12) 18 | text=ッ pos=(x:443 y:87 w:10 h:9) 19 | text=ク pos=(x:458 y:84 w:12 h:13) 20 | text=を pos=(x:474 y:83 w:13 h:14) 21 | text=使 pos=(x:384 y:106 w:16 h:14) 22 | text=っ pos=(x:402 y:111 w:12 h:8) 23 | text=て pos=(x:417 y:108 w:14 h:11) 24 | text=み pos=(x:433 y:107 w:15 h:13) 25 | text=ま pos=(x:450 y:106 w:12 h:13) 26 | text=し pos=(x:468 y:107 w:10 h:13) 27 | text=た pos=(x:481 y:106 w:14 h:13) 28 | text=〝 pos=(x:496 y:116 w:6 h:4) 29 | text=ー pos=(x:122 y:137 w:4 h:11) 30 | text=F pos=(x:128 y:137 w:8 h:11) 31 | text=“ pos=(x:136 y:137 w:8 h:11) 32 | text=明 pos=(x:145 y:136 w:14 h:14) 33 | text=朝 pos=(x:160 y:136 w:16 h:14) 34 | text=で pos=(x:177 y:137 w:15 h:12) 35 | text=† pos=(x:193 y:136 w:15 h:14) 36 | text=〟 pos=(x:208 y:146 w:5 h:4) 37 | text=ヒ pos=(x:122 y:161 w:12 h:12) 38 | text=ロ pos=(x:138 y:162 w:12 h:10) 39 | text=シ pos=(x:154 y:161 w:13 h:12) 40 | text=で pos=(x:169 y:161 w:15 h:12) 41 | text=† pos=(x:185 y:160 w:15 h:14) 42 | text=〟 pos=(x:200 y:170 w:5 h:4) 43 | text=メ pos=(x:506 y:170 w:13 h:14) 44 | text=赤 pos=(x:301 y:189 w:15 h:15) 45 | text=し pos=(x:318 y:192 w:7 h:11) 46 | text=丶 pos=(x:328 y:192 w:4 h:9) 47 | text=字 pos=(x:333 y:189 w:15 h:15) 48 | text=で pos=(x:349 y:192 w:15 h:12) 49 | text=の pos=(x:365 y:192 w:15 h:12) 50 | text=古 pos=(x:506 y:185 w:14 h:31) 51 | text=琶 pos=(x:537 y:169 w:16 h:46) 52 | text=メ pos=(x:302 y:223 w:13 h:13) 53 | text=イ pos=(x:318 y:222 w:14 h:14) 54 | text=リ pos=(x:336 y:222 w:10 h:14) 55 | text=祀 pos=(x:349 y:222 w:31 h:14) 56 | text=す pos=(x:382 y:222 w:14 h:14) 57 | text=〟 pos=(x:398 y:232 w:5 h:4) 58 | text=茗 pos=(x:506 y:217 w:14 h:31) 59 | text=で pos=(x:538 y:219 w:14 h:13) 60 | text=麦 pos=(x:506 y:249 w:14 h:22) ==== 認識した文字ブロックの情報 0 | text=加順ス 卜ですー メイリ赫すー ーF^ゴシックを 使ってみました〝 ーF“明朝で†〟 ヒロシで†〟 メ 赤し丶字での 古 琶 メイリ祀す〟 茗 で 麦 pos=(x:0 y:0 w:607 h:476) ==== 認識した文字段落(ブロックとの違いがよくわからない)の情報 0 | text=加順ス 卜ですー メイリ赫すー ーF^ゴシックを 使ってみました〝 ーF“明朝で†〟 ヒロシで†〟 メ 赤し丶字での 古 琶 メイリ祀す〟 茗 で 麦 pos=(x:28 y:43 w:525 h:228) ==== 認識した文字の行ごとの情報 0 | text=加順ス 卜ですー pos=(x:28 y:43 w:136 h:14) 1 | text=メイリ赫すー ーF^ゴシックを pos=(x:29 y:75 w:458 h:22) 2 | text=使ってみました〝 pos=(x:384 y:106 w:118 h:14) 3 | text=ーF“明朝で†〟 pos=(x:122 y:136 w:91 h:14) 4 | text=ヒロシで†〟 メ pos=(x:122 y:160 w:397 h:24) 5 | text=赤し丶字での 古 琶 pos=(x:301 y:169 w:252 h:47) 6 | text=メイリ祀す〟 茗 で pos=(x:302 y:217 w:250 h:31) 7 | text=麦 pos=(x:506 y:249 w:14 h:22) ==== 認識した単語のごとの情報 0 | text=加順ス pos=(x:28 y:44 w:82 h:13) 1 | text=卜ですー pos=(x:115 y:43 w:49 h:14) 2 | text=メイリ赫すー pos=(x:29 y:75 w:101 h:14) 3 | text=ーF^ゴシックを pos=(x:385 y:83 w:102 h:14) 4 | text=使ってみました〝 pos=(x:384 y:106 w:118 h:14) 5 | text=ーF“明朝で†〟 pos=(x:122 y:136 w:91 h:14) 6 | text=ヒロシで†〟 pos=(x:122 y:160 w:83 h:14) 7 | text=メ pos=(x:506 y:170 w:13 h:14) 8 | text=赤し丶字での pos=(x:301 y:189 w:79 h:15) 9 | text=古 pos=(x:506 y:185 w:14 h:31) 10 | text=琶 pos=(x:537 y:169 w:16 h:46) 11 | text=メイリ祀す〟 pos=(x:302 y:222 w:101 h:14) 12 | text=茗 pos=(x:506 y:217 w:14 h:31) 13 | text=で pos=(x:538 y:219 w:14 h:13) 14 | text=麦 pos=(x:506 y:249 w:14 h:22)
認識レベルは、なんかちょっとザンネンな感じです。
認識レベルを上げるにはどんな調整をすればよいのかは、よくわかっていません。
rubyでocrを利用することに関しては、以下が参考になりました。
http://schima.hatenablog.com/entry/2013/10/16/203616
