【问题标题】:converting cv::Mat for tesseract将 cv::Mat 转换为 tesseract
【发布时间】:2011-11-13 22:44:43
【问题描述】:

我正在使用 OpenCV 提取扫描文档的子图像,并希望使用 tesseract 对此子图像执行 OCR。

我发现我可以在 tesseract 中使用两种方法进行文本识别,但到目前为止我还没有找到可行的解决方案。

A.) 如何将 cv::Mat 转换为 PIX* (PIX* 是leptonica 的数据类型)

基于下面的 vasiles 代码,这基本上是我当前的代码:

 cv::Mat image = cv::imread("c:/image.png"); 
 cv::Mat subImage = image(cv::Rect(50, 200, 300, 100)); 

 int depth;
 if(subImage.depth() == CV_8U)
    depth = 8;
 //other cases not considered yet

 PIX* pix = pixCreateHeader(subImage.size().width, subImage.size().height, depth);
 pix->data = (l_uint32*) subImage.data; 

 tesseract::TessBaseAPI tess;
 STRING text; 
 if(tess.ProcessPage(pix, 0, 0, &text))
 {
    std::cout << text.string(); 
 }   

虽然它没有崩溃或发生任何事情,但 OCR 结果仍然是错误的。它应该可以识别我的示例图像中的一个单词,但它会返回一些不可读的字符。

PIX_HEADER这个方法不存在,所以我用pixCreateHeader,但是它没有把通道数作为参数。那么如何设置频道数呢?

B.) 我如何将cv::Mat 用于TesseractRect()

Tesseract 提供了另一种使用此签名的文本识别方法:

char * TessBaseAPI::TesseractRect   (   
    const UINT8 *   imagedata,
    int     bytes_per_pixel,
    int     bytes_per_line,
    int     left,
    int     top,
    int     width,
    int     height   
)   

目前我正在使用以下代码,但它也会返回不可读的字符(尽管与上面的代码不同。

char* cr = tess.TesseractRect(
           subImage.data, 
           subImage.channels(), 
           subImage.channels() * subImage.size().width, 
           0, 
           0, 
           subImage.size().width, 
           subImage.size().height);   

【问题讨论】:

    标签: c++ opencv tesseract


    【解决方案1】:
    tesseract::TessBaseAPI tess; 
    cv::Mat sub = image(cv::Rect(50, 200, 300, 100));
    tess.SetImage((uchar*)sub.data, sub.size().width, sub.size().height, sub.channels(), sub.step1());
    tess.Recognize(0);
    const char* out = tess.GetUTF8Text();
    

    【讨论】:

    • 我在 iOS 上从来没有成功过。当本机字节顺序与 leptonica 想要的匹配时,也许这有效?
    • 确实是@KaolinFire。它在 C++ 或 iOS(跨平台)上对我不起作用。相同的图像,从文件名和垫子分析,一个是好的(文件名),垫子不是。见stackoverflow.com/questions/27000797/…
    【解决方案2】:

    对于任何使用 OpenCV/Tesseract 的 JavaCPP 预设的人来说,这是可行的

    Mat img = imread("file.jpg");
    Mat gray = new Mat();
    cvtColor(img, gray, CV_BGR2GRAY);
    
    // api is a Tesseract client which is initialised
    
    api.SetImage(gray.data().asBuffer(),gray.size().width(),gray.size().height(),gray.channels(),gray.size1())
    

    【讨论】:

      【解决方案3】:
      cv::Mat image = cv::imread(argv[1]);
      
      cv::Mat gray;
      cv::cvtColor(image, gray, CV_BGR2GRAY);
      
      PIX *pixS = pixCreate(gray.size().width, gray.size().height, 8);
      
      for(int i=0; i<gray.rows; i++) 
          for(int j=0; j<gray.cols; j++) 
              pixSetPixel(pixS, j,i, (l_uint32) gray.at<uchar>(i,j));
      

      【讨论】:

      • 如果我的 Mat 图像是二进制的怎么办?我应该改变什么?
      【解决方案4】:

      首先,对您的 subImage 进行深拷贝,以便将其存储在连续的内存块中:

      cv::Mat subImage = image(cv::Rect(50, 200, 300, 100)).clone(); 
      

      然后,使用正确的参数初始化一个以 PIX 为首的(我不知道如何)。

      // ???? Put your own constructor here. 
      PIX* pix = new PIX_HEADER(width, height, channels, depth); 
      

      或者,手动创建它:

      PIX pix;
      pix.width = subImage.width;
      ...
      

      然后将pix数据指针设置为subImage数据指针

      pix.data = subImage.data;
      

      最后,在完成 pix 工作之前,确保您的 subImage 对象不会超出范围。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-29
        • 2014-05-07
        • 2011-06-07
        • 2016-04-13
        • 2011-10-23
        • 1970-01-01
        • 2012-01-03
        • 1970-01-01
        相关资源
        最近更新 更多