lol

nixos/testing: Improve quality of OCR

First of all, we're now using ImageMagick to improve the screenshot so
that Tesseract has an esier time to recognize the text. The resulting
image of this post-processing is a scaled up black-and-white version
with the backgrounds almost entirely removed and the text edges a bit
blurred, so the screen shots now more or less resemble an image from a
scanner rather. This is what Tesseract is trained for by default.

As mentioned in the previous commit we now also use Tesseract 4, which
further improves the quality of text recognition.

I've spent countless hours just to test different postprocessing
variants and testing what works best for our tests and this is the one
that worked best so far. It's certainly not perfect and I'd like to
avoid the scaling step but we're way better off than before.

In addition to this, the OCR process is now done without an intermediate
file, solely using pipes.

I've tested this using the following VM tests which have OCR enabled:

* nixos/tests/chromium.nix -A stable
* nixos/tests/emacs-daemon.nix
* nixos/tests/installer.nix -A luksroot
* nixos/tests/lightdm.nix
* nixos/tests/plasma5.nix
* nixos/tests/sddm.nix

All of the tests still succeed and comparing some of the recognition
results to the earlier results it now also detects a lot more text than
before this commit.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>

aszlig a443bdc0 7b5263e1

+14 -9
+11 -7
nixos/lib/test-driver/Machine.pm
··· 542 $self->nest("performing optical character recognition", sub { 543 my $tmpbase = Cwd::abs_path(".")."/ocr"; 544 my $tmpin = $tmpbase."in.ppm"; 545 - my $tmpout = "$tmpbase.ppm"; 546 547 $self->sendMonitorCommand("screendump $tmpin"); 548 - system("ppmtopgm $tmpin | pamscale 4 -filter=lanczos > $tmpout") == 0 549 - or die "cannot scale screenshot"; 550 unlink $tmpin; 551 - system("tesseract $tmpout $tmpbase") == 0 or die "OCR failed"; 552 - unlink $tmpout; 553 - $text = read_file("$tmpbase.txt"); 554 - unlink "$tmpbase.txt"; 555 }); 556 return $text; 557 }
··· 542 $self->nest("performing optical character recognition", sub { 543 my $tmpbase = Cwd::abs_path(".")."/ocr"; 544 my $tmpin = $tmpbase."in.ppm"; 545 546 $self->sendMonitorCommand("screendump $tmpin"); 547 + 548 + my $magickArgs = "-filter Catrom -density 72 -resample 300 " 549 + . "-contrast -normalize -despeckle -type grayscale " 550 + . "-sharpen 1 -posterize 3 -negate -gamma 100 " 551 + . "-blur 1x65535"; 552 + my $tessArgs = "-c debug_file=/dev/null --psm 11 --oem 2"; 553 + 554 + $text = `convert $magickArgs $tmpin tiff:- | tesseract - - $tessArgs`; 555 + my $status = $? >> 8; 556 unlink $tmpin; 557 + 558 + die "OCR failed with exit code $status" if $status != 0; 559 }); 560 return $text; 561 }
+3 -2
nixos/lib/testing.nix
··· 93 94 vms = map (m: m.config.system.build.vm) (lib.attrValues nodes); 95 96 - ocrProg = tesseract.override { enableLanguages = [ "eng" ]; }; 97 98 # Generate onvenience wrappers for running the test driver 99 # interactively with the specified network, and for starting the ··· 111 vms=($(for i in ${toString vms}; do echo $i/bin/run-*-vm; done)) 112 wrapProgram $out/bin/nixos-test-driver \ 113 --add-flags "''${vms[*]}" \ 114 - ${lib.optionalString enableOCR "--prefix PATH : '${ocrProg}/bin'"} \ 115 --run "testScript=\"\$(cat $out/test-script)\"" \ 116 --set testScript '$testScript' \ 117 --set VLANS '${toString vlans}'
··· 93 94 vms = map (m: m.config.system.build.vm) (lib.attrValues nodes); 95 96 + ocrProg = tesseract_4.override { enableLanguages = [ "eng" ]; }; 97 98 # Generate onvenience wrappers for running the test driver 99 # interactively with the specified network, and for starting the ··· 111 vms=($(for i in ${toString vms}; do echo $i/bin/run-*-vm; done)) 112 wrapProgram $out/bin/nixos-test-driver \ 113 --add-flags "''${vms[*]}" \ 114 + ${lib.optionalString enableOCR 115 + "--prefix PATH : '${ocrProg}/bin:${imagemagick}/bin'"} \ 116 --run "testScript=\"\$(cat $out/test-script)\"" \ 117 --set testScript '$testScript' \ 118 --set VLANS '${toString vlans}'