d.sunnyone.org
sunnyone.org

ページ

ラベル Scanner の投稿を表示しています。 すべての投稿を表示
ラベル Scanner の投稿を表示しています。 すべての投稿を表示

2012-11-10

bkimgprocに傾き補正機能を追加

bkimgprocに傾き補正機能を追加した。
(といっても、-deskew 40%を引数に追加しただけだけど)

ちなみに、"t"を指定された場合のみ機能するようになっている。テキストでないと誤爆しそうだったので。これでようやくmとtを分けた意味がでてきた。




2012-10-10

自炊向け本画像処理スクリプト群bkimgproc公開

前回のエントリで予告した、ImageMagickのwrapper script群を公開しました。
https://github.com/sunnyone/bkimgproc
git cloneするか、"ZIP"のボタンを押してzipを落として展開してください。

本1冊ごとにディレクトリを作って連番の素材を入れていき、最後にスクリプトを実行するとまとめてくれるツールです。詳しい使い方は、READMEに載せました。

Ubuntu/DebianであればREADMEの方法で使えますが、普通のshell scriptなので、もしかしたらCygwinでも動くかもしれません。

特徴としては、以下の通りです。
  • pdf, cbz出力(PDFは見開き方向指示に対応)
  • 横向きスキャンデータの回転
  • 白レベル自動判定による白レベル調整
  • kobo向けリサイズ(kobo plugin)
  • 余白の自動カット(kobo plugin)
  • テキストのボールド化(kobo plugin)
使い方にも書いてありますが、白レベル判定は、配置したPDFを単位に行うことで、確実性を高めています。なお、PDFの中でも、偶数と奇数ページで白さが違うことがあったので、別々に判定して対応しています。

PDFの見開き方向指示は、こちらの方法を利用させていただいています。

ちなみにうちでは、convall.shの起動は、Jenkinsを使っています。

2012-09-27

ImageMagickで紙の白レベルを判定する

今日は、一部で「美白化」と呼ばれる、もともと白かった紙の色褪せた部分を白くする処理について。白くするには、どれだけ白っぽくするか、すなわち白とする基準を指定する必要があるが、ImageMagickを利用して、どのレベル以降を白と見做すか判断する方法について、この記事で述べる。

結果だけ使いたい方は、判定ロジックのシェルスクリプトを最後に載せているのでどうぞ。
実行すると、このようになる(以下は95%だった例)
$ ./whitelevel.sh test.jpg
95

この方法(+α)で運用しているが、かなりうまく動いている。

背景

ImageMagickを使って美白化をする例はいくつかWeb上にもあり、-levelを使ってパーセンテージ指定で白レベルを指定するか、-linear-stretchを使ってハイライト側のピクセル数から判断する方法があった。しかし、前者は紙によって異なるし、後者は白い部分が少ない画像で悲しい思いをする可能性があるので、実際の画像から白のレベルを決めたい、というのが背景である。

方針

直感的に言えば、白っぽい部分はヒストグラム上は山になっているはずなので、その直感の方法に合わせて、ヒストグラムを作成し、グラフの傾きから計算すればできそうである。しかし、「ImageMagickでヒストグラムを出力し、数値を計算可能な状態にparseする」「数値をもとに山を求める」というののどちらも面倒くさい。しかも、実際に画像を見てみると、白部分がなだらかだったりして、山になっていないこともある。

ちょっと困っていたが、画像を見ていてふと
「はじっこ(枠)って白くね?」
「ImageMagickって枠切りとれるわ」

という2点に気付き、枠を切り出し、その色を白とすることを思い立った。

もう少し具体的な方針を書くと、以下の通りである。
  1. convertコマンドの-trimを利用して、画像全体のサイズと枠の切り出し座標を得る。
  2. 枠のサイズが、白レベルを判定するのに十分であるかを確認する。
  3. 枠を切り出し、色の平均レベル(μ)と、標準偏差(σ)を算出する。
  4. μ-3σ(正規分布における99.73%の点)を得て、白レベルとする。
  5. (得られたレベルと-levelを利用して、美白化する。)

