Vícejazykový systém pro OCR - Readiris pro 6 cz

Sdílet

V podtitulku uvedená zkratka OCR pochází ze sousloví Optical CharacterRecognition, v češtině pak optické rozpoznávání znaků. Jedná se o specializovaný software, který je schopen přev...
V podtitulku uvedená zkratka OCR pochází ze sousloví Optical Character
Recognition, v češtině pak optické rozpoznávání znaků. Jedná se o
specializovaný software, který je schopen převést informaci obrazovou na
znakovou pomocí důmyslného algoritmu. Lidově řečeno, vytáhne z naskenovaného
textu znaky a předá je případně ke zpracování běžnému textovému editoru. Ušetří
tedy spoustu času při přepisování textu do počítače.

Samozřejmě že to vypadá moc ideálně. Proto je třeba překonat několik zádrhelů.
Předně je potřeba mít zařízení, které převede předlohu do počítače, tedy nějaký
druh skeneru. Také na předlohu jsou kladeny určité požadavky. Například musí
být dobře čitelná. Všechno výše uvedené platí pro veškeré OCR programy. Dají se
vcelku dobře rozlišit podle toho, s jak nekvalitním textem se ještě dokáží
vypořádat.


Skenujeme a rozeznáváme

V případě, že vaše pracoviště ještě není skenerem vybaveno, měli byste si ho co
nejdříve pořídit. Hodí se totiž na spoustu věcí. Chcete-li ho používat jako
zdroj pro OCR, nejsou na něj kladeny žádné speciální nároky. Pro recenzovaný
software pak stačí být vybaven ještě nějakým rozumným PC, a lze začít pracovat.
Po bezproblémové instalaci a prvním spuštění se objeví průvodce nastavením
parametrů. Po jejich zadání už zbývá jen založit předlohu do skeneru a
stisknout tlačítko pro načtení předlohy. Program používá standardní TWAIN
rozhraní a skenování tedy probíhá obvyklým způsobem. Obecně lze také říct, že
není třeba skenovat text s příliš velkým rozlišením (stačí asi 300-400 dpi).
Jednak se tím redukuje velikost předlohy, jednak je vyšší rozlišení už
neefektivní. Ale zpátky k práci. Po naskenování textu následuje jeho rozdělení
na odstavce a jejich seřazení, jak jdou po sobě. Rozpoznávání textu se spustí
dalším tlačítkem. Rozpoznaný text pak ReadIRIS uloží jako dokument v textovém
editoru, přednastaven je MS Word 97/2000. Použití Wordu je výhodné i proto, že
ReadIRIS podporuje ukládání textu ve formátovaném tvaru. Je možno samozřejmě
nastavit ukládání i jako plain text, který formátování přirozeně ztrácí.


Zkušenosti

Již výše jsem naznačil, že hodně závisí na kvalitě předlohy. Při pokusu o
rozeznání tmavězeleného textu na tmavěmodrém pozadí činí potíže i člověku,
natož počítači. Nejlepších výsledků se podaří dosáhnout s černým textem na
bílém pozadí. Nejhorších naopak v případě spektrálně blízkých barev, jak jsem
již zmínil. V případě snímání barevného textu je třeba si vyhrát s nastavením
skeneru.

Při rozpoznávání je ReadIRIS čím dál tím lepší. Důvodem je jeho schopnost učit
se. Při prvním spuštění se objeví největší množství špatně určených znaků.
Vyplatí se ze začátku nechat program rozpoznávat v učicím modu. V případě
nejasnosti se zeptá na správnou interpretaci znaku a naučí se příslušnou
variantu daného písmene. Čím rozsáhlejší znalosti ReadIRIS získá, tím více se
snižuje počet chyb ve čteném textu. Po několika textech přečtených a
interaktivně opravovaných je úspěšnost skutečně vysoká a je pak možno učení
vypnout.

Jak je již řečeno výše, výstupy ReadIRISu se exportují přímo do MS Wordu
společně s formátováním, tzn. že rozpoznaný text zachovává odstavce, odrážky a
ostatní prvky. Navíc při skenování kompletní stránky i s grafikou je pak
obrázek vložen jako objekt do výsledného dokumentu na stejném místě jako v
předloze.

Zkušenosti jsem sbíral skenováním různých předloh od dokumentů, vytištěných
laserovou tiskárnou, po reklamní letáky nevysoké kvality (graficky a obsahově).
Pokud se jednalo o černobílé texty s ucházejícím tiskem, ReadIRIS byl takřka
stoprocentní. Zachoval formátování, a chyby byly zanedbatelné, jako třeba
nevynechání mezery mezi slovy. Se zhoršující se kvalitou předlohy klesala i
úspěšnost rozpoznání a ve zmíněném případě kombinace modrá-zelená byla
úspěšnost už mizivá. Je třeba dodat, že i já jsem měl problém rozluštit, co je
tam napsáno. Program umožňuje navíc obvyklé operace se zdrojovým obrázkem
otočit, zrcadlit nebo roztáhnout, což se občas hodí.


