有能なフリ

有能ではないが、有能かのように振る舞う

スマートフォンで撮った書類から影を取り除いてみた

はじめに

久しぶりに記事を書いています、NamedPythonです。

卒業が近づき、卒業研究も大詰めになってまいりました。テーマは「陰影を含む文書画像からの陰影除去」と題して画像処理をちまちまやっていました。

ぶっちゃけほぼ既存だし、目新しいこともしてないので論文書くついでに研究?のまとめとして記事を書きたいと思います。

なんならGitHub公開しています、ハハハ。もはやこうやって記事のネタにすること、公開することを想定してなんとDockerにのっけてあります。すぐ試せるね。

プロジェクトのコードネームはdeshade-doc(でしぇーど どっく)shadeで挟むことによる謎のそれっぽさを演出しています。スタバで10分考えました。

github.com

愚かにも入力画像をignoreしていないですが、見逃してください。

きっかけ

授業ノートとか、書類とかを紙でとっておくのは面倒なので、Scanbotというアプリ でスキャンして管理していました。

そこそこ気に入っていて、ある程度のノイズは取り除いてくれていました。しかし、にはどうも弱いらしく黒つぶれが多発していました。

表面化していた問題はそこではなく、OCRが効かないというところだったので、当初はOCRの精度改善をテーマにしようと考えていましたが、なにせ郵便局あたりが頑張ってしまって研究の余地がない。ないというか、僕の技術では追いつけない

じゃあOCRかける前段階、二値化とか画像への前処理を研究すればいいんじゃないの、っていうことで陰影の除去をテーマにしました。

一応重複とか類似の研究は調べましたが、ここまでピンポイントなのはなかった気がします。あったらこっそり教えてください。といっても時すでに遅しですが。

環境

めちゃんこわかりやすい。

あとはこの上でドッカーン。コンテナの中身は

です。もともと FROM ですでにあるイメージを引っ張ってきてPillowを足してるだけなのでシンプル。他の授業でも使うので流用ができている、良きかな。

理論みたいな

そんな大層なものではないですが、考えなしにやっているわけでもないのでそれっぽく。

二値化の手法としてそこそこ有名?な判別分析法ではうまく二値化できないことを利用して、「陰影を含んでいる文書は判別分析法でうまく二値化できない。問題がある。」といちゃもんをつけて問題を解決する形をとっています。

しかし、判別分析法のいいところ(と、勝手に思っているの)は、曖昧な影の輪郭(領域)を、ヒストグラムをもとにはっきり示してくれるところです。しかしこの判断ができるのは、文書画像のみであることに注意されたい。風景写真ではこんなガバガバな判断基準で陰影の領域は断定できないです。

では、「判別分析法によってはっきりした領域を切り出して、個別に処理してあげればいいではないか」と考えて、手っ取り早くガンマ補正をしました。

一回ではそうはうまくいかないので、ちまちま二値化、切り出し、ガンマ補正、元の位置に貼り付け、二値化、...という風に繰り返す処理にしました。

切り出しの条件はというと、面積です。そこそこ大きい面積の暗い領域を影と決めつけて、切り出しています。

そして、このが見つからなくなったら繰り返し脱出、有限回で終了、アルゴリズムとしても破綻していない(はず)です。

以下はこれらに結果をつけながらつらつらと。

各ステップと結果

1.

文書を携帯端末で撮影、クロップします。なので入力画像はクロップされた3チャンネル画像です。画像は実際に僕がとったノート。

f:id:namedpython:20181225155543j:plain
入力画像

2.

判別分析法を用いて二値化。 すると、影がある場合はヒストグラム(および割り出される閾値)が偏って影の部分は黒く潰れます。以下は大津の二値化をかけたもの。すごく黒く潰れる。

f:id:namedpython:20181225160131p:plain
判別分析法で二値化をかけた入力画像

3.

影の部分を切り出してガンマ補正γ=1.2くらい(これらは1.18)でゆっくり明るくしていく。以下は切り出した影の部分(左)とガンマ補正をかけたあと(右)。

f:id:namedpython:20181225162331p:plainf:id:namedpython:20181225162326p:plain
ガンマ補正前、ガンマ補正後

4.

