Odborný článok

Extrakcia textu PDF v poradí štruktúry v Delphi s HotPDF

Každý geometrický extraktor textu háda. Číta glyfy, ktoré stránka kreslí, triedi ich podľa baseline a horizontálnej pozície a dúfa, že vizuálne usporiadanie zodpovedá poradiu, v akom by čítal človek. Pri jednostĺpcovej správe je ten tip správny. Pri dvojstĺpcovom článku z časopisu, formulári s bočným panelom alebo tabuľke, ktorej bunky boli emitované stĺpec po stĺpci, je zlý spôsobmi, ktoré sa ťažko všimnú a sú drahé objaviť po prúde. HotPDF na to odpovedá ExtractLoadedPageStructureText, ktorý ignoruje geometriu úplne: prechádza strom štruktúry dokumentu v poradí autorstva, ako ho definuje ISO 32000-1 §14.8.4, a potom znovu skladá glyfy strany podľa ich marked-content identifikátora. Pre tagované PDF to nie je heuristika, je to poradie, ktoré produkujúca aplikácia deklarovala

Funkcia vracia False, keď strana nemá použiteľný strom štruktúry, čo je signál prepadnúť na geometrický extraktor, nie zlyhať. Tento dvojcestný návrh je dôležitejší než algoritmus: reálny príjem dokumentov vidí tagované vládne formuláre a výstup skenerov v tom istom priečinku a pipeline, ktorá zvláda len jeden z nich, nie je pipeline

Prečo geometrická extrakcia mylí poradie čítania?

Pretože content stream PDF nenesie žiadne poradie čítania. Je to sekvencia kresliacich operátorov a producent je slobodný emitovať ich v akejkoľvek sekvencii, ktorá sedí jeho vlastnému layout enginu. Textové procesory zvyčajne emitujú v poradí toku a geometrické triedenie vyzerá dobre. Layout nástroje, návrhári formulárov a generátory správ často nie: pätička strany sa môže emitovať pred telom, tabuľka sa môže plniť po stĺpcoch a dvojstĺpcová strana môže prelínať riadky z oboch stĺpcov, pretože skladateľ ich rozriesil spolu

Porovnanie dvojstĺpcovej strany PDF ukazujúce geometrickú extrakciu triedenú podľa baseline spájajúcu stĺpce oproti extrakcii MCID v poradí štruktúry v HotPDF
Triedenie glyfov podľa baseline prelíná dva stĺpce do nesmyslu, zatiaľ čo strom štruktúry prehráva poradie, ktoré producent deklaroval

Režim zlyhania je tichý. Geometrický extraktor nikdy nehlási chybu, len odovzdá späť prózu, ktorej vety sú zlepené z dvoch stĺpcov. Čokoľvek, čo ten text konzumuje — vyhľadávací index, mapovač polí e-faktúr, retrieval pipeline kŕmiaci jazykový model — dedí škodu bez varovania. HotPDF dodáva aj geometrické extraktory pre načítané dokumenty a tie zostávajú správnym nástrojom pre netagované súbory; zmysel cesty v poradí štruktúry je prestať hádať, keď dokument už odpoveď nesie

Čo strom štruktúry skutočne uchováva

Tagované PDF uchováva druhý, paralelný popis strany. Katalóg ukazuje na /StructTreeRoot, ktorej deti /K tvoria strom prvkov štruktúry: /Document, /Sect, /P, /Table, /TR, /TD a ďalšie. Listy toho stromu sú marked-content referencie, celé čísla, ktoré menujú úsek content streamu strany. Na strane obsahu sa tie úseky otvárajú operátorom BDC nesúcim /MCID a zatvárajú s EMC. Každý prvok štruktúry nesie aj položku /Pg menujúcu stranu, ku ktorej patrí, čo umožňuje prechod po stranách v dokumente, ktorej strom štruktúry sa tiahne cez stovky strán

Anatómia stromu štruktúry PDF viažuca prvky StructTreeRoot ako Sect, Table, TR a TD na úseky BDC MCID v content streame strany HotPDF
Listy stromu sú marked-content referencie a každý prvok nesie položku Pg, ktorá nechá prechod filtrovať na aktuálnu stranu

HotPDF prechádza ten strom s hĺbkovým stropom 128 úrovní a filtruje na /Pg, takže prispieva len aktuálna strana. Výstupom prechodu nie je text, je to usporiadaný zoznam hodnôt MCID: poradie autorstva úsekov marked-content na tejto strane. Zloženie textu je potom vecou prehratia glyfov v tom poradí

MCID sa zaznamenáva počas extrakcie glyfov, nie dohľadáva sa potom

Toto je implementačný detail, ktorý robí funkciu lacnou. HotPDF už zaznamenáva aktívny marked-content identifikátor na každom glyfe, ktorý extrahuje, v poli MCID záznamu THPDFGlyphRecord, pretože interpret content streamu vie, ktorý scope BDC je otvorený v momente, keď spracováva každý operátor Tj alebo TJ. Extrakcia v poradí štruktúry preto nepotrebuje druhý prechod cez content stream. Zbiera sekvenciu MCID zo stromu štruktúry, potom roztriedi už extrahované glyfy podľa MCID a emituje ich v tej sekvencii

var
  Pdf: THotPDF;
  PageCount, I, Untagged: Integer;
  PageText, AllText: UnicodeString;
  Report: TStrings;   // diagnostická zbierka vo vlastníctve volajúceho
