windows - Windows 上的 Perl Image::OCR::Tesseract 模块

标签 windows perl tesseract

有人知道在 Windows 上安装“Image::OCR::Tesseract”模块的优雅方法吗?由于名为“LEOCHARRE::CLI”的仅 *NIX 模块依赖性,该模块无法通过 CPAN 在 Windows 上安装。该模块似乎不需要运行“Image::OCR::Tesseract”本身。

我通过首先手动安装 makefile.pl 中列出的依赖模块(“LEOCHARRE::CLI”除外),然后将模块文件移动到“C”下的正确目录结构,设法让模块工作:\Perl\site\lib\Image\OCR”。让它工作的最后一部分是更改从命令行调用 ImageMagick 和 Tesseract 可执行文件的代码部分,以便在模块调用可执行文件时在程序名称周围加上引号。

这行得通,但我真的觉得从适用于 Windows 的存储库在生产系统上安装 PPM 或 CPAN 会更好。

最佳答案

没关系,我明白了,虽然我不能决定什么是更好的解决方案。

要让安装程序通过传统的“perl makefile.pl、make、make test、make install”例程在 Windows 上运行,需要编辑 Makefile.pl 脚本,包括缺少的 Windows 安装模块(Devel::AssertOS::MSWin32),并修补 AssertEXE.pm 以使用“File::Which”而不是 Windows 缺少的内置 shell“which”命令。所有这一切仍然需要对“Image::OCR::Tesseract”进行修补,以便在从命令行执行“convert”和“tesseract”时在程序名称周围加上引号。

考虑到使安装程序在 Windows 上运行所涉及的步骤数量,以及模块不会为模块创建二进制组件以链接到的事实,我认为安装和运行 Tesseract 模块的最佳选择在 Windows 上将首先安装以下二进制包:

图像魔术 Link

正方体 http://code.google.com/p/tesseract-ocr/downloads/list

接下来,找到您的 Perl 模块目录 - 在我的系统上它是“C:\Perl\site\lib”。如果没有,请创建一个文件夹“Image”。接下来,打开图像文件夹并创建一个名为“OCR”的文件夹。打开 OCR 文件夹。此时,您的路径应该类似于“C:\Perl\site\lib\Image\OCR”。创建一个名为“Tesseract.pm”的新文本文件,并复制以下内容...

package Image::OCR::Tesseract;
use strict;
use Carp;
use Cwd;
use String::ShellQuote 'shell_quote';
use Exporter;
use vars qw(@EXPORT_OK @ISA $VERSION $DEBUG $WHICH_TESSERACT $WHICH_CONVERT %EXPORT_TAGS @TRASH);
@ISA = qw(Exporter);
@EXPORT_OK = qw(get_ocr get_hocr _tesseract convert_8bpp_tif tesseract);
$VERSION = sprintf "%d.%02d", q$Revision: 1.24 $ =~ /(\d+)/g;
%EXPORT_TAGS = ( all => \@EXPORT_OK );


BEGIN {
   use File::Which 'which';
   $WHICH_TESSERACT = which('tesseract');
   $WHICH_CONVERT   = which('convert');
   
   if($^O=~m/MSWin/) {
      $WHICH_TESSERACT='"'.$WHICH_TESSERACT.'"';
      $WHICH_CONVERT='"'.$WHICH_CONVERT.'"';
   }
   $WHICH_TESSERACT or die("Is tesseract installed? Cannot find bin path to tesseract.");
   $WHICH_CONVERT or die("Is convert installed? Cannot find bin path to convert.");
}

END {
   scalar @TRASH or return;
   if ( $DEBUG ){
      print STDERR "Debug on, these are trash files:\n".join("\n",@TRASH) ;
   }
   else {
      unlink @TRASH;
   }
}

sub DEBUG { Carp::cluck("Image::OCR::Tesseract::DEBUG() deprecated") }

sub get_hocr {
   my ($abs_image,$abs_tmp_dir,$lang)= @_;
   -f $abs_image or croak("$abs_image is not a file on disk");
   my $hocr="hocr";
   if(defined $abs_tmp_dir){

      -d $abs_tmp_dir or die("tmp dir arg $abs_tmp_dir not a dir on disk.");

      $abs_image=~/([^\/]+)$/ or die("cant match filename in path arg '$abs_image'");
      my $abs_copy = "$abs_tmp_dir/$1";

      # TODO, what if source and dest are same, i want it to die
      require File::Copy;
      File::Copy::copy($abs_image, $abs_copy) 
         or die("cant make copy of $abs_image to $abs_copy, $!");

      # change the image to get ocr from to be the copy
      $abs_image = $abs_copy;
      # since it's a copy. erase that on exit
      push @TRASH, $abs_image;      
   }

   my $tmp_tif = convert_8bpp_tif($abs_image);
   
   push @TRASH, $tmp_tif; # for later delete

   _tesseract($tmp_tif,$lang,$hocr) || '';
}