元の位置に貼り付けます。実はMatで貼り付けるのがめんどくさくてImage.paste()を使うためにここだけPILを使っていたり。貼り付けると明るくしたのがわかりやすい。

f:id:namedpython:20181225163243p:plain
元の位置に貼り付け

5.

2の手順に戻って判別分析法で二値化します。以下は2との比較。

f:id:namedpython:20181225160131p:plainf:id:namedpython:20181225163716p:plain
さっきの二値化、今回の二値化

あれ、なんか領域広くなってますね。いいんです。これはまだ途中経過。こうやって階層的に明るくする範囲を拡大していくんです。

6.

以降は、切り出し、ガンマ補正、元の位置に貼り付けまで一気にやったものを、前後比較しながら見ていきましょう。

f:id:namedpython:20181225163243p:plainf:id:namedpython:20181225164217p:plain
貼り付け1回目、貼り付け2回目

少し段ができましたね。次も見ていきましょう。

7.

プログラム内のループで言えば3ループ目になります。

f:id:namedpython:20181225164217p:plainf:id:namedpython:20181225164704p:plain
貼り付け2回目、貼り付け3回目

8.

そうこうして15ループします。このループ数は影の分散具合とγをどれくらい細かく(>1.00)するかによります。これが最終結果。元画像と比べてみましょう。

f:id:namedpython:20181225155543j:plainf:id:namedpython:20181225165104p:plain
最初、最後

...できてはいるけど汚い。っていうのは心にしまっておいてください。階層的に明るくしていった感じがわかると思います。思いの外、この階層が影の濃度ごとに分かれていて面白い。

9.

最後のものを判別分析法によって二値化します。プログラム的には、ここである一定の面積の黒い領域がなければbreakとなっています。以下は最初の二値化と最後の二値化。

f:id:namedpython:20181225160131p:plainf:id:namedpython:20181225165445p:plain
最初の二値化、最後の二値化

こう見ると、だいぶ綺麗になっています(言い聞かせるように)。 かすれている部分は、僕の筆圧が足りていなかったり過度に照明が当たっていたりする部分です。

まとめと所感

「やってみた感」と思ったあなた、正解です。研究としての体裁を最低限保ったやってみたです。でも研究の動機はそんくらいがいいだろうと思っているので、僕は僕を許します。

ちなみに実行時間はまあまあ現実的。入力画像はリサイズしていたりします。 上の結果は15ステップですが、実行時間は約20[sec]timeコマンドをつけて計測したrealタイム。リアルタイム処理は想定していないのでこんくらいが妥当だと愚考。

もちろん、伸び代はあります。γは可変にできますし、現在の処理に加えて明るすぎる領域は明度を下げて白飛び黒つぶれ両方に対応したらもっと綺麗になると思います。

ですが、今回はここまで。あとは論文を書くだけです。

さいごに

読んでいただきありがとうございました。まとめかた、およびアウトプットが下手なので、とりあえず数を打って改善を図ります。

GitHubに上がってはいますが、なんというかバックアップに近いので、READMEは需要があれば書きます。

ではまた。

Railsのデプロイ先でレイアウト変更が反映されないトラブル

はじめに

自分が経験不足なだけと思っていたトラブルに関して,割と詰まる人多いかなと思って書きます.

環境

大したことじゃないので雑にいきます.

症状

ローカル環境では反映されてたのにデプロイ先では反映されてない,とか.
rails5 assets doesn't workとか,There are differences between local(development) and deployed(production)とか.

解決策

多分二つある.

デプロイ前に毎回precompileする

デプロイ先だと,precompileされたapplication.*を読むらしい.ローカルは各assets読むからすぐ反映される.

んじゃデプロイ前にprecompileしようねってことで以下のコマンド.

$ bundle exec rake assets:precompile

これやると各assetsがapplication.*にに集結する.はいハッピー!

configいじる


production.rbにprecompileをtrueにするconfigがあったからそれ.


雑だけどあった気がする.時間がないので検証は省略.

おわりに


10分で書いたので誤記を含むと思われます.指摘していただけるとハッピーです.
これで結構長いこと悩んだ経験あるので誰かのお役に立てれば.

ではまた.

言う側の「わかりました」

