これが問題へのアルゴリズム的アプローチの始まりです...
テスト目的で作成したbox.jpg
、352x232ピクセルのサイズの画像を使用しています。

目標は、赤いボックスを識別し、「デイブ」の画像を抽出することです。
私のアルゴリズムのアプローチは次のようになります。
画像を元の幅で、高さが1ピクセルしかないものに拡大縮小します。同時に、グレースケールに変換してコントラストを上げます。ImageMagickが出力できる各ピクセルのプロパティのテキストによる説明を使用します。このようにして、垂直の赤い線のピクセルが極端な色の値を蓄積した2つのスポットを見つけることができるはずです。(垂直の赤い線のピクセルと灰色の文字のピクセルは、より一般的な色の値になります。)
他の方向でも同じようにします。画像を元の高さで幅が1ピクセルしかないものに拡大縮小します(グレースケールに変換し、コントラストを上げ、テキストによる説明を使用します... yadda-yadda)。水平の赤い線のピクセルが極端な色の値を蓄積した2つのスポットを見つけることができます。(灰色の文字ピクセルと組み合わされた垂直の赤い線は、より「平均的な」色の値になります。)
2つの結果のそれぞれで、各カラー値のピークの位置を特定します。これにより、元の画像から抽出するサブ画像のジオメトリが得られます。
元の画像からサブ画像を抽出します。必要に応じて両側をトリミングします。
完全なアルゴリズムを詳しく説明することはできませんが、手順1と2で使用するコマンドは次のとおりです。
ステップ1のコマンド
convert \
-type grayscale \
-depth 8 \
box.jpg \
-scale x1\! \
-contrast-stretch 6x6 \
columns.txt
ステップ1の結果
これはの内容ですcolumns.txt
:
# ImageMagick pixel enumeration: 352,1,255,gray
0,0: ( 0, 0, 0) \#000000 black <-- left outer image border
1,0: (253,253,253) #FDFDFD gray(253,253,253)
2,0: (255,255,255) #FFFFFF gray(255,255,255)
3,0: (255,255,255) #FFFFFF gray(255,255,255)
[...]
20,0: (255,255,255) #FFFFFF white
21,0: (255,255,255) #FFFFFF white
[...]
46,0: (255,255,255) #FFFFFF white
47,0: (255,255,255) #FFFFFF white
48,0: (243,243,243) #F3F3F3 gray(243,243,243)
49,0: ( 0, 0, 0) #000000 black <-- left box border (ex-red)
50,0: ( 0, 0, 0) #000000 gray(0,0,0) <-- left box border (ex-red)
51,0: ( 0, 0, 0) #000000 black <-- left box border (ex-red)
52,0: ( 0, 0, 0) #000000 black <-- left box border (ex-red)
53,0: (221,221,221) #DDDDDD gray(221,221,221)
54,0: (231,231,231) #E7E7E7 gray(231,231,231)
55,0: (236,236,236) #ECECEC gray(236,236,236)
[...]
247,0: (236,236,236) #ECECEC gray(236,236,236)
248,0: (216,216,216) #D8D8D8 gray(216,216,216)
249,0: ( 0, 0, 0) #000000 black <-- right box border (ex-red)
250,0: ( 1, 1, 1) #010101 gray(1,1,1) <-- right box border (ex-red)
251,0: ( 0, 0, 0) #000000 black <-- right box border (ex-red)
252,0: ( 1, 1, 1) #010101 gray(1,1,1) <-- right box border (ex-red)
253,0: (226,226,226) #E2E2E2 gray(226,226,226)
254,0: (244,244,244) #F4F4F4 gray(244,244,244)
255,0: (244,244,244) #F4F4F4 gray(244,244,244)
[...]
303,0: (255,255,255) #FFFFFF white
304,0: (255,255,255) #FFFFFF white
305,0: (255,255,255) #FFFFFF white
[...]
342,0: (255,255,255) #FFFFFF white
343,0: (255,255,255) #FFFFFF white
344,0: (255,255,255) #FFFFFF gray(255,255,255)
345,0: (255,255,255) #FFFFFF gray(255,255,255)
346,0: (255,255,255) #FFFFFF gray(255,255,255)
347,0: (255,255,255) #FFFFFF gray(255,255,255)
348,0: (255,255,255) #FFFFFF gray(255,255,255)
349,0: (255,255,255) #FFFFFF gray(255,255,255)
350,0: (253,253,253) #FDFDFD gray(253,253,253)
351,0: ( 0, 0, 0) #000000 black <-- right outer image border
(注: ImageMagickが時々、時々の色の値を呼び出すこと、そして#FFFFFF
時々white
、時々の色の値を呼び出すことは少し混乱しているようです...たぶんバグですか?とにかく、ここで私たちをブロックしません...)gray(255,255,255)
#000000
black
gray(0,0,0)
ステップ2のコマンド
convert \
-type grayscale \
-depth 8 \
box.jpg \
-scale 1x\! \
-contrast-stretch 6x6 \
rows.txt
ステップ2の結果
これはの内容ですrows.txt
(今回は紛らわしい色の名前を削除しました):
# ImageMagick pixel enumeration: 1,232,255,gray
0,0: ( 0, 0, 0) #000000 <-- top outer image border
0,1: (255,255,255) #FFFFFF
0,2: (255,255,255) #FFFFFF
0,3: (255,255,255) #FFFFFF
0,4: (255,255,255) #FFFFFF
0,5: (255,255,255) #FFFFFF
0,6: (255,255,255) #FFFFFF
0,7: (255,255,255) #FFFFFF
0,8: (255,255,255) #FFFFFF
0,9: (255,255,255) #FFFFFF
0,10: (255,255,255) #FFFFFF
[...]
0,46: (255,255,255) #FFFFFF
0,47: (255,255,255) #FFFFFF
0,48: (240,240,240) #F0F0F0
0,49: ( 0, 0, 0) #000000 <-- top box border (ex-red)
0,50: ( 0, 0, 0) #000000 <-- top box border (ex-red)
0,51: ( 0, 0, 0) #000000 <-- top box border (ex-red)
0,52: ( 0, 0, 0) #000000 <-- top box border (ex-red)
0,53: (225,225,225) #E1E1E1
0,54: (234,234,234) #EAEAEA
[...]
0,207: (244,244,244) #F4F4F4
0,208: (230,230,230) #E6E6E6
0,209: ( 0, 0, 0) #000000 <-- bottom box border (ex-red)
0,210: ( 0, 0, 0) #000000 <-- bottom box border (ex-red)
0,211: ( 0, 0, 0) #000000 <-- bottom box border (ex-red)
0,212: ( 0, 0, 0) #000000 <-- bottom box border (ex-red)
0,213: (234,234,234) #EAEAEA
0,214: (245,245,245) #F5F5F5
[...]
0,229: (255,255,255) #FFFFFF
0,230: (255,255,255) #FFFFFF
0,231: ( 0, 0, 0) #000000 <-- bottom outer image border
これらの2つの結果から、次のように確実に結論付けることができます。
- 左側の垂直の赤いボックスの境界線は、ピクセル列49〜52にあります。
- 右側の垂直の赤いボックスの境界線は、ピクセル列249〜252にあります。
- 上部の水平の赤いボックスの境界線は、ピクセル行49〜52にあります。
- 下の水平の赤いボックスの境界線は、ピクセル行209〜222にあります。
- 1.と2から、197の赤いボックスの「内側の幅」(249から52を引いたもの)を計算できます。次に、抽出されたサブ画像の幅に196を使用しましょう。
- 3.と4から、157の赤いボックスの「内側の高さ」(209から52を引いたもの)を計算できます。次に、抽出されたサブ画像の高さに156を使用しましょう。
- 切り抜きの水平オフセットは52ピクセルである必要があります。53を選びます。
- 切り抜きの垂直オフセットは52ピクセルである必要があります。53を選びます。
したがって、元のサブイメージからサブイメージを切り取るコマンドは次のようになります。
convert -crop 196x156+53+53 box3.jpg sub-box.jpg
または、画像のサイズをこのWebページの白い背景と区別しやすくするには:
convert -crop 196x156+53+53 box3.jpg -colorize 20,0,20 sub-box.jpg
結果の画像:

これで、画像にOCRを適用できます。
tesseract sub-box.jpg OCR-subbox 1>/dev/null && cat OCR-subbox.txt
Dave