なお、紙の横方向(綴じてあるほうと、その反対側)は、均一でないことがあるので、余白は上下を用いる。

手順

1. convertコマンドの-trimを利用して、画像全体のサイズと切り出し座標を得る

まず、convertコマンドでは、-trimを使うと、余白を切り取ることができる。
-fuzzオプションを併せて利用すると、その範囲を誤差と見做してくれる。
例としては、以下の通り。
$ convert -trim -fuzz 40% hello.jpg hello-trim.jpg

こんな画像が:

こうなる:


さらに、convertコマンドでは、info:を出力先にすると、画像を出力する代わりに、画像の情報を吐き出してくれる。
$ convert -trim -fuzz 40% hello.jpg info:
hello.jpg JPEG 1338x719 1792x1076+184+136 8-bit DirectClass 0.020u 0:00.010

実は、必要な情報は含まれているので、このままでもいいのだが、-formatというオプションを利用すると、出力フォーマットを調整できる。

まずは、以下の情報を使う。
%H   page (canvas) height
%Y   page (canvas) y offset (including sign)
%h   current image height in pixels
それぞれ、「元画像の高さ」「切り出し縦オフセット」「切り出された画像の高さ」である。

$ convert -trim -fuzz 40%  hello.jpg  -format "%H %Y %h" info:
1076 +136 719

これで、切り出しサイズが得られた。

2. 枠のサイズが、白レベルを判定するのに十分であるかを確認する

端から黒かったりすると、白レベル判定に不十分なので、1.で得たサイズが妥当かどうか、確認する。
上記のサイズから計算するだけなので詳細は省くが、今は、高さが全体の1%以下あるいは25%以上の場合は、白レベル判定不能にしている。

3. 枠を切り出し、色の平均レベル(μ)と、標準偏差(σ)を算出する

サイズ情報を得ているので、-cropを使って画像を切り出し、また-formatとinfo:を使って白部分の平均と標準偏差を得る。今回は、以下の指定を使う。

%[mean]                 CALCULATED: average value statistic of image
%[standard-deviation]   CALCULATED: standard-deviation statistic of image

コマンドとしては、ボールド化のときに使った彩度をゼロにする-modulate 100,0を併せて、以下の形(わかりやすさのため改行を入れている)。
$ convert hello.jpg \
  -modulate 100,0 \
  '(' -clone 0 -crop x$TOP_BLANK+0+0 ')' \
  '(' -clone 0 -crop x+0+$BOTTOM_OFFSET ')' \
  -delete 0 \
  -append -format "%[mean] %[standard-deviation]" info:
64209.3 671.804

これは、上下の双方が白レベル判定として有効だったときで、上下をそれぞれ切り出し、もとの画像を削除したあと、くっつけて情報を得ている。$TOP_BLANKは%Yの値で、$BOTTOM_OFFSETは%Y + %hの値である。

4. μ-3σ(正規分布における99.73%の点)を得て、白レベルとする

この得られた白い部分は、ちゃんと白だけの画像であれば、正規分布だろうと想定して、正規分布では99.73%の値をカバーできる、μ-3σの点を白と判断する。
正規分布のイメージはこちら等で: http://www.cap.or.jp/~toukei/kandokoro/html/14/14_2migi.htm

上記の例では、64209.3 - 3 * 671.804 = 62193.888である。
Maxが65535なので、パーセンテージにすると、655.35で割って、62193.888 / 655.35 = 94.901...である。

これで、95%というレベルが得られた。

(5. 得られたレベルと-levelを利用して、美白化する)

端から色がついていたりして、取得できない画像があるので、もう少し工夫が必要なのだが、一応得られたものを適用するには、-levelを利用して、以下のように処理できる。
$ convert -modulate 100,0 -level ,94% hello.jpg hello-white.jpg

実際にこれを使って白くしたものがこちら。

実装

上記を実装したスクリプトは、以下の通り。


よりうまく使うには

よりうまく使うには、単体の画像ではうまくいかず、画像群に対して使うのが妥当なのだけど、それをするとスクリプトを使う前提の説明がしんどいのでここでは省く。