「…わかりました」

割とポロっと口から出る割に,だいたいわかってない.

けれど,わかるまで説明をお願いするのも申し訳ないし,話を聞きながらではあまり整理がつかない.

メモを取るにも話が抽象的するぎる.

「すみません,いまいちわからないので,一度自分で整理します.」

一時的に話から離脱して,自分の理解を見直す.

相手の言葉が消えないうちに,自分の世界へ持ち込んで,理解を組み立てる.

理解が形になったと思ったら,相手に確認を取る.話に具体性が出て,理解を固めやすくなる.

相手の時間もとらないし,理解もできる.お互いに幸せになれる.

なぜかを考える

話す側の説明は,いまいち整理されていない.なぜなら,話し言葉のほとんどは,準備された文章ではないから.

わかりやすいための工夫をしていても,断片的でしかない.

ストリームを受け取って,リアルタイムにデータを構築できるのは,一緒にいる時間が長い人同士にしかできない(と思う).

それなら,リアルタイムに構築するのではなく,すべて受け取ってから構築を開始するべきだと思う.

話から離脱しているので,構築の余裕もそれなりにある.人との会話は,脳のリソースを結構食う(と思う).

わかるまで説明してもらうことは,また同じストリームを開始することであり,人間の場合,表現方法が変わって余計わからない.

おわりに

ここ最近で思うところがあったので書きました.

仕事を振る立場も,振られる立場も,いろいろ意識することがあるなと感じました.

ではまた.

Raspberry Pi 3に電源を繋ぐだけでSSHとVNCができる環境を構築する via Bluetooth PAN

はじめに

授業でRaspberry Piを扱うことになって,できるだけ少ない配線で作業したいなと思って構築した環境です. どっちかっていうと実用ではなく学習向けの環境かも.インターネット共有はできません.

f:id:namedpython:20170415121820j:plain

環境

初期セットアップはやっぱり装備多めになりますよね〜.

これらを最終的に上から4つ(または5つ)ぐらいまでに絞ります.

やり方

普通にセットアップしていきます.

まずはRaspbianを公式からダウンロードします.割と長い.

ダウンロードできたら,イメージをmicroSDに焼いていきます.

macOSのターミナルにて

$ diskutil list
$ diskutil unmountDisk /dev/diskN
$ diskutil eraseDisk MS-DOS RASPI /dev/diskN
$ diskutil unmountDisk /dev/diskN
$ sudo dd if=~/Downloads/xxx-raspbian-jessie.img of=/dev/diskN bs=N

Nは,環境に合わせて適当にやってください.eraseDisk前のunmountは必要だったか覚えてませんが,まあ一応やっておきます.

焼き終わったらRasPiに各種I/Oと焼いたmicroSDを差して電源を投入します.

無事起動したら,左上のスタートボタンからPreference -> Raspberry Pi Configurationをクリック.

Interfaceタブから,SSHを探してEnableしておく.Localeタブから,ロケールとかタイムゾーンとか設定しとく.

設定の適用には再起動が必要なので,ダイアログに従って再起動する.

戻ってきたらコンソールを立ち上げて,update & upgradeしていきます.

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get dist-upgrade

パスワードが初期パスのままなので変えておきましょう.初期パスはraspberryです.

$ passwd
  1. 初期パス
  2. 新パス
  3. 新パス確認

の順で打っていきます.このパスはSSHのログインにも使います.

次に,ネットワークの設定をやっていきます.コンソールエディタを使いますので,いろいろ好みはあると思いますがなければインストールしておきます.

$ sudo emacs /etc/dhcpcd.conf

こいつに追記していきます.

bnep0は,今回のメインであるBluetooth PANのインターフェースです.書いといてください.

#Bluetooth PAN with my MBP
interface bnep0
static ip_address=192.168.x.y/z
static routers=192.168.l.1

xyzは好みで変えてください.

static ip_addressに設定したアドレスは,静的に割り振られます.メモっときましょう.

次に,BluetoothMacとRasPiをペアリングします.

$ bluetoothctl
[bluetooth]# scan on

こうすると,周囲のBluetoothバイスが検知されていきます.

