如何检测图像中的框并将其作为单个文件拉出?

时间:2012-04-09 14:39:18

标签: php image-processing imagemagick ocr tesseract

我需要采用编程方式拍摄扫描图像(让我们假设PNG或任何其他方便的图像格式)并将其分解为许多较小的图像。扫描的图像是网格,网格的框总是相同的大小和相同的相对位置。由于扫描图像,因此它们不一定在同一绝对位置。在每个框中都是一个字符,理想情况下我想将字符保存为自己的图像文件,没有任何框边框。

我更喜欢PHP和ImageMagick,我认为这将是正确的工具组合。但是,如果有更好的方法,我会很灵活。

1 个答案:

答案 0 :(得分:5)

这是解决问题的算法方法的开始......

我正在使用我为测试目的创建的这张图片,名为box.jpg,尺寸为352x232像素:

The test image...

目标是识别红色框并提取“Dave”图片。

我的算法方法如下:

  1. 将图片缩放为具有原始宽度,但高度仅为1像素的图片;同时转换为灰度并增加对比度;使用ImageMagick可以发出的每个像素属性的文本描述。通过这种方式,您应该能够找到垂直红线像素累积极端颜色值的两个点。 (垂直红线像素和灰色字母像素将具有更常见的颜色值。)

  2. 在另一个方向上执行相同操作:将图片缩放为具有原始高度的图片,但宽度仅为1像素(转换为灰度,增加对比度,使用文字说明... yadda- yadda)。您将找到水平红线像素累积极值颜色值的两个点。 (垂直红线与灰色字母像素组合将具有更“平均”的颜色值。)

  3. 确定两个结果中每个结果中每个颜色值峰值的位置:这将为您提供从原始图像中提取的子图像的几何图形。

  4. 从原始图像中提取子图像。根据需要裁剪每一面。

  5. 我无法详细说明完整的算法,但这里是我用于步骤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 somtimes black的颜色值,somtimes 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
    

    从这两个结果我们可以得出可靠的结论:

    1. 左侧垂直红色框边框线位于像素列49-52。
    2. 右侧垂直红色框边框线位于像素列249-252。
    3. 顶部水平红色框边框线位于像素行49-52。
    4. 底部水平红色框边框线位于像素行209-222。
    5. 从1.和2.你可以计算出红色方框的“内部宽度”197(249减去52)。让我们使用196作为提取的子图像的宽度。
    6. 从3.和4.您可以计算红色框的“内部高度”157(209减去52)。让我们使用156作为提取的子图像的高度。
    7. 裁剪的水平偏移需要为52像素。我们选53。
    8. 裁剪的垂直偏移量需要为52像素。我们选53。
    9. 因此,我们从原始图像中剪切子图像的命令可能是:

      convert  -crop 196x156+53+53  box3.jpg  sub-box.jpg
      

      或者,为了使图像尺寸更好地与此网页的白色背景区分开来:

      convert  -crop 196x156+53+53  box3.jpg  -colorize 20,0,20  sub-box.jpg
      

      结果图片
      enter image description here

      您现在可以在图像上应用OCR:

      tesseract sub-box.jpg OCR-subbox 1>/dev/null && cat OCR-subbox.txt
      
        Dave