実は何度か紹介してきたような方法を組合せて、決まった置き方をすると自動で本をまとめるスクリプト群ができていて、うまく動いているのだけど、PDF対応中なので、近日公開予定。


2012-09-22

画像分割ツールKiritoriMage公開

画像分割ツールKiritoriMage version 0.0.1をリリースした。GUIアプリケーションのフリーソフトウェアの新規リリースは、もう10年ぶりくらいになる。

http://github.com/sunnyone/kiritorimage/
ダウンロード: https://github.com/downloads/sunnyone/kiritorimage/KiritoriMage-0.0.1.zip

どんなソフトウェアかというと、区切り線を指定して、その区切られた領域をクリックしていくことで、画像を分割していくツール。以下の画像を見てもらえれば、どんなアプリケーションかわかると思う。


たいていの画像処理ソフトは、1回の保存オペレーションでひとつの範囲しか保存できないのに対し、このツールは複数の範囲が保存できるのが特徴。ちなみに、mageと呼ぶほどすごいことはできない。

自分用なので、保存形式がJPEG固定だったり、保存フォルダは画像と同じフォルダのみ(実は裏技があるのだけど)だったりと、制限は多いのだけど、ひとまずは使えるようになったので公開。

MITライセンスにしているので、改変や再配布も自由。もし拡張とかあればpull requestしてもらえれば。

2012-08-22

裁断機180AT-P

前々から、CARL社のディスクカッターDC-210Nで本を切っていたんだけど、最近この機器に必要な40枚(実際は漫画ぐらいの紙の分厚さになると50p=25枚が妥当な印象)ごとに分割する処理が大変になってきて、裁断機がほしくなってきていた。

安全性は気にしている製品がいいし、定番どころでPK-513Lか、その後継のPK-513LNかなぁと思っていたんだけど、ハンドルが畳めないらしく、それはちょっと邪魔だなぁ、いいのないかなぁと思ってやめていた。

ところが、高崎精器というところが出している180AT-Pだと、LEDライトも含めPK-513Lとほぼ同じ性能でハンドルが畳めるというじゃないですか。

ということで180AT-Pを買ってみた。

裁断能力という点では、DC-210Nと比較して40枚が180枚になったというのはやはり大きくて、分厚くない文庫本とか漫画の類なら一発でいけるのは非常に楽。大きい本だとさすがに分けなくちゃいけないけど、手間の量が段違い。作業って、時間も重要な要素だけど、手間っていうのも重要なんだなぁと認識した。

配置しておく場所を作ったので、実はこのブログにあるような立ててしまっておくということはしていないんだけど、ハンドルを折っておけるメリットとして、安心感というのがあるということに気づいた。
というのも、ハンドルが上がった状態だと、ロックはかかっていて実際のところは問題ないのだけど、下方向に力をかけられてしまう。でも、ハンドルが畳んである状態だと、平たいのでそもそも力をかける状況になりにくい。(あそびはあって、押すとちょっとだけ下がるけど)
この安心感は違うなぁと思った。

あとは、LEDが思ったより役に立つということ。裁断機って、こんなに切る場所を定めにくいとは思わなかった。慣れるまでかもしれないけど、期待してなかったけどあってよかった装備。とはいえ、表紙が大きすぎてスキャナに入らない、といった1枚っぺらのようなものだと、これからもディスクカッターを使うけどね。

というわけで、良製品なのに、全然メジャーな感じがしない180AT-Pについて、書いておいてみました。

2012-08-15

ImageMagickで本文ボールド化(改良版)

ImageMagickで「本文ボールド化」っぽいことをするで一応ボールド化できるようになったのだけど、threshold で、重ねる画像(レイヤー)を2値化してしまっているせいで、白黒でスキャンしたときのようなでこぼこが目立つようになってしまった。そこで改良してみた。

改良版はこちら。


改良点は、-thresholdによる2値化をやめ、画像の重ね方を「Multiply」(いわゆるレイヤーの「乗算」)にした。あと、アルファチャネルの作成をやめた。

