将 PDF 转换为 PNG 以供 Tesseract 处理
Converting PDF to PNG for Tesseract to process
我目前遇到 Imagemagick 和 Tesseract 的问题。
我正在为 PHP 中的文档开发命令行分类器。这个想法是它接收 PDF 文档并使用 League Pipeline package 通过许多步骤传递它。我认为必要的步骤如下:
- 将 PDF 转换为 PNG 文件
- 从 PNG 文件中提取文本
- 运行 通过机器学习库对文本进行分类
主要命令如下所示:
<?php
namespace Matthewbdaly\LetterClassifier\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use League\Pipeline\Pipeline;
use Matthewbdaly\LetterClassifier\Stages\ConvertPdfToPng;
use Matthewbdaly\LetterClassifier\Stages\ReadFile;
class Processor extends Command
{
protected function configure()
{
$this->setName('process')
->setDescription('Processes a file')
->setHelp('This command processes a file')
->addArgument('file', InputArgument::REQUIRED, 'File to process');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$file = $input->getArgument('file');
$pipeline = (new Pipeline)
->pipe(new ConvertPdfToPng)
->pipe(new ReadFile);
$pipeline->process($file);
}
}
如您所见,它接受文件名作为第一个参数,然后在将文件传递到管道之前为所需的步骤定义管道。
转换 PDF 的步骤如下所示:
<?php
namespace Matthewbdaly\LetterClassifier\Stages;
use Imagick;
class ConvertPdfToPng
{
public function __invoke($file)
{
$tmp = tmpfile();
$uri = stream_get_meta_data($tmp)['uri'];
$img = new Imagick($file);
$img->setResolution(300, 300);
$img->setImageDepth(8);
$img->setImageFormat('png');
$img->writeImage($uri);
return $tmp;
}
}
它将 PDF 的 PNG 版本写入临时文件。生成的文件看起来不错,至少在我看来是这样,但 Tesseract 无法正确读取它。这是 Tesseract 应该处理文件的第二步:
<?php
namespace Matthewbdaly\LetterClassifier\Stages;
use thiagoalessio\TesseractOCR\TesseractOCR;
class ReadFile
{
public function __invoke($file)
{
$uri = stream_get_meta_data($file)['uri'];
$ocr = new TesseractOCR($uri);
$output = $ocr->lang('eng')->run();
eval(\Psy\Sh());
}
}
Psysh 的输出如下所示:
=> """
Am sum\n
\n
mm“ m mun SuHrkw-l\n
n m 51mm\n
\n
mm\n
\n
um um\n
\n
ms Murine\n
1 Elm: 51mm\n
Emnuumn\n
\n
a mu\n
\n
m Mm 2m-\n
Dav st-n-m.\n
\n
P‘Eualanfl ma lumnflarvlmamrmy ”Hay ”mum-m-\n
we we “mum-m n: "mum,“ m mun\n
\n
vm [harem\n
\n
Am smrm
"""
这不是我要分类的信件的内容 - 文本被损坏了。如果我 运行 来自 shell 的以下命令,它们会按预期工作,将字母的文本转换并写入输出文件:
convert -density 300 Quote.pdf output.png
tesseract output.png output
如果我在 Tesseract 阶段对文件路径进行硬编码以指向使用 convert
命令生成的 output.png
,那是可行的。所以我相当有信心问题出在生成 PNG 文件的步骤上。我没有使用 Imagemagick 的经验,所以我不确定为什么无法处理该文件,但似乎缺少某种设置。
任何人都可以提出可能是什么问题吗?
我怀疑问题是 Imagick 在您调用 setResolution()
之前读取了 PDF。
尝试实例化一个空的 IMagick 对象,设置分辨率,然后读取文件:
$img = new Imagick();
$img->setResolution(300, 300);
$img->readImage($file);
我目前遇到 Imagemagick 和 Tesseract 的问题。
我正在为 PHP 中的文档开发命令行分类器。这个想法是它接收 PDF 文档并使用 League Pipeline package 通过许多步骤传递它。我认为必要的步骤如下:
- 将 PDF 转换为 PNG 文件
- 从 PNG 文件中提取文本
- 运行 通过机器学习库对文本进行分类
主要命令如下所示:
<?php
namespace Matthewbdaly\LetterClassifier\Commands;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use League\Pipeline\Pipeline;
use Matthewbdaly\LetterClassifier\Stages\ConvertPdfToPng;
use Matthewbdaly\LetterClassifier\Stages\ReadFile;
class Processor extends Command
{
protected function configure()
{
$this->setName('process')
->setDescription('Processes a file')
->setHelp('This command processes a file')
->addArgument('file', InputArgument::REQUIRED, 'File to process');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$file = $input->getArgument('file');
$pipeline = (new Pipeline)
->pipe(new ConvertPdfToPng)
->pipe(new ReadFile);
$pipeline->process($file);
}
}
如您所见,它接受文件名作为第一个参数,然后在将文件传递到管道之前为所需的步骤定义管道。
转换 PDF 的步骤如下所示:
<?php
namespace Matthewbdaly\LetterClassifier\Stages;
use Imagick;
class ConvertPdfToPng
{
public function __invoke($file)
{
$tmp = tmpfile();
$uri = stream_get_meta_data($tmp)['uri'];
$img = new Imagick($file);
$img->setResolution(300, 300);
$img->setImageDepth(8);
$img->setImageFormat('png');
$img->writeImage($uri);
return $tmp;
}
}
它将 PDF 的 PNG 版本写入临时文件。生成的文件看起来不错,至少在我看来是这样,但 Tesseract 无法正确读取它。这是 Tesseract 应该处理文件的第二步:
<?php
namespace Matthewbdaly\LetterClassifier\Stages;
use thiagoalessio\TesseractOCR\TesseractOCR;
class ReadFile
{
public function __invoke($file)
{
$uri = stream_get_meta_data($file)['uri'];
$ocr = new TesseractOCR($uri);
$output = $ocr->lang('eng')->run();
eval(\Psy\Sh());
}
}
Psysh 的输出如下所示:
=> """
Am sum\n
\n
mm“ m mun SuHrkw-l\n
n m 51mm\n
\n
mm\n
\n
um um\n
\n
ms Murine\n
1 Elm: 51mm\n
Emnuumn\n
\n
a mu\n
\n
m Mm 2m-\n
Dav st-n-m.\n
\n
P‘Eualanfl ma lumnflarvlmamrmy ”Hay ”mum-m-\n
we we “mum-m n: "mum,“ m mun\n
\n
vm [harem\n
\n
Am smrm
"""
这不是我要分类的信件的内容 - 文本被损坏了。如果我 运行 来自 shell 的以下命令,它们会按预期工作,将字母的文本转换并写入输出文件:
convert -density 300 Quote.pdf output.png
tesseract output.png output
如果我在 Tesseract 阶段对文件路径进行硬编码以指向使用 convert
命令生成的 output.png
,那是可行的。所以我相当有信心问题出在生成 PNG 文件的步骤上。我没有使用 Imagemagick 的经验,所以我不确定为什么无法处理该文件,但似乎缺少某种设置。
任何人都可以提出可能是什么问题吗?
我怀疑问题是 Imagick 在您调用 setResolution()
之前读取了 PDF。
尝试实例化一个空的 IMagick 对象,设置分辨率,然后读取文件:
$img = new Imagick();
$img->setResolution(300, 300);
$img->readImage($file);