代码之家  ›  专栏  ›  技术社区  ›  Dmitriy Kisil

Tesseract不识别png文件中的captcha,该文件包含英文字母和数字。

  •  0
  • Dmitriy Kisil  · 技术社区  · 8 年前

    我需要从url中提取captcha并用tesseract识别它。我的代码是:

    #!/usr/bin/perl -X
    ###
    $user = 'user'; #Enter your username here
    $pass = 'pass'; #Enter your password here
    ###
    #Server settings
    $home = "http://perltest.adavice.com";
    $url = "$home/c/test.cgi?u=$user&p=$pass";
    #Get HTML code!
    $html = `GET "$url"`
    ###Add code here!
    #Grab img from HTML code
    if ($html =~ m%img[^>]*src="(/[^"]*)"%s)
    {
        $img = $1;
    }
    ###
    die "<img> not found\n" if (!$img);
    #Download image to server (save as: ocr_me.img)
    print "GET '$home$img' > ocr_me.img\n";
    system "GET '$home$img' > ocr_me.img";
    ###Add code here!
    #Run OCR (using shell command tesseract) on img and save text as ocr_result.txt
    system("tesseract ocr_me.img ocr_result");
    print "GET '$txt' > ocr_result.txt\n";
    system "GET '$txt' > ocr_result.txt";
    ###
    die "ocr_result.txt not found\n" if (!-e "ocr_result.txt");
    # check OCR results:
    $txt = 'cat ocr_result.txt';
    $txt =~ s/[^A-Za-z0-9\-_\.]+//sg;
    $img =~ s/^.*\///;
    print `echo -n "file=$img&text=$txt" | POST "$url"`;
    

    图像分析正确。此图像包含验证码,看起来像:

    My image PNG file, which contains a captcha

    我的输出是:

    GET 'http://perltest.adavice.com/captcha/1533110309.png' > ocr_me.img
    Tesseract Open Source OCR Engine v3.02.02 with Leptonica
    GET '' > ocr_result.txt
    Captcha text not specified
    

    如您所见,脚本正确地解析图像。但是Tesseract在PNG文件中没有看到任何内容。我试图用shell命令tesseract指定其他参数,如-psm和-l,但这也没有给出任何内容。

    更新 :在阅读了答案@dave cross之后,我尝试了他的建议。

    在输出中我得到:

    http://perltest.adavice.com/captcha/1533141024.png
    ocr_me.img
    Tesseract Open Source OCR Engine v3.02.02 with Leptonica
    []
    200Captcha text not specified
    Original image file not specified
    Captcha text not specified
    

    为什么我需要来自image.png的文本?也许这些额外的信息可以帮助你。 看看这个: enter image description here

    这就是$url在浏览器中的样子。这里我的目标是使用Perl在WIM中为这个页面创建查询。为此,我需要填写我的$user、$pass和$txt上面的表单(从Tesseract图像识别)。然后用“url”(代码中的最后一个字符串)发送。

    1 回复  |  直到 8 年前
        1
  •  2
  •   Dave Cross    8 年前

    这里发生了一些奇怪的事情。其中任何一个都可能导致你的问题。

    1. -X 在你的shebang线上是个糟糕的主意。它显式地关闭警告。我建议你移除它,添加 use warnings 在你的代码中修复所有暴露的问题(我建议添加 use strict 同样,但是您需要声明所有的变量)。
    2. 我建议使用 LWP::Simple 而不是炮击 GET .
    3. 请不要使用regex解析HTML。而是使用真正的HTML解析器。 Web::Query 是我现在的最爱。
    4. 你就跑吧 得到 同样,使用一个名为 $txt 那没有价值。那不管用!
    5. $txt = 'cat ocr_result.txt' 不会像你想象的那样。你需要的是反勾号,而不是单引号。

    更新: 显然,我没有访问您的用户名或密码的权限,因此我无法重建您的所有代码。但对于访问示例中的图像并从中提取文本来说,这似乎是可行的。

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    use feature 'say';
    
    use LWP::Simple;
    
    my $img_url  = 'http://perltest.adavice.com/captcha/1533110309.png';
    my $img_file = 'ocr_me.img';
    
    getstore($img_url, $img_file);
    
    my $txt = `tesseract $img_file stdout`;
    
    say $txt;
    

    这是您的实际错误:

    system("tesseract ocr_me.img ocr_result");
    print "GET '$txt' > ocr_result.txt\n";
    system "GET '$txt' > ocr_result.txt";
    

    你问我 tesseract 将其输出写入 ocr_result.txt ,但两行之后,您将使用对的失败调用的输出覆盖该文件。 得到 . 我不知道你会怎么想,但它会把输出的任何东西都弄脏。 特瑟拉克特 已经存储在该文件中。

    更新的更新:

    这是我当前版本的代码:

    #!/usr/bin/perl
    use strict;
    use warnings;
    use feature 'say';
    use LWP::Simple qw[$ua get getstore];
    use File::Basename;
    ###
    my $user = 'xxxx'; #Enter your username here
    my $pass = 'xxxx'; #Enter your password here
    ###
    #Server settings
    my $home = "http://perltest.adavice.com";
    my $url = "$home/c/test.cgi?u=$user&p=$pass";
    #Get HTML code!
    my $html = get($url);
    my $img;
    ###Add code here!
    #Grab img from HTML code
    if ($html =~ m%img[^>]*src="(/[^"]*)"%s)
    {
        $img = $1;
    }
    my $img_url = $home . $img;
    my $img_file = 'ocr_me.img';
    
    getstore($img_url, $img_file);
    
    say $img_url;
    say $img_file;
    
    # Looks like tesseract adds two newlines to its output -
    # so chomp() it twice!
    chomp(my $txt = `tesseract ocr_me.img stdout`);
    chomp($txt);
    
    say "[$txt]";
    
    $txt =~ s/\W+//g;
    
    my $resp = $ua->post($url, {
      u    => $user,
      p    => $pass,
      file => basename($img),
      text => $txt,
    });
    
    print $resp->code;
    print $resp->content;
    

    我改变了一些事情。

    1. 已更正 $img_url $url . $img $home . $img (这就是阻止它获得正确图像的原因)。
    2. 切换到使用lwp::simple-through(这很简单)。
    3. chomp Ed(两次!)输出来自 特瑟拉克特 删除换行符。
    4. 使用file::basename获取要在最终版本中传递的正确文件名 POST .
    5. 已从中删除任何非文字字符 $TXT 之前 就这样。

    它仍然不太管用。它似乎挂起等待服务器的响应。但恐怕我没时间帮你了。