以前のコマンドは、-thresholdを使わずに+compositeで重ねると、色が濃くなるどころか、かえって薄くなるケースがあったため(重ねた部分が優先されるため)に、黒いところを黒くするために使っていた。しかし、乗算にすれば、どちらかが黒ければ黒くなるので、そうすることにした。(ざっくりたとえば0.2 × 0.2 = 0.04なので、黒くなるという感じ。)
参考:ImageMagick v6 Examples -- Compositing Images


アルファチャンネルの作成も、重ね合わせの処理前にレベル補正をきちんとやっておけば問題なかったのでなくした。逆に、レベル補正しない状態では、アルファチャンネル使うverだと、効果が若干弱くなるものの、ハイライト部分が黒っぽくなることが避けられる感じなので、レベル補正がちゃんとできないようなケースでは、前回と同じく、アルファチャネルにレベルをコピーして乗算したほうがいいかもしれない。

細かいところではほかにも-geometryを-rollにしているが、これは-rollが絵を動かすためのオプションだったので、名前を変えただけ(別に-geometryでも動く)。


この本文ボールド化の効果は、コマンドではわかりづらいので、絵も乗せておく。
(下の絵は、コマンドで処理したのち、画像エディタで切り出し、400%に拡大したもの。)

リサイズ/グレースケール化のみ

convert input.jpg -modulate 100,0 -geometry 650x700 output.jpg


薄い感じ。

+レベル補正/ガンマ補正

convert input.jpg -modulate 100,0 -level 10%,90% -gamma 0.5 -geometry 650x700 output.jpg

結構よくなる。これでもいいかも。ガンマ補正がかなり有効。


+本文ボールド化

convert input.jpg 
  -modulate 100,0   # 色を飛ばす
  -level 10%,90%    # レベル補正
    '(' +clone      # 画像をコピー
        -roll +0+1  # 縦に1pixelずらす
      '(' +clone    # 画像をコピー
        -roll +1-1  # 縦に1pixel戻して、横に1pixelずらす
      ')' +composite -compose Multiply # 縦にずらしたものと、横にずらしたものを乗算で重ねる
    ')' +composite -compose Multiply   # 元の画像と、ずらしたものを乗算で重ねる
  -gamma 0.5        # ガンマ補正
  -geometry 600x750 # サイズ変更
  output.jpg


さらに文字を太く。

2012-08-14

横倒しスキャンはどれだけ速いのか?

本をスキャンする際、横に倒して読んで後で回転させたほうが速くスキャンできると聞いて、どのくらい速くなるか試してみた。単純に考えると、紙を送る量が少ないので、速そうである。

結論としては、試した範囲では、縦でのスキャンに比べて、1.3倍程度の高速化であった。

計測方法

ScanSnap S1500のスーパーファイン/カラーのモードで、以下の3種類の紙を、25枚ずつ、縦(そのままの形)と横(倒した形)で1回(*)ずつ、スキャンボタンを押してから紙送りが終わるまでの時間を、ストップウォッチで計る。

(*)実はいくつか2回読んだ。でも、ほとんど変わらなかったので、1回としている。まぁ、1回でも2回でも精度はよくないと思うので、真面目な結果を知りたい方はぜひもっといろいろなパターン/回数でチャレンジを。

種類高さ幅・高さ比
新書10.8cm17.3cm1.60
コミック(普通)12.3cm18.2cm1.47
コミック(大)14.3cm21.0cm1.46

サイズは、裁断後のサイズ(実測)である。

計測結果

スキャン所要時間の結果は、以下となった。
種類縦(1枚あたり)横(1枚あたり)縦時間・横時間比
新書48.5s34.9s1.94s/枚1.40s/枚1.39
コミック(普通)50.8s38.0s2.03s/枚1.52s/枚1.34
コミック(大)56.4s41.8s2.26s/枚1.67s/枚1.34

感想

200ページ(100枚)のコミックだとすると、縦の場合と横の場合で以下のようになる。
縦:2.03 秒 × 100 枚 = 203 秒 = 3分23秒
横:1.52 秒 × 100 枚 = 152 秒 = 2分32秒
後処理の問題や、紙挿入の取り違えなんかもあるので、この時間差をどう見るかは、人次第だと思う、という感じの結果であった。