sub get_ocr {
   my ($abs_image,$abs_tmp_dir,$lang)= @_;
   -f $abs_image or croak("$abs_image is not a file on disk");
   if(defined $abs_tmp_dir){

      -d $abs_tmp_dir or die("tmp dir arg $abs_tmp_dir not a dir on disk.");

      $abs_image=~/([^\/]+)$/ or die("cant match filename in path arg '$abs_image'");
      my $abs_copy = "$abs_tmp_dir/$1";

      # TODO, what if source and dest are same, i want it to die
      require File::Copy;
      File::Copy::copy($abs_image, $abs_copy) 
         or die("cant make copy of $abs_image to $abs_copy, $!");

      # change the image to get ocr from to be the copy
      $abs_image = $abs_copy;
      # since it's a copy. erase that on exit
      push @TRASH, $abs_image;      
   }

   my $tmp_tif = convert_8bpp_tif($abs_image);
   
   push @TRASH, $tmp_tif; # for later delete

   _tesseract($tmp_tif,$lang) || '';
}

sub convert_8bpp_tif {
   my ($abs_img,$abs_out) = (shift,shift);
   defined $abs_img or die('missing image arg');

   $abs_out ||= $abs_img.'.tmp.'.time().(int rand(9000)).'.tif';
   
   my @arg = ( $WHICH_CONVERT, $abs_img, '-compress','none','+matte', $abs_out );
   
   #die (join(" ", @arg));
   
   system(@arg) == 0 or die("convert $abs_img error.. $?");

   $DEBUG and warn("made $abs_out 8bpp tiff.");
   $abs_out;
}



# people expect tesseract to automatically convert

*tesseract = \&_tesseract;
sub _tesseract {
    my ($abs_image,$lang,$hocr) = @_;
   defined $abs_image or croak('missing image path arg');
   
   $abs_image=~/\.tif+$/i or warn("Are you sure '$abs_image' is a tif image? This operation may fail.");
   
   #my @arg = (
   #   $WHICH_TESSERACT, shell_quote($abs_image), shell_quote($abs_image), 
   #   (defined $lang and ('-l', $lang) ), '2>/dev/null'
   #); 

   my $cmd = 
      ( sprintf '%s %s %s', 
         $WHICH_TESSERACT, 
         shell_quote($abs_image), 
         shell_quote($abs_image) 
      ) .
      ( defined $lang ? " -l $lang" : '' ) .
      ( defined $hocr ? " hocr" : '' ) .
      "  2>/dev/null";
   $DEBUG and warn "command: $cmd";

    system($cmd); # hard to check ==0 

    my $txt = $abs_image.($hocr?".html":".txt");
   unless( -f $txt ){      
        Carp::cluck("no text output for image '$abs_image'. (No text file '$txt' found on disk)");
      return;
   }

    $DEBUG and warn "Found text file '$txt'";
   
   my $content = (_slurp($txt) || '');   
   $DEBUG and warn("content length of text in '$txt' from image '$abs_image' is ". length $content );
   push @TRASH, $txt;

   $content;
}

sub _slurp {
   my $abs = shift;
   open(FILE,'<', $abs) or die("can't open file for reading '$abs', $!");
   local $/;
   my $txt = <FILE>;
   close FILE;
   $txt;
}  

1;


__END__

#sub _force_imgtype {
#   my $img = shift;
#   my $type = shift;
#   my $delete_original = shift;
#   $delete_original ||=0;
#   
#
#   if($img=~/\.$type$/i){
#      return $img;
#   }
#
#   my $img_out= $img;
#   $img_out=~s/\.\w{1,5}$/\.$type/ or die("cant get file ext for $img");
#
#
#
#}

保存并关闭。如果您在安装 ImageMagick 和 Tesseract 二进制文件之前打开过命令行 session ,请关闭并打开一个新 session 。使用以下脚本测试模块:

use Image::OCR::Tesseract;
my $image = 'SomeImageFileThatContainsText.jpg';

my $text = Image::OCR::Tesseract::get_ocr($image);

print "Text...\n";
print $text."\n";

print "Normal Exit\n";

exit;

就是这样。困惑,我知道,但没有什么好的方法可以解决这样一个事实,即模块安装程序确实需要更新以支持 Windows(和其他)系统,即使实际模块代码几乎无需修改即可运行。实际上,如果 Tesseract 和 ImageMagick 安装到没有空格的路径,那么“Image::OCR::Tesseract”模块代码不需要任何更改,但这个小调整可以让支持的可执行文件安装在任何地方,包括默认位置。

关于windows - Windows 上的 Perl Image::OCR::Tesseract 模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19431336/

相关文章:

windows - SignerSignEx 用于签署 .exe 文件的示例源代码?

windows - 当记事本不是默认应用程序时,如何从 Windows 资源管理器运行 PowerShell 脚本?

perl - 在没有插件的模板工具包中调用外部子和模块?

perl - 多行搜索替换为 Perl

windows - 如何从图像生成 tiff/box 文件以在 Windows 中训练 Tesseract

python-3.x - 在Python3文本库中使用tesseract

android - 使用 Tesseract 的 OCR Android 应用程序

windows - WSL 可以继承 Windows 身份验证凭据吗

mysql - 如何在没有数字 ID 的情况下从 MySQL 数据库表中获取随机行?

windows - 试图更换;使用 cmd 文件在 txt 文件中使用 ASCII 控制字符