Hodnocení

ReadIRIS mě příjemně překvapil. Čtení černobílého textu je rychlé a
odpovídající předloze, což je přesně to, co bych od OCR softwaru očekával.
Navíc je dodáván v jedné verzi pro desítky jazykových mutací, mezi nimiž
nechybí čeština. Nevzniká tedy problém háčků a čárek. Zároveň lze několika
kliknutím i změnit rozpoznávání z češtiny třeba na ruštinu a nechat si přečíst
text psaný azbukou, což jsem také úspěšně odzkoušel. Kromě jiných znakových sad
zvládne program i různé druhy fontů.

Jestli se u vás přepisují z tištěných předloh do počítače kvanta textů, tak
ReadIRIS je řešením pro vás. Vražte těch pár korun do nějakého skeneru a pusťte
se do optického rozpoznávání znaků. Zejména je to vhodné pro ty, kteří nejsou
schopni během pracovní doby přepsat pětistránkovou dokumentaci. S dobře
vycvičeným ReadIRISem se časová náročnost tohoto úkonu výrazně sníží.




ReadIRIS PRO 6 CZ

schopnost učit se
úspěšnost rozpoznávání
množství podporovaných znakových sad

K recenzi poskytla firma: I.R.I.S. www.irislink.com
Distributor pro ČR: SWS, a. s.
Dostihová 1, 763 15 Slušovice
Cena: 16 421 Kč (bez DPH)
'; document.getElementById('preroll-iframe').onload = function () { setupIframe(); } prerollContainer = document.getElementsByClassName('preroll-container-iframe')[0]; } function setupIframe() { prerollDocument = document.getElementById('preroll-iframe').contentWindow.document; let el = prerollDocument.createElement('style'); prerollDocument.head.appendChild(el); el.innerText = "#adContainer>div:nth-of-type(1),#adContainer>div:nth-of-type(1) > iframe { width: 99% !important;height: 99% !important;max-width: 100%;}#videoContent,body{ width:100vw;height:100vh}body{ font-family:'Helvetica Neue',Arial,sans-serif}#videoContent{ overflow:hidden;background:#000}#adMuteBtn{ width:35px;height:35px;border:0;background:0 0;display:none;position:absolute;fill:rgba(230,230,230,1);bottom:20px;right:25px}"; videoContent = prerollDocument.getElementById('contentElement'); videoContent.style.display = 'none'; videoContent.volume = 1; videoContent.muted = false; const playPromise = videoContent.play(); if (playPromise !== undefined) { playPromise.then(function () { console.log('PREROLL sound allowed'); // setUpIMA(true); videoContent.volume = 1; videoContent.muted = false; setUpIMA(); }).catch(function () { console.log('PREROLL sound forbidden'); videoContent.volume = 0; videoContent.muted = true; setUpIMA(); }); } } function setupDimensions() { prerollWidth = Math.min(iinfoPrerollPosition.offsetWidth, 480); prerollHeight = Math.min(iinfoPrerollPosition.offsetHeight, 320); } function setUpIMA() { google.ima.settings.setDisableCustomPlaybackForIOS10Plus(true); google.ima.settings.setLocale('cs'); google.ima.settings.setNumRedirects(10); // Create the ad display container. createAdDisplayContainer(); // Create ads loader. adsLoader = new google.ima.AdsLoader(adDisplayContainer); // Listen and respond to ads loaded and error events. adsLoader.addEventListener( google.ima.AdsManagerLoadedEvent.Type.ADS_MANAGER_LOADED, onAdsManagerLoaded, false); adsLoader.addEventListener( google.ima.AdErrorEvent.Type.AD_ERROR, onAdError, false); // An event listener to tell the SDK that our content video // is completed so the SDK can play any post-roll ads. const contentEndedListener = function () { adsLoader.contentComplete(); }; videoContent.onended = contentEndedListener; // Request video ads. const adsRequest = new google.ima.AdsRequest(); adsRequest.adTagUrl = iinfoVastUrls[iinfoVastUrlIndex]; console.log('Preroll advert: ' + iinfoVastUrls[iinfoVastUrlIndex]); videoContent.muted = false; videoContent.volume = 1; // Specify the linear and nonlinear slot sizes. This helps the SDK to // select the correct creative if multiple are returned. // adsRequest.linearAdSlotWidth = prerollWidth; // adsRequest.linearAdSlotHeight = prerollHeight; adsRequest.nonLinearAdSlotWidth = 0; adsRequest.nonLinearAdSlotHeight = 0; adsLoader.requestAds(adsRequest); } function createAdDisplayContainer() { // We assume the adContainer is the DOM id of the element that will house // the ads. prerollDocument.getElementById('videoContent').style.display = 'none'; adDisplayContainer = new google.ima.AdDisplayContainer( prerollDocument.getElementById('adContainer'), videoContent); } function unmutePrerollAdvert() { adVolume = !adVolume; if (adVolume) { adsManager.setVolume(0.3); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } else { adsManager.setVolume(0); prerollDocument.getElementById('adMuteBtn').innerHTML = ''; } } function onAdsManagerLoaded(adsManagerLoadedEvent) { // Get the ads manager. const adsRenderingSettings = new google.ima.AdsRenderingSettings(); adsRenderingSettings.restoreCustomPlaybackStateOnAdBreakComplete = true; adsRenderingSettings.loadVideoTimeout = 12000; // videoContent should be set to the content video element. adsManager = adsManagerLoadedEvent.getAdsManager(videoContent, adsRenderingSettings); // Add listeners to the required events. adsManager.addEventListener(google.ima.AdErrorEvent.Type.AD_ERROR, onAdError); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_PAUSE_REQUESTED, onContentPauseRequested); adsManager.addEventListener( google.ima.AdEvent.Type.CONTENT_RESUME_REQUESTED, onContentResumeRequested); adsManager.addEventListener( google.ima.AdEvent.Type.ALL_ADS_COMPLETED, onAdEvent); // Listen to any additional events, if necessary. adsManager.addEventListener(google.ima.AdEvent.Type.LOADED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.STARTED, onAdEvent); adsManager.addEventListener(google.ima.AdEvent.Type.COMPLETE, onAdEvent); playAds(); } function playAds() { // Initialize the container. Must be done through a user action on mobile // devices. videoContent.load(); adDisplayContainer.initialize(); // setupDimensions(); try { // Initialize the ads manager. Ad rules playlist will start at this time. adsManager.init(1920, 1080, google.ima.ViewMode.NORMAL); // Call play to start showing the ad. Single video and overlay ads will // start at this time; the call will be ignored for ad rules. adsManager.start(); // window.addEventListener('resize', function (event) { // if (adsManager) { // setupDimensions(); // adsManager.resize(prerollWidth, prerollHeight, google.ima.ViewMode.NORMAL); // } // }); } catch (adError) { // An error may be thrown if there was a problem with the VAST response. // videoContent.play(); } } function onAdEvent(adEvent) { const ad = adEvent.getAd(); console.log('Preroll event: ' + adEvent.type); switch (adEvent.type) { case google.ima.AdEvent.Type.LOADED: if (!ad.isLinear()) { videoContent.play(); } prerollDocument.getElementById('adContainer').style.width = '100%'; prerollDocument.getElementById('adContainer').style.maxWidth = '640px'; prerollDocument.getElementById('adContainer').style.height = '360px'; break; case google.ima.AdEvent.Type.STARTED: window.addEventListener('scroll', onActiveView); if (ad.isLinear()) { intervalTimer = setInterval( function () { // Example: const remainingTime = adsManager.getRemainingTime(); // adsManager.pause(); }, 300); // every 300ms } prerollDocument.getElementById('adMuteBtn').style.display = 'block'; break; case google.ima.AdEvent.Type.ALL_ADS_COMPLETED: if (ad.isLinear()) { clearInterval(intervalTimer); } if (prerollLastError === 303) { playYtVideo(); } break; case google.ima.AdEvent.Type.COMPLETE: if (ad.isLinear()) { clearInterval(intervalTimer); } playYtVideo(); break; } } function onAdError(adErrorEvent) { console.log(adErrorEvent.getError()); prerollLastError = adErrorEvent.getError().getErrorCode(); if (!loadNext()) { playYtVideo(); } } function loadNext() { iinfoVastUrlIndex++; if (iinfoVastUrlIndex < iinfoVastUrls.length) { iinfoPrerollPosition.remove(); playPrerollAd(); } else { return false; } adVolume = 1; return true; } function onContentPauseRequested() { videoContent.pause(); } function onContentResumeRequested() { videoContent.play(); } function onActiveView() { if (prerollContainer) { const containerOffset = prerollContainer.getBoundingClientRect(); const windowHeight = window.innerHeight; if (containerOffset.top < windowHeight/1 && containerOffset.bottom > 0.0) { if (prerollPaused) { adsManager.resume(); prerollPaused = false; } return true; } else { if (!prerollPaused) { adsManager.pause(); prerollPaused = true; } } } return false; } function playYtVideo() { iinfoPrerollPosition.remove(); youtubeIframe.style.display = 'block'; youtubeIframe.src += '&autoplay=1&mute=1'; } }