また、最初は縦横比そのものになるのかなと思っていたが、縦横比とは若干ずれた比になった。動きを見ていると、紙を送り終わった後に若干の待ちがあるので、縦横比に関わらず1枚あたりに固定的にかかる時間があるのだと思う。

実際、「コミック」の場合で、縦横比に関わらない時間があると想定して計算してみると...
 a: 1cmあたりのスキャン時間
 b: 1枚あたりで固定にかかる時間

 2.03 = 18.2a + b
 1.52 = 12.3a + b
を解いて
 0.51 = 5.9a よって a = 0.086
 2.03 = 18.2 × 0.086 + b より b = 0.46
1cmあたり0.086s、1枚あたり0.46s。

残りの「新書」「コミック(大)」で試しに計算してみると、
新書(横):10.8×0.086 + 0.46 = 1.43s/枚 (実測: 1.40s/枚)
新書(縦):17.3×0.086 + 0.46 = 1.94s/枚 (実測: 1.94s/枚)
コミック大(横):14.3×0.086 + 0.46 = 1.69s/枚 (実測: 1.67s/枚)
コミック大(縦):21.0×0.086 + 0.46 = 2.27s/枚 (実測: 2.26s/枚)
とまぁ実測と近い感じなので、きっとそういう感じなのでしょう。
(もっといい考察があれば教えてくださいまし。)

なお、横版は、紙送りが終わった後に、ファイル(PDF)に出すのに時間がかかっていたということも付け加えておく。

2012-07-29

ImageMagickで「本文ボールド化」っぽいことをする

スキャンした本達を加工しているのだが、バッチ的に加工したいので、ImageMagickで加工する方法を模索している。

概ね自分に必要なことはImageMagickでできそうなのだが、ChainLPについている「本文ボールド化」というのに相当するのが見当たらない。ImageMagickなら適当に操作すればできるだろうということでやってみた。

結論のコマンドは、以下のとおり。


どうしてこうなったのかがわからないと思うので、詳しいことは以下に書く。

方針
本文ボールド化の設定画面を見ると、XとかYがあって、それぞれ値を増やすと画像の黒い部分がそれぞれの方向に伸びる。 ということは、黒い部分を検出して、XとYに伸ばしているに違いないと読んだ。

これは、以下の方法でできそうなので、それをコマンドでやることにする。
  1. 画像をコピーする
  2. 黒検出する
  3. 1pixel移動する
  4. 元の画像に重ねる
実装
上述の方法を、ImageMagickのコマンドで実現するとこうなる。
convert input.jpg # input.jpgをロード
   '('                   # スタックの次の画像として処理開始
      +clone                   # 最後の画像をコピー
      -threshold 50%           # 50%を境に、白黒にする
      -alpha Copy              # 白黒の値(Value大=白なので、白っぽさ)をアルファチャンネルにコピーする
      -channel alpha -negate   # アルファチャンネルの値を、逆転させる(黒っぽさにする)
      -geometry +0+1           # 縦に1pixelずらす
        '('                    # スタックの次の画像として処理開始
            +clone             # 前の画像をコピーして
            -geometry +1-1     # 縦の1pixelを戻し、横に1pixelずらす
        ')'                    # スタックの現在の画像の処理完了
      +composite               # ひとつ前の画像を、その前の画像に結合
    ')'                        # スタックの現在の画像の処理完了
   +composite                  # ひとつ前の画像を、その前に画像に結合 
   output.jpg                  # output.jpgに出力

-threshold 50%は、結構悩んだ。最適解には思えないので、-levelとか、-black-thresholdとかをうまくあてこむともっとよくなると思う。

参考
さらっと書いているが、ここまでたどりつくのにだいぶ苦労した。いろいろなところを読んだのだが、一番近くなったのはここ。
ImageMagick 透過PNGを非透過な画像に変換する

まぁ、なんといっても公式が大事。-fxまで使えれば、特殊なアルゴリズムを必要としない、バッチ的な画像加工は概ねできるんじゃないかと思っているが、まだ使いこなせていない。
ImageMagick: Command-line Options

2012-01-04