自分のMacが検知されたら(そのMacのの名前とアドレスが出ます),一緒に書かれているアドレスをメモっときます.以降,これをBT_Addrと呼びます.

ではペアリングです.

自分がやった時割とよくFailedとか出されたので,出た場合は後述の対処をしてください.

[bluetooth]# pair BT-Addr
[bluetooth]# connect BT-Addr
[bluetooth]# trust BT-Addr

とします. これらのいずれかでBluez.Failedとか出されたら,以下の対処を試してください.

$ pulseaudio --start
$ bluetoothctl
[bluetooth]# connect BT-Addr

これでできなかったら,もうわかりません.格闘してください.

自分はこれで成功したこともあったのですが,なぜこれで成功するのかわかりません.格闘してたら見つけました.

それでは,ペアリングが完了した前提で進めていきます.確認方法としては

  • Mac側のBluetooth設定でraspberrypiが太字になっている.

  • Raspbianの左上の方のBluetoothアイコンをクリックすると,自分のMacの名前の左にチェックマークがついている

って感じです.これらが揃っていればペアリングは成功しているでしょう.

次に,Bluetooth PANを構築します.

参考にした記事はこちら

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

sudo apt-get install python-dbus

スクリプトを適当な場所にwgetし,実行権限とか与えて,BluetoothPANのリクエストをMacに送信します.

$ wget https://raw.githubusercontent.com/mk-fg/fgtk/master/bt-pan
$ chmod +x bt-pan
$ sudo chown root: bt-pan
$ sudo mv bt-pan /usr/bin/
$ sudo bt-pan client BT_Addr

Macにダイアログが出てくるので許可する.

ここで一旦Macの設定に戻ります.Macの設定からネットワーク設定を開きます.左側の窓の中にBluetooth PANが出ていると思いますが,自己割り当てアドレスとなって黄色くなっていると思います.

これを修正しなければなりません.Bluetooth PANの詳細を開き,TCP/IPタブで,IPv4の設定を手入力にします.もし他の設定とかぶったりする場合は新しくプロファイルを作ってくださいね.

そして,IPv4アドレスのところをstatic routersのアドレスにします.

サブネットマスクはおおかた255.255.255.0でしょうか.

ルーターはメインのネットワークのルーターアドレスを設定しておきましょう.

これで,黄色から緑になったと思います.

ではRasPiに戻って,コンソールでIPが振られているか確認しましょう.

$ ifconfig bnep0

これで,inetのアドレスが,static ip_addressのアドレスになっていればうまくBluetooth PANが構築できています.

それでは,電源投入後自動で構築するようにしましょう.

sudo emacs /etc/rc.local

一番下にexit 0が見えると思いますが,そこの上であればどこに書いても構いません.

先ほど実行したbt-panを,ここに記述しておきます.これにはsudoは不要です.

bt-pan BT_Addr

と記述します.

ここまできたら,とりあえずテストとしてMacからSSH叩いてみましょう.

ssh pi@192.168.x.y

これでパスワード入力まで行けば成功です.一旦sudo rebootして再起動しましょう.自動でMacとつながるかどうか試します.

RasPiが起動した10秒後くらいにもういっかいSSHを叩いてパスワード入力まで行くようであれば,rc.localに書いた自動接続もうまくいっているようです.

それでは最後にVNCもできるようにしましょう.

MacからのVNCなので,プリインストールのReal VNCではできません.別のパッケージを使います.

sudo apt-get install tightvncserver

これをインストールすると,$ vncserver$ tightvncserverエイリアスされます.

$ vncserver

と実行すると,初回は接続用のパスワード設定しろと出てくるので,設定しましょう.

設定が終わると,画面の配信が始まります.気をつけて欲しいのは,配信される画面はディスプレイに映っているものと同じではなく別ウィンドウだということです.

それでは接続してみましょう.

MacのFinderを開きます.メニューバーの移動から,一番下のサーバーに接続をクリックします.

ダイアログが出てくるので,アドレス欄にvnc://192.168.x.y:5901と打って接続します.:5901もちゃんとつけてくださいね.

パスワード入力を要求されるので,入力して接続します.すると,RasPiの画面がMacに映ります!やったね!

