简单的方法来检测和裁剪图像中的文本块(段落)?

MrV*_*ary 4 ocr opencv numpy image

我已经对该主题进行了一些研究,但是我认为我的问题与之前提出的问题有很大不同。

我的博士论文涉及对旧字典进行OCR,然后将结果自动转换为类似XML的数据库。我已经弄清楚了这部分。但是,我想通过显示用于每个条目/词条的扫描片段来丰富最终结果。由于字典将近9000页长,因此手动进行字典是不可能的。

这是随机页面的外观:http : //i.imgur.com/X2mPZr0.png

由于每个条目始终等于一个段落,因此我想找到一种方法将每个图像分割成带有文本(不需要OCR)的矩形作为单独的文件,就像这样(不绘制矩形):http : //i.imgur.com /CWtQD6Q.png

好消息是我扫描的形状和大小相同,并且页边距/文本对齐方式相似。每个段落也总是有一个标识。

不好的是,我主要是语言学家,而不是程序员。我的大部分经验是使用Ruby,XML和CSS。而且有些段落只有一行。

我知道有些方法可以做类似的事情:

但是它们需要我花费大量时间来学习(尤其是我对Python的了解为0),而且我不知道它们是否不仅允许文本检测,还允许段落检测。

对此问题的任何意见/建议将不胜感激,尤其是对新手而言。

Mar*_*ell 6

我有一些想法要分享...我想我会遵循以下思路:

低分辨率复制的原始图像仅供参考

在此处输入图片说明

第1步-黑白阈值

我想我会为此使用OpenCV的Otsu阈值。

步骤2-查找垂直黑线

我将对图像每一列中的像素求平均,然后找到平均值最低的像素,该像素应该是中间的垂直线。下面的代码输出:

Centreline at column: 1635
Run Code Online (Sandbox Code Playgroud)

步骤3-将图片一分为二并修剪多余的空白

在此处输入图片说明 在此处输入图片说明

第4步-盒子过滤器

我将使用一个55x45的框进行框过滤,该框与每个段落开头的缩进匹配,然后与阈值匹配,因此所有段落的开头都用黑框标记。

在此处输入图片说明

我对OpenCV相当陌生,但是对上述想法进行了如下编码-我确信其中很多可以变得更加健壮和高效,因此将其视为概念性的;-)

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int
main(int argc,char*argv[])
{
   // Load image
   Mat orig=imread("page.png",IMREAD_COLOR);

   vector<int> PNGwriteOptions;
   PNGwriteOptions.push_back(CV_IMWRITE_PNG_COMPRESSION);
   PNGwriteOptions.push_back(9);

   // Get greyscale and Otsu-thresholded version
   Mat bw,grey;
   cvtColor(orig,grey,CV_RGB2GRAY);
   threshold(grey,bw,0,255,CV_THRESH_BINARY|CV_THRESH_OTSU);

   // Find vertical centreline by looking for lowest column average - i.e. darkest vertical bar
   Mat colsums;
   reduce(bw,colsums,0,CV_REDUCE_AVG);
   double min,max;
   Point min_loc, max_loc;
   minMaxLoc(colsums,&min,&max,&min_loc,&max_loc);
   cout << "Centreline at column: " << min_loc.x << endl;

   namedWindow("test",CV_WINDOW_AUTOSIZE);

   // Split image into left and right
   Rect leftROI(0,0,min_loc.x,bw.rows);
   Mat  leftbw=bw(leftROI);
   Rect rightROI(min_loc.x+8,0,bw.cols-min_loc.x-8,bw.rows);
   Mat  rightbw=bw(rightROI);
   imshow("test",leftbw);
   waitKey(0); 
   imshow("test",rightbw);
   waitKey(0); 

   // Trim surrounding whitespace off
   Mat Points;
   Mat inverted =  cv::Scalar::all(255) - leftbw;
   findNonZero(inverted,Points);
   Rect bRect=boundingRect(Points);
   Mat lefttrimmed=leftbw(bRect);

   inverted =  cv::Scalar::all(255) - rightbw;
   findNonZero(inverted,Points);
   bRect=boundingRect(Points);
   Mat righttrimmed=rightbw(bRect);

   imwrite("lefttrimmed.png",lefttrimmed,PNGwriteOptions);
   imwrite("righttrimmed.png",righttrimmed,PNGwriteOptions);

   // Box filter with 55x45 rectangle to match size of paragraph indent on left
   Mat lBoxFilt,rBoxFilt;
   boxFilter(lefttrimmed,lBoxFilt,-1,Size(55,45));
   normalize(lBoxFilt,lBoxFilt,0,255,NORM_MINMAX,CV_8UC1);
   threshold(lBoxFilt,lBoxFilt,254,255,THRESH_BINARY_INV);
   imwrite("leftBoxed.png",lBoxFilt,PNGwriteOptions);

}
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

万一您需要手工来构建此代码-似乎很难对它进行编译和链接-我制作了这样的CMakeLists.txt文件并将其存储在与源文件相同的目录中。然后,创建一个子目录,build以进行“源外”构建,构建过程为:

cd build
cmake ..
make -j 8
./demo
Run Code Online (Sandbox Code Playgroud)

CMakeLists.txt

cmake_minimum_required(VERSION 2.8)
project(demo)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
find_package(OpenCV)
add_executable(demo main.cpp)
target_link_libraries(demo ${OpenCV_LIBS})
Run Code Online (Sandbox Code Playgroud)

关键词:图像处理,书籍,页边距,书脊,中心线,页面,折痕,折叠,装订线,装订,缝合,文本,段落,检测,检测。