SheevaPlugを使ってScanSnap fi-5110EOXをネットワーク対応スキャナにする

タイトルはかなり大げさ。

うちにはfi-5110EOXがあるが、あまり使われていない。その理由は、いちいちWindows PCを立ち上げて作業をしないといけないからだと考えた。そうなのであれば、もっと手軽にスキャンできればよい。そこで、常時起動しているSheevaPlug (Debian入り)でスキャンし、共有フォルダに保存させることにした。
(なぜ「ScanSnap fi-5110EOXをDebian/Ubuntuで使う」をしたかというと、これがしたかったため。)

ベストな方式は、ScanSnapについているSCANボタンを押せば自動的にスキャンしてくれる方式。しかし、頓挫したためやめた(実装としては、scanbuttond, scanbdなどがあるようだ)。

そこで、スマートフォンのWebブラウザを使ってスキャンの指示をすることを考え、Web画面を適当に実装したところ、うまくいった。
スクリーンショットはこんな感じで、スキャンボタンを押すと、scanimageコマンドを起動してスキャンしてくれる。


副作用として、カラー/白黒や両面などのパラメータも指定できるようになった。

せっかくなので公開しておく。ダウンロードはこちらから:
https://code.launchpad.net/~sunnyone41/+junk/scanweb
bzr branch lp:~sunnyone41/+junk/scanwebするもよし、Browse the codeして全部同じディレクトリに
ダウンロードするもよし。ただし、HTMLが適当だったり、OSコマンドインジェクションできたりするので、使うときは適当に直して使うのが推奨。

ScanSnap fi-5110EOXをDebian/Ubuntuで使う

ScanSnap fi-5110EOXをLinux (Debian/Ubuntu)で使う方法。
ご想像のとおり、saneを使うだけ。

<準備>
scanimageがあれば良い。したがって、
# apt-get install sane-utils
これでOK。あとはつなげばスキャンできる。ただ、あとの準備として以下を入れておく。
# apt-get install imagemagick poppler-utils

<スキャン>
xsaneを入れてあれば、それでも良いし、上述のsane-utilsであればscanimageが使える。
使い方は以下。
/usr/bin/scanimage --batch --source "ADF Duplex" --mode Color --resolution=190 --y-resolution=190 --format=tiff
これでカレントにout1.tif, out2.tifという感じででてくる。ADF Frontで表だけにしたり、Grayで白黒にできたりするが、そこはscanimage --helpを参照。resolutionを190としたのは、これ以上大きくすると紙をフィードしてる途中でスキャンが止まってしまうから。
ここはちょっと残念だが、実用範囲なのでOKとする。

<画像変換>
1枚1枚の無圧縮TIFFファイルができるので、ImageMagickでJPEG圧縮してPDFに収める。
convert -compress JPEG -quality 85 -adjoin `ls -1 *.tif | sort -t t -k 2 -n` out.pdf
これでout1.tif, out2.tif, out3.tif... がout.pdfにくっつく。

sort -t t -k 2 -nは順番に並べるためのものだが、少々トリッキーなので説明しておくと、
outN.pdfのNが桁数固定でないので、ただのsortでは順番に並ばない。
普通の1,2,3,...10,11,...であれば-nを使えば数値順に並べられるが、out10.pdfなどという形なので、
それもできない。しかし、ou「t」の「t」をフィールドセパレータと見立てて、2番目のフィールドを数値から始まるようにした後、数値順でソートすればソートできるというわけだ。

これでコマンドラインでのスキャン作業はおしまい。結構簡単であった。
参考:sasasin.net/diary
OpenCVが面白そうなので、そのうちチャレンジしてみようかな。

<おまけ:画像取り出し>
もしPDFに入ったJPEGが欲しくなったら、convertで取り出せるかと思ったが、普通に
convert out.pdf out.jpgとすると、画像サイズが小さくなってしまう。
そこで、poppler-utilsに付属しているpdfimagesを使う。
pdfimages -j out.pdf image
こうすると、image-001.jpgなどという形で、JPEGファイルを切り出せる。

参考:Extract images from a PDF document | Stefaan Lippens' webface