VNCは,あくまで第二の手段として用意しておくまでです.基本的には,必要になった時にSSHから叩いてからの接続です.もし起動時に配信したいのであれば,先ほど同様rc.localに記述しましょう.

もし配信を停止したければ

$ vncserver -kill :N

で配信を切れます.Nは,$ vncserverを叩いた時に出てくるウィンドウ番号です.

けっこう長くなりましたね.お疲れ様でした.

Bluetooth PANによる接続ですが,インターネット接続は提供できません.他のやり方でできるかもしれませんが,このやり方ではできません.

しかし,僕がなぜWi-Fi共有ではなくBluetooth PANを選んだかにはきちんと理由があって,Mac/RasPi側のWi-Fi等を食いつぶしたくなかったからです.

RasPi側に,Bluetooth PAN以外に外界へのネットワーク接続をすれば,パッケージ等のインストールもSSH越しでできます.

あ,注意してほしいのですが,Mac側がスリープしてペアリングとかBluetooth PANが途切れると,他のネットワークを経由するか再起動しか接続の方法がありませんので悪しからず.

おわりに

画像とかなくてすみません.後日スクショとかつけるかもしれません.

指摘等ありましたらコメントでお願いします.

長くなってすみませんでした.あなたのRasPiライフがスマートでありますように.

ではまた.

Safariとかで出る警告『Unexpected CSS token』

はじめに

今回もGithub Issueに埋もれてるんじゃ?と思って書きます.

環境

症状

警告なのでそこまで気にすることでもないのですが,ないに越したことはないので一応対応しようと思いました. その警告は,bootstrap等のgemを利用していると出るのですが,タイトルにもある通り『Unexpected CSS token』. 10件くらいまとめて出てくるわりに,ページのスタイルが崩れているわけでもなかったので,調べました.

解法というより解説

github.com

おそらく調べると一番上かそこらに表示されるページなんですが,Issueスレたどるのって結構めんどくさかったりだいたい英語だったりするので翻訳も含めて解説しちゃいます. 大したことでもないんですけどね.

というのも,この警告はIE8やそこらへんの特殊なブラウザへのスタイル適用のためのコードが,Safariだと警告されて出てくる.ということらしいのです.

試しに,SafariのユーザーエージェントをIE8に変えてやってみたら警告は綺麗さっぱり消えました.

ユーザーエージェントは,開発タブ > ユーザーエージェント > (各エージェント) で変更できます.

開発タブがない場合は,メニューバーのSafari > 環境設定 > 詳細 の一番下にチェックボックスがあるのでそこにチェックです.

おわりに

今更ですが,生のWebをきっちり触ってからRails触りたかったと後悔しています. ではまた.

RailsのUpdateがうまくいかない

はじめに

トラブル解決というわけでもなく,格闘の結果わかったことを書きます. とある予約システムを作っていて,Submit毎のリダイレクトがうざいので非同期にしようと考えてremote: trueとかやって周りを調整してました. お客さんが触る部分はわりとすんなり非同期にできたんですけど,管理画面(ステータス表示・変更)を非同期にしたら500(Internal Server Error)吐きまして,そういう話です.

環境

  • Rails 5.0.0.1
    • development
    • SQLite3

超適当ですすみません.

症状と格闘の結果

冒頭で書いた通り,500を吐かれました.これはブラウザ側で見たエラーコンソール.じゃあRailsのログには何が残っていたかというと,

...
(1.0ms) rollback transaction
...
ActiveRecord::StatementInvalid (SQLite3::BusyException: database is locked: commit transaction):
...

死ぬほど省いてますがこんな感じ.rollback?! BusyException?! リダイレクトしないようにしただけで?!と思いながら格闘開始.

database is lockedから見るに,アクセスが衝突したんだろうな〜と思いながらエラー名コピペサーチでビンゴ.なんで衝突したのかの究明へ.

  • 作成Submitはめちゃすんなりできる
  • 更新Submit&Redirectはいける
  • 更新Submitは死ぬ

これらとのコードの違いを見ていきながらデバッグしていった.

得られた結果

という感じになりました.productionで試しても良かったのですが,「まぁ管理画面くらいリダイレクトしようや」とサボローがいったので保留. 他に読んだ記事はこれくらい

