Ocrideu is our JavaScript library for reading the machine-readable data of European identity documents: the MRZ of ICAO 9303 documents, plus the QR codes and barcodes some documents carry instead. Version 2.0 is available now on npm:

npm i @tuchsoft/ocrideu

What's new

  • Passports. The MRZ extractor reads all three ICAO formats now, not just the three-line TD1 of ID cards: TD2 (two lines of 36 characters) and TD3 (two lines of 44), which is the passport format. The German D issuing state is recognised too.
  • A crop that no longer destroys the page. The optimiser used to warp whatever contour it found to the proportions of an ID-1 card. On a passport page that contour is often the rectangle around the portrait photograph, and warping it shredded the page and the MRZ with it. The warp now happens only when the detected contour really looks like a card.
  • Side detection from the portrait. The library reports whether it received the front or the back of the document. It used to decide that from any detected face, and a hologram produces plenty of those. A face now counts as the holder's portrait only when it is high-confidence or sits in the left portrait zone.
  • No more fatal errors. The barcode reader has a fixed-size internal buffer and threw RangeError or ran out of memory on large, unusually proportioned and WebP images. The size we give it is computed now, so it cannot overflow.
  • A structured output. parse() returns one object: { mrz, country, profile, side, codes, is_document, portrait, image, hashes, expired, execution }, with a confidence on the detections and the raw detector evidence available on request.
  • Everything stays configurable. MRZ, image optimisation, QR, barcode, face detection, the detection thresholds and the sections of the output each have their own options, and every stage can be switched off.

Before and after

Measured on the two test sets we use for this library, comparing 2.0 with 1.1.5 on the same images:

Main set, 98 images1.1.52.0
Document side66.7%98.5%
MRZ recognised71.2%83.6%
QR recall (mean)0%85.7%
Barcode recall (mean)50.0%76.2%
is_document accuracynot measured95.9%
Fatal errors50
Difficult frames, 57 images1.1.52.0
MRZ recognised14.8%63.0%
MRZ text similarity0.120.54
MRZ exact readings04
Document side29.4%64.7%
Fatal errors100

A note on the size of those sets: a few hundred images is what it takes to catch the failures that matter, and it is not a large corpus. The numbers above are relative to the previous release, on our own images, and that is the claim they support. The improvements come from two kinds of work: real defects (the crop, the crashes, the hologram faces) and reading codes from the original grayscale in addition to the optimised image. The dataset itself is not fully publishable (some of the frames are licence-restricted or personal), so what the repository carries is the manifests and the ground truth, not every picture.

What each capability costs

Same main set, 98 images, one image per process:

Configurationmeanmedianp95
default, everything on3.56 s3.30 s5.05 s
face detection off3.33 s3.23 s4.58 s
QR off3.62 s3.32 s4.80 s
barcode off1.22 s0.94 s2.77 s
barcode "try hard" mode off2.22 s1.99 s3.55 s
MRZ only, code readers off1.13 s0.85 s2.54 s

QR and face detection are close to free. Barcode scanning is not: it is almost the whole difference between a 3.5-second image and a 1.2-second one, and most of that is the aggressive retry mode that exists to rescue difficult codes. If you only need the MRZ, you are paying a third of the price. Which row is right depends on the use, so the library exposes the choice rather than making it.

Breaking change

parse() had a flat result in 1.x and returns a structured object in 2.0. There is no compatibility mode: the fields moved, and the new object groups them by what they are.

// 1.x
import { parse } from '@tuchsoft/ocrideu';
const result = await parse(image);
console.log(result.mrz, result.barcodes);

// 2.0
const { mrz, codes, side, is_document } = await parse(image);
console.log(mrz, codes, side, is_document);

Beyond the moved fields, the object carries the issuing country, a profile of what could be inferred about the document, a confidence on each detection, and execution, the per-stage timings.

What it does not do

  • The side, the document verdict and the portrait are heuristics over independent evidence, not a trained model. They report a confidence and can be wrong on unusual documents.
  • Document detection is the weakest part. The signals that fire on a genuinely weak document are the same ones that fire on a landscape photograph with a card-shaped horizon, which is why it is a routing hint and not a gate.
  • It reads what is already encoded on the document. It does not read the printed fields and it does not verify authenticity, so it is not an identity check.

Install

npm i @tuchsoft/ocrideu

Package: @tuchsoft/ocrideu · Source: github.com/TuchSoft/ocrideu · Licence: Apache-2.0. The 1.1.5 build is still the reference for the comparison above and remains available on npm.