begin
  Pdf := THotPDF.Create(nil);
  try
    PageCount := Pdf.LoadFromFile('accessible-form.pdf');
    AllText := '';
    for I := 0 to PageCount - 1 do
    begin
      if Pdf.ExtractLoadedPageStructureText(I, PageText, Untagged) then
      begin
        // Poradie autorstva priamo zo stromu štruktúry
        if Untagged > 0 then
          Report.Add(Format('page %d: %d glyphs outside the structure tree',
            [I, Untagged]));
      end
      else
        // Žiadny použiteľný strom štruktúry na tejto strane: geometrický fallback
        Pdf.ExtractLoadedPageText(I, PageText);
      AllText := AllText + PageText + #13#10;
    end;
  finally
    Pdf.Free;
  end;
end;

Netagované glyfy sa počítajú, nikdy sa potichu nezahadzujú

Strana môže byť čiastočne tagovaná. Producenti pridávajú ozdobnú linku, číslo strany alebo neskorší vodoznak mimo akéhokoľvek scope BDC a tie glyfy nepatria žiadnemu MCID. Zahodiť ich by bolo uprataná implementácia a zároveň zlá, pretože rovnaká medzera sa objaví aj vtedy, keď producent taguje telo, ale zabudne tabuľku, a prídete o tabuľku bez toho, aby ste si to všimli

HotPDF pripája nevyžiadané glyfy ako geometrický chvost za textom v poradí štruktúry a hlási ich počet cez výstupný parameter UntaggedGlyphCount. To číslo je kvalitatívny signál, na ktorý možno reagovať. Hŕstka glyfov na strane dvoch tisíc je page furniture a možno ju ignorovať. Štyridsať percent strany mimo stromu štruktúry znamená, že tagovanie je ozdobné a geometrický extraktor je pre ten súbor úprimnejšia odpoveď

Rozhodovací tok extrakcie štruktúrneho textu HotPDF s geometrickým fallbackom, keď strana nemá použiteľný strom štruktúry alebo ozdobné tagovanie
True znamená poradie štruktúry s pripojeným netagovaným chvostom a False smeruje stranu do geometrického extraktora namiesto zlyhania
function ExtractPageBestEffort(Pdf: THotPDF; PageIndex: Integer;
  out AText: UnicodeString; out UsedStructure: Boolean): Boolean;
var
  Untagged, TotalGlyphs: Integer;
  Glyphs: THPDFGlyphArray;
begin
  UsedStructure := False;
  if Pdf.ExtractLoadedPageStructureText(PageIndex, AText, Untagged) then
  begin
    TotalGlyphs := 0;
    if Pdf.ExtractLoadedPageGlyphs(PageIndex, Glyphs) then
      TotalGlyphs := Length(Glyphs);
    // Veriť stromu štruktúry len vtedy, keď si nárokuje väčšinu strany
    if (TotalGlyphs = 0) or (Untagged * 4 <= TotalGlyphs) then
    begin
      UsedStructure := True;
      Result := True;
      Exit;
    end;
  end;
  Result := Pdf.ExtractLoadedPageText(PageIndex, AText);
end;

Čo prinúti funkciu vrátiť False

Tri prípady a stojí za to ich rozlíšiť, pretože len jeden z nich je defektom dokumentu. Prvý je obyčajné netagované PDF: žiadny /StructTreeRoot, nič na prechádzanie a False je jednoducho pravda. Druhý je naskenovaná strana, ktorej text pochádza z OCR vrstvy, ktorá nebola nikdy tagovaná. Tretí je ten zaujímavý: obsah nesúci operátory BDC s hodnotami /MCID, ale jeho strana nemá položku /StructParents a strom štruktúry tie identifikátory nikdy neodkazuje. Marked content existuje, strana štruktúry nie a nie je žiadne poradie na obnovenie. HotPDF hlási False namiesto jedného vymyslieť

Posledný prípad sa objavuje v ručne upravovaných súboroch a vo výstupe nástrojov, ktoré emitujú marked content na účely optional-content či artifact bez budovania stromu štruktúry. Ak sami produkujete tagované PDF, tá istá asymetria je to, čo kontroluje validácia PDF/UA a writer-side náprotivok pokrýva layout DOM emitujúci tagovaný, stránkovaný výstup

Kde sa poradie štruktúry vyplatí

Audit prístupnosti je zjavný: ak certifikujete dokument voči PDF/UA, poradie čítania, ktoré ohlási čítačka obrazovky, je presne poradie štruktúry, takže jeho extrakcia je spôsob, ako ho prezrieť bez čítačky obrazovky. Zber dát je väčší komerčný prípad. Tagované vládne formuláre, regulované zverejnenia a prílohy e-faktúr nesú menovky polí a hodnoty v deklarovanom poradí a ich čítanie v tom poradí odstraňuje celú triedu chýb mapovania, ktoré geometrická extrakcia vytvára na viacstĺpcových usporiadaniach

Najnovším konzumentom je retrieval pre jazykové modely. Chunkovanie dokumentu pre embedding je len také dobré, aké je poradie textu, a chunk, ktorý zlepí dva stĺpce, produkuje vety, ktoré nikdy neexistovali. Extrakcia v poradí štruktúry je najlacnejšia dostupná oprava, pretože pre tagované dokumenty je správne poradie už v súbore a len ho treba prečítať

HotPDF je natívna VCL komponenta pre Delphi a C++Builder, takže prechod stromom štruktúry aj prehrávanie glyfov bežia v procese nad načítaným dokumentom bez zapojenia externého renderera. Kompletné API detaily rodiny extrakcie načítaných dokumentov sú na produktovej stránke HotPDF Delphi PDF component