HotPDF poganja Tesseract znotraj vašega procesa Delphi skozi HPDFCreateTesseractDLLOCREngine, tovarno, dodano v v2.772.0, ki dinamično naloži DLL, skladen s Tesseract 5, poganja njegov C API (TessBaseAPIInit2, TessBaseAPIRecognize, iterator rezultatov) in vrne IHPDFOCREngine. THotPDF.ApplyLoadedOCRTextLayer uporabi ta motor, da skeniranim stranem PDF doda nevidno, iskalno plast besedila Unicode
Isti prepoznavalec je bil že dosegljiv skozi zunanji adapter tesseract.exe, ki zapiše BMP in razčleni TSV. Ta pot dela, vsaka stran pa plača zagon procesa, začasno bitno-slikovno datoteko in besedilni format brez osnovnih črt in brez nadzora nad segmentacijo strani. Klicanje DLL-ja odstrani vse tri. Odstrani tudi procesno steno, kar pomeni, da vezava Pascal leži neposredno na strukturi C, predznaken C in nizih, dodeljenih s strani C. Večina tega, kar je vredno vedeti o tem adapterju, so mesta, kjer lahko ta vezava tiho zgreši
Kako poganjate Tesseract v procesu iz Delphija s HotPDF?
Poganjanje Tesseract v procesu s HotPDF vzame en klic tovarne v enoti HPDFTesseractRecognition in isti klic ApplyLoadedOCRTextLayer, ki ga uporablja vsak OCR motor HotPDF. Tovarna potrjuje nemudoma. Datoteka DLL in imenik tessdata morata obstajati, jezikovni identifikator sme vsebovati samo črke ASCII, številke, _ in +, vsak model v kombinaciji, kot je chi_sim+eng, mora imeti ujemajočo datoteko .traineddata, vsi 21 zahtevanih izvozov pa se morajo razrešiti, preden je motor vrnjen. Napake nastavitve javijo EArgumentException; DLL, ki se ne naloži, javi EOSError s kodo napake Windows in namigom, da preverite arhitekturo in odvisnosti
uses
SysUtils, HPDFDoc, HPDFTesseractRecognition;
procedure MakeSearchable(const SourceFile, TargetFile: string);
var
Doc: THotPDF;
Engine: IHPDFOCREngine;
Options: THPDFOCRTextLayerOptions;
Info: THPDFOCRTextLayerInfo;
begin
// Aplikacija Win64 potrebuje 64-bitni DLL; odvisnostne DLL-je postavite ob njega
Engine := HPDFCreateTesseractDLLOCREngine('C:\OCR\Win64\libtesseract-5.dll',
'C:\OCR\tessdata', 'chi_sim+eng'); // THPDFTesseractOptions.Default
Doc := THotPDF.Create(nil);
try
Doc.AutoLaunch := False;
if Doc.LoadFromFile(SourceFile) < 1 then
raise Exception.Create('Cannot load ' + SourceFile);
Options := THPDFOCRTextLayerOptions.Default; // 300 DPI, MinimumConfidence 0.5
// Prazen seznam strani pomeni vsako stran; strani z že obstoječim besedilom se preskočijo
if not Doc.ApplyLoadedOCRTextLayer([], Engine, Options, Info) then
raise Exception.Create(string(Info.Diagnostic));
Writeln(string(Info.EngineName), ': ', Info.AcceptedWordCount,
' words accepted, ', Info.DroppedWordCount, ' dropped');
Doc.SaveLoadedDocument(TargetFile);
finally
Doc.Free;
end;
end;
THPDFTesseractOptions.Default nastavi PageSegMode na tpsAuto, EngineMode na temDefault, TimeoutMilliseconds na 60.000 in MaxPixels na 16.777.216. Pikslovni proračun šteje več, kot izgleda. Stran US Letter pri privzetih 300 DPI se izriše v 2.550 × 3.300 pikslov, približno 8,4 milijona, kar gre noter. Ista stran pri 600 DPI je 5.100 × 6.600, približno 33,7 milijona, adapter pa jo zavrne, preden Tesseract vidi piksel. Dvignite MaxPixels (strop je 67.108.864) ali pustite DPI, kjer je; vsaka stranica je tudi stisnjena na 32.767 pikslov
DLL se naloži z LoadLibraryEx z iskalnimi zastavicami za lastno mapo DLL plus privzete varne imenike, tako da lahko slikovne knjižnice, od katerih je odvisen Tesseract, živijo ob njem, brez dotikanja PATH ali trenutnega imenika. HotPDF ne priloži ne prenese nobenega izvajalnega okolja ali modela OCR; oboje preskrbite sami
Kaj se spremeni v primerjavi z adapterjem tesseract.exe?
DLL adapter odstopi izolacijo procesov za bogatejši izhod in nižje stroške na stran. Oba adapterja se priključita na isti cevovod plasti besedila, tako da sta preslikava koordinat, filtriranje zaupanja in zapis vse-ali-nič identični; razlikuje se, kako piksli gredo noter in besede ven
| Vid | Adapter tesseract.exe | Adapter DLL Tesseract |
|---|---|---|
| Tovarna | HPDFCreateTesseractOCREngine | HPDFCreateTesseractDLLOCREngine |
| Piksli noter | Datoteka BMP v zasebnem začasnem imeniku | Predpomnilnik 8-bitnih sivin v pomnilniku |
| Besede ven | TSV na ravni besed, omejen na 64 MiB | Iterator rezultatov, UTF-8 na besedo |
| Osnovne črte | Ni na voljo | Podane naprej iz TessPageIteratorBaseline |
| Segmentacija strani in način motorja | Samo samodejna segmentacija | THPDFTesseractPageSegMode, THPDFTesseractEngineMode |
| Zakasnitev | Trda: podrejeni proces je ubit | Sodelovalna: Tesseract ga mora opaziti |
| Izolacija sesutja in pomnilnika | Ločen proces | Brez, si deli vaš naslovni prostor |
Ena cena ne izgine. Vsak klic Recognize ustvari svojo instanco API in pokliče TessBaseAPIInit2, tako da se jezikovni modeli inicializirajo na stran, namesto enkrat na motor. Datotečni predpomnilnik operacijskega sistema zmehča ponovno nalaganje, pri velikih večjezičnih naborih modelov pa je še vedno prevladujoča fiksna cena na stran in šteje proti roku prepoznavanja. Motor DLL RapidOCR v procesu vzame obratno zasnovo in drži svoje modele ONNX v pomnilniku za življenje motorja; težave na meji (C ABI, posojeni predpomnilniki, neprekinljivo native delo) pa so ista družina
Zakaj Delphi ne more kopirati strukture monitorja Tesseract?
Delphi ne more varno zrcaliti monitorja napredka Tesseract, ker ETEXT_DESC vsebuje različico-odvisna notranja polja, tako da ročno prepisan zapis postavi callback preklica in rok na napačne odmike na nekaterih izgradnjah. Nič ne odpove glasno, ko se to zgodi. Tesseract preprosto prebere vaš kazalec callback iz polja, ki zdaj drži kaj drugega, ali pa rok sploh nikoli ne vidi
HotPDF zato monitor obravnava kot neprozoren kazalec in se ga dotika samo skozi izvožene funkcije: TessMonitorCreate, TessMonitorSetCancelThis, TessMonitorSetCancelFunc, TessMonitorSetDeadlineMSecs in TessMonitorDelete. Če C API vežete sami za drug namen, velja isti vzorec. Skica spodaj je vaša lastna koda vezave, ne API HotPDF, in zrcali deklaracije, ki jih HotPDF uporablja interno
type
// C: typedef bool (*TessCancelFunc)(void *cancel_this, int words);
TTessCancelFunc = function(CancelThis: Pointer; Words: Integer): Boolean; cdecl;
TTessMonitorCreate = function: Pointer; cdecl; // ETEXT_DESC*, nikoli dereferenciran
TTessMonitorDelete = procedure(Monitor: Pointer); cdecl;
TTessMonitorSetCancelFunc = procedure(Monitor: Pointer; Func: TTessCancelFunc); cdecl;
TTessMonitorSetCancelThis = procedure(Monitor, CancelThis: Pointer); cdecl;
TTessMonitorSetDeadlineMSecs = procedure(Monitor: Pointer; MSecs: Integer); cdecl;
TTessBaseAPIRecognize = function(Handle, Monitor: Pointer): Integer; cdecl;
TOCRJob = record
CancelRequested: Boolean;
DeadlineTick: UInt64;
end;
POCRJob = ^TOCRJob;
function ShouldCancel(CancelThis: Pointer; Words: Integer): Boolean; cdecl;
begin
// Teče na skladu Tesseract: branje zastavic in ure, nikoli izjeme
Result := (CancelThis = nil) or POCRJob(CancelThis)^.CancelRequested or
(GetTickCount64 >= POCRJob(CancelThis)^.DeadlineTick);
end;
// Uporaba, s kazalci funkcij, razrešenimi z GetProcAddress:
// Monitor := MonitorCreate();
// try
// MonitorSetCancelThis(Monitor, @Job);
// MonitorSetCancelFunc(Monitor, ShouldCancel);
// MonitorSetDeadlineMSecs(Monitor, RemainingMs);
// RC := BaseAPIRecognize(API, Monitor);
// finally
// MonitorDelete(Monitor);
// end;
Dve podrobnosti te skice sta namerni. Callback vrne Boolean, ki je en bajt tako v Delphiju kot v Free Pascalu, kar se ujema s C bool v TessCancelFunc. Štiribajtni Windows BOOL ali Delphi LongBool je videti zamenljiv in ni: kadar ena stran zapiše en bajt in druga bere štiri, so zgornji bajti vrnilnega registra karkoli je tam ostalo, in false lahko prispe kot true. Isti glavni stvari dodatno zaplete, ker funkcije, kot je TessPageIteratorBoundingBox, vrnejo int, ki ga HotPDF deklarira kot Integer. Preberite C tip vsake vrnjene vrednosti, namesto da bi predpostavili en dogovor za celoten API
Druga podrobnost je, da callback nikoli ne javi izjeme. Izjema Delphi, ki se razvije skozi okvirje C++ Tesseract, je nedoločeno obnašanje, zato callback HotPDF bere samo žeton preklica in monotono vrednost GetTickCount64. Adapter pretvori rezultat v diagnostiko preklica ali zakasnitve, potem ko se TessBaseAPIRecognize vrne, in to preverjanje opravi ne glede na native vrnilno kodo
Katere native kazalce je lastnik strani Delphi?
Adapter DLL Tesseract HotPDF je lastnik treh native objektov na zahtevo — instance API, monitorja in iteratorja rezultatov — vse ostalo pa posoja. Vsak klic Recognize ustvari svojo množico in jo sprosti v bloku finally: TessResultIteratorDelete, nato TessMonitorDelete, nato TessBaseAPIDelete. Sprostitev vmesnika motorja raznaloži knjižnico
TessResultIteratorGetPageIteratorvrne posojen pogled v iterator rezultatov, ne novega objekta. HotPDF ga uporablja zaTessPageIteratorBoundingBoxinTessPageIteratorBaselineter ga nikoli ne sprosti; njegovo ločeno brisanje bi isti pomnilnik sprostilo dvakratTessResultIteratorGetUTF8Textvrne niz, dodeljen s strani lastnega izvajalnega okolja DLL. HotPDF ga skopira in vrne skoziTessDeleteTextv blokufinally; PascalFreeMembi ga sprostil na napačnem kupu- Besedilo besed se dekodira s strogim potrjevanjem UTF-8 in preverjanjem dolžine, preden se pretvori. Besede s kontrolnimi znaki, okvarjenim UTF-8, okvirji izven slike, obrnjenimi pravokotniki ali zaupanjem izven 0-100 ne uspejo zahteve, namesto da bi bile tiho zakrpane
- Skupno besedilo na zahtevo je omejeno na 1.048.576 kodnih enot UTF-16, število besed pa mora soditi v proračun zahteve, izročen od
ApplyLoadedOCRTextLayer
Zaupanje prispe kot 0-100 in se skalira na 0-1, tako da THPDFOCRTextLayerOptions.MinimumConfidence pomeni isto stvar za vsak motor. Ko Tesseract poroča osnovno črto, sta oba konca podana naprej; sicer cevovod plasti besedila pade nazaj na svojo geometrijsko oceno, točno kakor pri vhodu TSV
Zakaj potrjevati enum, preden doseže DLL?
HotPDF skopira surovi ordinal PageSegMode in EngineMode v Integer, preden preveri obseg, ker lahko prevajalnik predpostavi, da enum spremenljivka vedno drži deklarirano vrednost, in zloži Ord(X) > Ord(High(T)) v konstantni false. Ordinali niso okras: THPDFTesseractPageSegMode sledi številčenju segmentacije strani Tesseract od 0 do 13, THPDFTesseractEngineMode številčenju načina motorja od 0 do 3, oba pa greta v DLL kot gola cela števila. Zapis opcij, zgrajen s FillChar, zapolnjen iz toka ali podan iz C++Builderja z ulitim celim številom, lahko nosi bajt, kot je 200. Potrjevanje skopiranega ordinala to spremeni v EArgumentException ob času tovarne, namesto v nedefiniran način znotraj native kode. Tovarna tudi zavrne tpsOSDOnly in tpsAutoOnly, ki ne izdelajo nobene besede, ter zahteva osd.traineddata za tpsAutoOSD in tpsSparseTextOSD
Kaj dejansko jamči zakasnitev prepoznavanja?
Zakasnitev DLL Tesseract je sodelovalna: HotPDF lahko ustavi svoje lastno delo in prosi Tesseract, naj se ustavi, a ne more prisiliti native kode, da se vrne. Ura se začne, ko se Recognize začne, tako da pretvorba bitne slike in inicializacija modelov porabita isti proračun kot prepoznavanje. HotPDF preverja pretečen čas in žeton preklica med pretvorbo v sivine in med besedami, medtem ko prehaja rezultate, ter podaja preostale milisekunde TessMonitorSetDeadlineMSecs, preden pokliče TessBaseAPIRecognize
Vrzel je znotraj native klica. Monitor Tesseract je obravnavan med prepoznavanjem besed, ne med TessBaseAPIInit2 ali analizo postavitve strani, tako da lahko počasno nalaganje modelov ali patološka postavitev teče čez rok, preden je zakasnitev prijavljena. Pikslovni in izhodni proračuni tudi ne omejijo lastne rabe pomnilnika native knjižnice. Če potrebujete delavca, ki ga lahko ubijete, uporabite procesni adapter; to je pošteno trgovanje, ne manjkajoča zmožnost
Segmentacija strani je mesto, kjer DLL adapter zasluži svoj kruh na težkem vhodu. Obrazci, oznake in skenirane tabele z raztresenimi polji se pogosto bolje prepoznajo s tpsSparseText kot s samodejno segmentacijo, ki poskuša sestaviti stolpce in odstavke, ki jih ni
procedure OCRFormPages(Doc: THotPDF; const Pages: array of Integer);
var
Engine: IHPDFOCREngine;
TessOptions: THPDFTesseractOptions;
LayerOptions: THPDFOCRTextLayerOptions;
Info: THPDFOCRTextLayerInfo;
begin
TessOptions := THPDFTesseractOptions.Default;
TessOptions.PageSegMode := tpsSparseText; // raztresena polja, brez sestavljanja stolpcev
TessOptions.EngineMode := temLSTMOnly; // potrebuje modele LSTM v tessdata
TessOptions.TimeoutMilliseconds := 20000; // vključuje inicializacijo modelov
Engine := HPDFCreateTesseractDLLOCREngine('C:\OCR\Win64\libtesseract-5.dll',
'C:\OCR\tessdata', 'eng+deu', TessOptions);
LayerOptions := THPDFOCRTextLayerOptions.Default;
LayerOptions.MinimumConfidence := 0.6;
if not Doc.ApplyLoadedOCRTextLayer(Pages, Engine, LayerOptions, Info) then
case Info.Status of
otlsCancelled:
Writeln('OCR cancelled, document unchanged');
otlsEngineError:
Writeln('Tesseract failed or timed out: ', string(Info.Diagnostic));
else
Writeln(string(Info.Diagnostic));
end;
end;
Zakasnitev pride na plan kot otlsEngineError z diagnostiko Tesseract DLL OCR timed out, preklican žeton pa kot otlsCancelled. V obeh primerih je ApplyLoadedOCRTextLayer prepoznala vsako izbrano stran, preden začne transakcijo zapisa, tako da odpoved na strani 40 od 50 pusti naloženi dokument točno takšnega, kot je bil. Vedmite, da tpsSingleLine, tpsSingleBlock in tpsSparseText spremenijo samo segmentacijo; nobeden od njiju ne poravna poševnega skena
Free Pascal in Lazarus: zastareli piksli in izgubljena kitajščina
Obe tovarni Tesseract delujeta v Windows Free Pascal in izgradnjah Lazarus Win32 ter Win64 od v2.772.1, po dveh popravkih, specifičnih za FPC. Najprej znova zgradite paket Lazarus za ciljno arhitekturo; splošni prenos je pokrit v HotPDF na Free Pascal in Lazarus Win64
Prvi popravek zadeva piksle. LCL TBitmap, zapisan skozi scanline, lahko posodobi svojo surovo sliko, brez osvežitve ročaja bitne slike Windows, tako da GetDIBits na tem ročaju vrne stare piksle. Simptom je bil zmeden: besedilo, narisano neposredno na bitno sliko, je bilo prepoznano, stran, izrisana s strani izrisovalnika PDF HotPDF, pa je izdelala prazen seznam besed. Na FPC adapter zdaj bere posnetek, ki upošteva obliko, skozi CreateIntfImage, ki spoštuje pikslovni format in vrstni red vrstic surove slike. Izgradnja Delphi obdrži pot GetDIBits na zasebni 24-bitni kopiji. Nobena izgradnja ne spremeni bitne slike klicalca
Drugi popravek pripada adapterju tesseract.exe. TStringList FPC shranjuje nize ANSI, tako da je dodelitev dekodiranega besedila TSV UTF-8 k Lines.Text tiho izpustila vsak kitajski znak ali znak dopolnilne ravnine, ki ga sistemska kodna stran ANSI ni mogla predstaviti. Pot FPC zdaj obdrži TSV kot bajte UTF-8, odstrani BOM na ravni bajtov in dekodira vsako besedo v UnicodeString posebej. DLL adapter tega problema ni nikoli imel, ker vsako besedo dekodira neposredno iz iteratorja
Hiter pregled
- Tovarna:
HPDFCreateTesseractDLLOCREngine(LibraryPath, TessDataDirectory, Language[, Options])vHPDFTesseractRecognition, dodana v v2.772.0, podpora FPC v v2.772.1 - Privzete vrednosti:
tpsAuto,temDefault, 60.000 ms, 16.777.216 pikslov; obseg zakasnitve 1-3.600.000 ms, pikslovni strop 67.108.864 - Ujemite bitnost DLL-ja z aplikacijo in postavite odvisnostne DLL-je ob DLL Tesseract
- Monitor obravnavajte kot neprozornega; nikoli ne kopirajte
ETEXT_DESCv zapis Pascal - Deklarirajte callback preklica kot
cdeclz enobajtnim rezultatomBooleanin nikoli ne pustite, da bi iz njega ušla izjema - Besedilo iteratorja sprostite z
TessDeleteText; nikoli ne sprostite iteratorja strani, pridobljenega iz iteratorja rezultatov - Pričakujte, da je rok sodelovalen: inicializacija modelov in analiza postavitve ga lahko pretečeta
- Uporabite adapter tesseract.exe, kadar potrebujete trdo prekinitev ali izolacijo sesutij
Adapter DLL Tesseract, procesni adapterji in vgrajeni motor OCR vsi prihajajo s komponento HotPDF Delphi PDF za Delphi, C++Builder in Free Pascal; poglejte stran izdelka HotPDF za izdaje in prenose