最近テストコードは書くようになりましたが,デバッグは雑ってよく言われるのでおそらく解決策は存在すると思うのでもう少し格闘します.

おわりに

Atomのterminal-plusの記事がよく読まれていてめっちゃ嬉しいのでトラブル解決系書きたいんですけど,そこまでトラブルに出会わないので書けません. そういえばMacBook Pro(Late-2016)買いました.またなんか開発したいです. ではまた.

Atomのterminal-plusが動かないトラブル

はじめに

久しぶりの記事です.そして新年ですね.あけましておめでとうございます.
今回の記事についてですが,解決法がterminal-plusのIssueに上がってて自分の環境では解決したのですが,もしかして他のIssueに埋もれて見えないんじゃないかと思って記事にしようと思いました.
こういう技術系の記事ってQiitaの方が良かったりするんですかね...(小声)

環境

現時点での環境です.実際のトラブルはもう少し下のバージョンだったかもしれません.

※ご注意 2018/12/25追記※

terminal-plusの後継パッケージ、platformio-ide-terminalがでています。現在は以下の対処をするより上記パッケージを導入する方が得策です。

筆者はVSCode浮気をしているので状況は変わっているかもしれませんが、以下の対処は非推奨とします。

症状

検索に引っかかるようにここに症状を書きだしときます.
英語で検索かける人向けにterminal-plus not workingとかいれとくといいのかもしれませんね.
症状は,Atom内でterminal-plusを起動しても入力待機してくれない(カーソル点滅もない)というものです.
自分はちょっとだけprofileをいじったbashを使ってるのですが,terminal-plusは各個人の環境と同じシェルをAtomに出してくれます.
f:id:namedpython:20170101181829p:plain
macOS上のターミナルの画像です.変なカスタムをしてても...
f:id:namedpython:20170101182334p:plain
ちゃんとそのまま出てくれます.
今回の症状は,
https://cloud.githubusercontent.com/assets/17022349/20955206/91868450-bc41-11e6-8c56-e17927dc0240.png
このままの状態で動かないものです.これは入力待機状態ではありません.正常なterminal-plusの動作は,各環境でのシェルと同じものになっているはずです.先ほど自分の環境の画像を出したのはこれを説明するためです.(もちろん,zsh等使っている人はそれが出ますよ!)

解決方法

いちおうterminal-plusのGithub Issueに書いてあることなのでリンクを載せておきます.
Issueのタイトルにもある通り,temporary fix(一時的修正,要は応急処置)なので,修正リリースがくると思います.もうきてたりして...
github.com
まず,メニューのAtom -> 環境設定 -> パッケージ -> 検索欄[terminal-plus]でパッケージを選択します.
f:id:namedpython:20170101185005p:plain
次にterminal-plusのパッケージ画面から,View Codeをクリックします.
f:id:namedpython:20170101185306p:plain
Tree Viewからpackage.jsonを選択します.
f:id:namedpython:20170101185412p:plain

編集画面47行目あたりに,

"pty.js": "git+https://github.com/jeremyramin/pty.js.git#28f2667",

とあると思います.これを,

"pty.js": "git+https://github.com/jeremyramin/pty.js.git",

に書き換えます..git以降を削ればOK.この時点ではまだ治っていません.
ターミナルを開いて,次のようにコマンドを打ちます.コマンドから見るにパッケージのリビルドですかね.

$cd ~/.atom/packages/terminal-plus/
$npm install
$apm rebuild

そしてAtomを再起動.これで治ると思います.

$npm install

でエラーが出た人はNodeJSが入っていないかもしれないので

$brew install node

とかでNodeJSをインストール.

$apm rebuild

でエラーが出た人はシェルコマンドが入っていないかもしれないので,メニューのAtom -> シェルコマンドをインストール でインストールしましょう.

おわりに

親切でやわらかい解説を心がけました.用語間違ってたらすみません,指摘してくださるとありがたいです.
つい最近までAtom.appを開いて使っていたのですが,あれだと環境変数参照できなかったりするんですね.LaTeXコンパイルができなくてめっちゃ悩んでました.コマンドラインから起動するようにしたら治りました....
今年もプロコンとかいろいろ頑張っていきます.
ではまた.