Ela.kpi.ua



Нац?ональний техн?чний ун?верситет Укра?ни?Ки?вський пол?техн?чний ?нститут ?мен? ?горя С?корського?Факультет ?нформатики та обчислювально? техн?киКафедра обчислювально? техн?ки?На правах рукопису??До захисту допущено?УДК Зав?дувач кафедриСт?ренко С.Г.(п?дпис) (?н?ц?али, пр?звище)“” 2019 р.Маг?стерська дисертац?яз? спец?альност?: 121. ?нженер?я програмного забезпечення____(код та назва напряму п?дготовки або спец?альност?)Спец?ал?зац?я: 121.Програмне забезпечення високопродуктивних комп’ютерних систем та мереж_________________________________________________на тему: Система розп?знавання рекв?зит?в документ?в по зображеннюВиконав (-ла): студент (-ка) VI курсу, групи ?П-84мп(шифр групи)Блонський Андр?й Володимирович(пр?звище, ?м’я, по батьков?)(п?дпис) Науковий кер?вник доцент Клименко ?.А.(посада, науковий ступ?нь, вчене звання, пр?звище та ?н?ц?али)(п?дпис) Консультант (назва розд?лу)(посада, вчене звання, науковий ступ?нь, пр?звище, ?н?ц?али)(п?дпис) Рецензент (посада, науковий ступ?нь, вчене звання, науковий ступ?нь, пр?звище та ?н?ц?али)(п?дпис) Засв?дчую, що у ц?й маг?стерськ?й дисертац?? нема? запозичень з праць ?нших автор?в без в?дпов?дних посилань.Студент (п?дпис)Ки?в – 2019 рокуНац?ональний техн?чний ун?верситет Укра?ни?Ки?вський пол?техн?чний ?нститут ?мен? ?горя С?корського?Факультет (?нститут) ?нформатики та обчислювально? техн?ки (повна назва)Кафедра Обчислювально? техн?ки (повна назва)Осв?тньо-квал?ф?кац?йний ступ?нь маг?стр (назва ОКР)Спец?альн?сть 121. ?нженер?я програмного забезпечення (код ? назва)Спец?ал?зац?я 121. Програмне забезпечення високопродуктивних комп’ютерних систем та мереж_________________________________(код ? назва)ЗАТВЕРДЖУЮЗав?дувач кафедриСт?ренко С.Г.(п?дпис)(?н?ц?али, пр?звище)?? 2019 р.ЗАВДАННЯна маг?стерську дисертац?ю студенту Блонському Андр?ю Володимировичу(пр?звище, ?м’я, по батьков?)1. Тема дисертац??Система розп?знавання рекв?зит?в документ?в по зображенню Науковий кер?вник дисертац?? доцент Клименко ?.А.(пр?звище, ?м’я, по батьков?, науковий ступ?нь, вчене звання)затверджен? наказом по ун?верситету в?д ?_07_? __11__ 2018 р. № _4112-c_2. Строк подання студентом дисертац?? __________3. Об’?кт досл?дження розп?знавання даних документа по зображенню4. Предмет досл?дженняметоди та ?нструменти розп?знавання тексту по зображенню, можлив?сть створити систему, яка здатна автоматично розп?знавати текст та викор?нювати необх?дн? дан? ?з документа5. Перел?к завдань, як? потр?бно розробити:1. Проанал?зувати сучасн? ?нструменти розп?знавання тексту2. Спроектувати та розробити систему, яка здатна автоматизувати процес розп?знавання3. Протестувати систему на предмет ефективност?4. Проанал?зувати ?нвестиц?йну складову технолог??6. Консультанти розд?л?в дисертац??: Розд?лПр?звище, ?н?ц?али та посада консультантаП?дпис, датазавдання видавзавдання прийнявнормоконтрольКулаков Ю.А.7. Дата видач? завдання Календарний план№ з/пНазва етап?в виконання маг?стерсько? дисертац??Строк виконання етап?в дисертац?? Прим?тка1Анал?з предметно? област?, огляд л?тератури14.09.20192Досл?дження ?нструмент?в розп?знавання тексту26.09.20193Опис особливостей ? вимог системи04.10.20194Виб?р технолог?й для реал?зац?? системи12.10.20195Проектування та реал?зац?я системи29.10.20196Тестування системи05.11.20197Оформлення матер?ал?в дисертац??15.11.2019Студент ______________ А.В.Блонський (п?дпис) (?н?ц?али, пр?звище)Науковий кер?вник дисертац?? ?.А.Клименко (п?дпис) (?н?ц?али, пр?звище)РЕФЕРАТна маг?стерську дисертац?ювиконану на тему: Система розп?знавння рев?зит?в документ?в по зображеннюстудентом: Блонським Андр??м ВолодимировичемРобота склада?ться ?з вступу та чотирьох розд?л?в. Загальний обсяг роботи: 80 аркуш?в основного тексту, 14 ?люстрац??, 28 таблиць. При п?дготовц? використовувалася л?тература з 30 р?зних джерел.Актуальн?сть. Б?льш?сть сучасних компан?й ведуть електронний документооб?г. ?сну? багато ?нструмент?в для перетворення паперового документу в його цифровий вигляд. Але ?нструмент?в для викор?нення специф?чних даних ?з документ?в – нема?. Цей процес до сих п?р робиться в б?льшост? випадк?в ?вручну?. Важко п?драхувати, ск?льки грошей та часу могла би зекономити система яка автоматизувала би б?знес-процес розп?знавання тексту документа та викор?нення корисних даних ?з нього.Мета ? завдання досл?дження. Метою маг?стерсько? роботи ? розробка системи розп?знавання та викор?нення специф?чних даних ?з зображень документ?в та тестування системи ?з метою анал?зу ефективност? тако? системи.Для досягнення мети досл?дження поставлено ? вир?шено так? завдання:анал?з ?нструмент?в розп?знавння тексту;досл?дження особливостей та вимог системи розп?знавння рекв?зит?в документу по зображенню;проектування та розробка системи розп?знавння рекв?зит?в документу по зображенню.Об’?кт досл?дження – процес розробки системи для розп?знавання та викор?нення специф?чних даних ?з документа по зображенню.Предмет досл?дження – засоби автоматизац?? процесу розп?знавання та викор?нення специф?чних даних ?з документа.Особистий внесок здобувача. Маг?стерське досл?дження ? самост?йно виконаною роботою, в як?й в?дображено особистий авторський п?дх?д та особисто отриман? теоретичн? та прикладн? результати, що в?дносяться до вир?шення задач?. Спос?б проектування системи ?з р?зними ?нструментами, б?б?л?отеками та фреймворками. Формулювання мети та завдань досл?дження проводилось сп?льно з науковим кер?вником.Практична ц?нн?сть. Отримана система розп?знавння рекв?зит?в документ?в по зображенню може бути впроваджена у будь-яку коропоративну систему електронного документооб?гу на комерц?йн?й основ?.Ключов? слова. Розп?знавання тексту, комп’ютерний з?р, оптичне розп?знавння символ?в, система розп?знавння рекв?зит?в, розп?знавння зображення.SUMMARYfor the master’s thesiscompleted on the topic: Document Image Details Recognition Systemstudent: Andrii Blonskyi The work consists of an introduction and four parts. Total: 80 main body sheets, 14 illustrations, 28 tables. In the course of preparation, literature from 30 different sources was used. Topicality. Most modern companies maintain electronic document flow. There are many tools for converting a paper document into its digital form. But there are no tools to recognize specific data i documents. This process is still done in most cases "manually". It is difficult to calculate how much money and time could be saved by a system that would automate the business process of recognizing the text of a document and saving useful data from it. The purpose and objectives of the study. The purpose of the master's thesis is to develop a system for recognizing specific data from document images and testing the system to analyze the effectiveness of it. To achieve the goal of the study set and solved such tasks: ? analysis of text recognition tools; ? analysis of features and requirements of the system of recognition of the requisites of the document on the image; ? design and development of the system of recognition of details of the document on the image. Object of study - the process of developing a system for recognizing specific data from an image of the document. The subject of research – ways to automate the process of recognizing specific data from an image of the document. Personal contribution of the applicant. The master's research is a self-completed work that reflects the author's personal approach and personally obtained theoretical and applied results related to the issue. A method of designing a system with different tools, libraries and frameworks. The purpose and objectives of the study were formulated jointly with the scientific supervisor. Practical value. The obtained system of recognition of the requisites of documents on the image can be implemented in any corporative system of electronic document flow on a commercial basis. Keywords Text Recognition, Computer Vision, Optical Character Recognition, System of Requisties Recognition, Image Recognition.ЗМ?СТ TOC \o "1-3" \h \z \u ПЕРЕЛ?К ТЕРМ?Н?В ТА СКОРОЧЕНЬ PAGEREF _Toc26896246 \h 10ВСТУП PAGEREF _Toc26896247 \h 12РОЗД?Л 1 ОГЛЯД ?СНУЮЧИХ Р?ШЕНЬ PAGEREF _Toc26896249 \h 141.1. Загальн? в?домост? про задачу розп?знавання рекв?зит?в та технолог?? комп’ютерного зору PAGEREF _Toc26896250 \h 141.2. Значення OCR у б?знес? PAGEREF _Toc26896251 \h 191.3. Огляд наи?популярн?ших реал?зац?и? OCR PAGEREF _Toc26896252 \h 23ВИСНОВОК ДО РОЗД?ЛУ 1 PAGEREF _Toc26896253 \h 32РОЗД?Л 2 АНАЛ?З ЗАДАЧ? ТА ОГЛЯД ТЕХНОЛОГ?Й PAGEREF _Toc26896255 \h 332.1. Опис предметно? област? PAGEREF _Toc26896256 \h 332.2. Виб?р технолог?и? та ??х об?рунтування PAGEREF _Toc26896257 \h 362.3. Повний цикл роботи програми PAGEREF _Toc26896258 \h 47ВИСНОВОК ДО РОЗД?ЛУ 2 PAGEREF _Toc26896259 \h 48РОЗД?Л 3 ПРОЕКТУВАННЯ ТА РОЗРОБКА СИСТЕМИ PAGEREF _Toc26896261 \h 493.1. Визначення вимог для проектування PAGEREF _Toc26896262 \h 493.2. Опис функц?оналу ?нтерфейсного та автоматичного режим?в PAGEREF _Toc26896263 \h 493.3. Прецеденти PAGEREF _Toc26896264 \h 503.4. Проектування бази даних PAGEREF _Toc26896265 \h 573.5. Основн? р?шення з реал?зац??? системи та ?? компонент?в PAGEREF _Toc26896266 \h 603.6. Тестування системи PAGEREF _Toc26896267 \h 66ВИСНОВКИ ДО РОЗД?ЛУ 3 PAGEREF _Toc26896268 \h 68РОЗД?Л 4 РОЗРОБКА СТАРТАП ПРОЕКТУ PAGEREF _Toc26896270 \h 694.1. Опис ?де? проекту PAGEREF _Toc26896271 \h 694.2. Технолог?чний аудит проекту PAGEREF _Toc26896272 \h 714.3. Анал?з ринкових можливостей запуску стартап-проекту PAGEREF _Toc26896273 \h 724.4. Розроблення ринково? стратег?? проекту PAGEREF _Toc26896274 \h 774.5. Розроблення маркетингово? програми стартап-проекту PAGEREF _Toc26896275 \h 79ВИСНОВКИ ДО РОЗД?ЛУ 4 PAGEREF _Toc26896276 \h 83ЗАГАЛЬН? ВИСНОВКИ PAGEREF _Toc26896277 \h 84СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ PAGEREF _Toc26896278 \h 87ДОДАТКИ PAGEREF _Toc26896279 \h 90ДОДАТОК А PAGEREF _Toc26896280 \h 90ДОДАТОК Б PAGEREF _Toc26896282 \h 135ПЕРЕЛ?К ТЕРМ?Н?В ТА СКОРОЧЕНЬOCR??(Optical Character Recognition – OCR) – технолог?я, яка дозволя? перетворювати р?зн? типи документ?в, так? як в?дсканован? документи, PDF-файли або фото з цифрово? камери, в редагован? формати з можлив?стю пошуку.API??(англ.?Application Programming Interface,?API) – наб?р?визначень?п?дпрограм, протокол?в вза?мод?? та засоб?в для створення програмного забезпечення.SDK??(SoftWare Development Kit) – наб?р ?з засоб?в розробки,?утил?т?? документац??, який дозволя??програм?стам?створювати?прикладн? програми?за визначеною?технолог??ю?або для певно? платформи (програмно??або?програмно-апаратно?)JAR??Java-арх?в. Явля? собою ZIP-арх?в, в якому м?ститься частина програми на мов??Java.PDF??Portable Document Format?(PDF)?– в?дкритий формат файлу, створений ? п?дтримуваний компан??ю?Adobe Systems, для представлення двовим?рних документ?в у незалежному в?д пристрою виведення та розд?льно? здатност? вигляд?. Кожен PDF-файл може м?стити повну ?нформац?ю про 2D-документ, таку як: тексти, зображення, векторн? зображення, в?део, ?нтерактивн? форми та ?н. В грудн? 2007 року формат PDF було затверджено як стандарт?ISO?32000. Явля?ться основним форматом для збереження документ?в.PNG??Portable Network Graphics?–?растровий?формат збереження граф?чно? ?нформац??, що використову??стиснення?без втрат. PNG був створений для зам?ни формату?GIF?граф?чним форматом, який не потребу??л?ценз???для використання. Зазвичай файли формату PNG мають розширення .pngTIFF??(англ.?Tagged Image File Format)?– формат збереження растрових?граф?чних зображень.Apache License??(Apache Software License?до верс?? 2.0) – л?ценз?я на?в?льне програмне забезпечення?Apache Software Foundation.ВСТУПСьогодн? будь-яка сучасна орган?зац?я чи компан?я вводить електронний документооб?г всередин? компан?? та з ?ншими компан?ями. Кожен документ ма? певн? рекв?зити та ключов? слова, за якими його можна швидко знайти у баз? даних. В залежност? в?д типу документу, рекв?зити можуть бути р?зн?, та представлен? у р?зних типах даних. В будь-якому випадку, сьогодн? майже у вс?х орган?зац?ях, введенням рекв?зит?в та даних по документам займа?ться сп?вроб?тник. Цей процес автоматизовний х?ба що, для компан?й, в яких використову?ться один тип документу. Але коли тип?в таких документ?в багато - автоматизовувати цей процес ста? ваще.Розвиток нейронних мереж та систем комп’ютерного зору проходить саме зараз, але вже досяг певних результат?в. Багато систем вм?ють досить точно розп?знавати об’?кти, що зображен? на фотограф?ях, в тому числ? ? текст в документах. Мета ц??? маг?стерсько? дисертац?? - вивчити можлив?сть використання б?бл?отек ?з розп?знавання тексту для автоматизац?? розп?знавання ?х рекв?зит?в та розробка тако? системи.?сну? велика к?льк?сть OCR б?бл?отек, потр?бно було проанал?зувати ?х та пор?вняти. Потр?бно було також розробити певний п?дх?д, за яким система би могла ?навчатись? точно викор?нювати потр?бн? дан? ?з документа. П?сля цього вже можна було приступати до автоматизц?? б?знес-процесу ?з виявлення рекв?зит?в та збереження ?х у баз? даних. Пом?ж таблиц? ?з отриманими рекв?зитами у баз? даних також потр?бно було створити схему для збереження даних, потр?бних саме для точного викор?нення рекв?зит?в.Не ?сну? ?дино?, повноц?нно? системи, яка здатна використовувати OCR б?бл?отеки для автоматизац?? б?знес-процесу розп?знавання та викор?нення рекв?зит?в документ?в. Така система дозволить скоротити час на розп?знавання даних документ?в та ?х збереження у баз? даних. А висока точн?сть роп?знавання також да? можлив?сть проводити автоматично анал?з докумен?в. У св?т?, де намагаються автоматизувати вс? робоч? процеси, така система точно знайшла б сво? м?сце.В?дсутност? таких готових систем ? пояснення. Зазвичай, у кожно? компан?? своя пол?тика докуменооб?гу, та сво? формати документ?в. Пом?ж розп?знавання, треба зробити анал?з документу та викорин?ти потр?бн? дан?. При великий к?лькост? р?зних тип?в документ?в це зробити досить важко. Тому ?диним вир?шенням тако? проблеми ? створення у систем? модуля, який би дозволяв ?навчати? систему точно розп?знавати рекв?зити в кожному тип? документу.Звичайно, як?сть отриманих даних, а отже й як?сть вс??? системи в ц?лому напряму залежить в?д точност? розп?знавання символ?в. Тому був проведений анал?з найпопулярн?шних б?бл?отек ?з розп?знавання тексту, та п?д?браний найкращий ?з вар?нт?в.Вир?шення цих ключових проблем та як?сна техн?чна реал?зац?я й приведе до створення системи ?з розп?знавання рекв?зит?в документ?в по зображенню. Система розроблялася як окремий модуль, який можна буде ?з легк?стю впровадити у будь-яку систему ?з орган?зац?? роботи компан?й.РОЗД?Л 1ОГЛЯД ?СНУЮЧИХ Р?ШЕНЬ1.1. Загальн? в?домост? про задачу розп?знавання рекв?зит?в та технолог?? комп’ютерного зоруСьогодн?, як н?коли ран?ше, ведуться активн? роботи ?з розробки та вдосконалення технолог?й комп’ютерного зору, зокрема розп?знавання об’?кт?в по зображенню.Системи розп?знавання обличчя та системи б?ометричного сканування також використовують технолог?ю комп'ютерного зору для ?дентиф?кац?? ос?б з метою безпеки. Найпоширен?ший приклад комп’ютерного зору в розп?знаванн? обличчя - це безпека ?нформац?? у смартфонах. Б?льш досконал? способи розп?знавання обличчя та б?ометрики включають в житлових або б?знес-системах безпеки, як? використовують ун?кальн? ф?з?олог?чн? особливост? людей для перев?рки ?хньо? особистост?. Алгоритми глибокого навчання можуть ?дентиф?кувати ун?кальн? зразки в?дбитк?в людей та використовувати його для контролю доступу до областей високо? безпеки, таких як робоч? м?сця з високою конф?денц?йн?стю, так? як атомн? електростанц??, досл?дницьк? лаборатор?? та банк?вськ? сховища.Системи комп’ютерного зору також чудово розп?знають тонк? диференц?альн? модел? у с?тках та райдужних системах людей, як? набагато ефективн?ш? як ун?кальн? ?дентиф?катори. Ц? системи можна використовувати для п?двищення безпеки високоц?нних актив?в та м?сць розташування.Автомоб?льн? транспортн? засоби, щоб безпечно пересуватися вулицями, повинн? бути в змоз? визначити перешкоди, вив?ски, ?нш? транспортн? засоби та будь-яку людину, яка може заважати. Для цього ц? машини оснащен? безл?ччю ?нструмент?в, таких як LiDAR та ультразвуков? датчики. Вони також використовують камери, що охоплюють весь ?хн?й периметр, як? забезпечують комп’ютерний з?р, щоб безпечно ор??нтуватися щодо оточення. Хоча ?нш? технолог?? можуть допомогти автошколам розп?знати та уникати перешкод, комп'ютерний з?р може допомогти ?м прочитати дорожн? знаки та дотримуватися правил дорожнього руху для максимально? безпеки. Комп'ютерний з?р може також допомогти у прийнятт? критичних р?шень на дороз?, таких як поступки машин? швидко? допомоги та пожежних машин.Комп'ютерний з?р, окр?м того, що в?н вм?? розп?знавати елементи та об'?кти цифрових зображень так само точно, як ? люди, також може визначити законом?рност?, як? може пропустити зорова система людини. Наприклад, досл?дники розробили Ш?, який використову? комп’ютерне бачення для ?дентиф?кац?? ракових пухлин за допомогою КТ-зображень, щоб д?агностувати рак леген? краще, н?ж рентгенологи людини. Ц? програми можуть допомогти запоб?гти п?зньому виявленню раку ? можуть допомогти пац??нтам сво?часно отримувати л?кування. Комп'ютерний з?р можна використовувати для в?зуального визначення ?нших форм раку та ?нших захворювань з б?льшою точн?стю, н?ж люди.Комп'ютерне бачення можна використовувати для сканування прямого або записаного кадру спостереження, щоб допомогти прац?вникам закону та безпеки житт?во важливою ?нформац??ю. Наприклад, комп’ютерний з?р може використовуватися для сканування живих кадр?в ?з загальнодоступно? зони для виявлення шк?дливих предмет?в, таких як зброя, або для виявлення п?дозр?лих повед?нкових чи рухомих зразк?в, як? можуть передв?щати будь-як? незаконн? д?? з боку людей на основ? ?сторичних даних. З подальшим розвитком комп'ютерне бачення також може бути використане для сканування натовпу людей, щоб висв?тлити присутн?сть зац?кавлених орган?в будь-яких зац?кавлених ос?б або розшукуваних ос?б. Таким чином, використання комп’ютерного зору може допомогти прискорити затримання людей, як? ц?кавлять, та запоб?гання злочинам.Виробничий сектор ? одним ?з сектор?в, де найб?льш широко використову?ться автоматизац?я та робототехн?ка. Оск?льки все б?льше ? б?льше виробничих п?дрозд?л?в переходять до повн?стю автоматизованого виробництва, ?м потр?бно буде використовувати б?льш ?нтелектуальн? системи для контролю промислових процес?в та результат?в. Хоча так? технолог??, як ?нтернет речей (IoT), революц?он?зують виробничий сектор ? роблять процеси б?льш автономними, комп'ютерний з?р може надал? допомогти в ?х вдосконаленн?. Наприклад, комп’ютерний з?р можна використовувати для перев?рки виготовлено? продукц?? на предмет дефект?в та нев?дпов?дностей. Таким чином, це може усунути потребу в огляд? людиною на виробнич?й л?н??.Завдяки подальшому досл?дженню та вдосконаленню технолог?? майбутн? комп'ютерного зору дозволить виконувати б?льш широкий спектр функц?й. Технолог?? комп’ютерного зору не т?льки будуть прост?шими у навчанн?, але й зможуть в?др?знити б?льше в?д зображень, н?ж зараз. Це також можна використовувати разом з ?ншими технолог?ями або ?ншими п?дмножинами AI для створення б?льш потужних додатк?в. Наприклад, програми з п?дписом зображень можуть по?днуватися ?з створенням природних мов (NLG) для ?нтерпретац?? об'?кт?в у оточенн? для людей ?з слабким попитом. Комп'ютерний з?р також буде в?д?гравати житт?во важливу роль у розвитку штучного загального ?нтелекту (AGI) та штучного над?нтеллекту (ASI), надаючи ?м можлив?сть обробляти ?нформац?ю так само, як ? нав?ть краще, н?ж зорова система людини [1-2].Враховуючи можливост? сучасного комп’ютерного зору, може бути важко пов?рити, що ? б?льше переваг та застосувань технолог??, як? залишаються невивченими. Майбутн? комп'ютерного зору прокладе шлях для систем штучного ?нтелекту, таких же людських, як ? ми. Однак перед тим, як зробити це, ? к?лька виклик?в, як? необх?дно подолати, найб?льший з них - дем?стиф?кац?я чорно? скриньки Ш?. Це тому, що, як ? ?нш? програми для глибокого навчання, комп'ютерний з?р, незважаючи на функц?ональну ефективн?сть, ? нерозб?рливим щодо його внутр?шнього функц?онування.Програмне забезпечення ?з техлого?ями комп’ютерного зору зм?ню? галуз? та робить життя споживач?в не т?льки легшим, але й ц?кав?шим. Комп'ютерний з?р, як поле, отримало багато розголосу та пристойну суму ?нвестиц?й. На п?вн?чноамериканський ринок програмного забезпечення ?з техлого?ями комп’ютерного зору було ?нвестовано 120 м?льйон?в долар?в США, тод? як ринок Китаю зб?льшився до 3,9 м?льярда долар?в.?ндустр?я роздр?бно? торг?вл? стала п?онером у впровадженн? програмного забезпечення ?з техлого?ями комп’ютерного зору. ASOS, онлайн-магазин одягу додав у св?й додаток вар?ант пошуку за фотограф??ю у 2017 роц?, а багато конкурент?в зробило аналог тако? функц??. Деяк? з них нав?ть зробили крок уперед ? використовували програмне забезпечення ?з техлого?ями комп’ютерного зору для зближення онлайнового та офлайн-досв?ду.Великий магазин солодощ?в у США п?д назвою Lolli & Pops використову? розп?знавання обличчя, щоб ?дентиф?кувати частих покупц?в, коли вони заходять у магазин. Таким чином, прац?вники магазину можуть персонал?зувати досв?д покупки, роблячи персонал?зован? рекомендац?? щодо товар?в та пер?одичн? знижки на програмою лояльност?.Машини Tesla ?з функц??ю автоп?лоту також використовують технолог?? розп?знавання об’?кт?в. А саме, камери у передн?й частин? машини передають зображення на комп’ютер, який ма? розп?знати розм?тку та ?нших учасник?в дорожнього руху для зебезпечення безпеки п?д час вв?мкненого режиму автоп?лоту.А один ?з останн?х приклад?в - магазин Amazon Go у Нью-Йорку. В цьому магазин? нема? н? кас, н? продавц?в. Покупець заходить у магазин, бере все що потр?бно, та просто виходить, а грош? автоматично будуть списан? ?з його рахунку. Все це достяга?ться за рахунок велико? к?лькост? сенсор?в та камер у магазин?, як? за допомогою технолог?й розпознавання розп?знають товари, як? купля? покупець та самого покупця, який вже внесений у базу даних магазину.Таким чином ми бачимо, що програмне забезпечення ?з технолог?ми комп’ютерного зору вже починають впроваджуватись у вс? сфери нашого життя. Таке програмне забезпечення дозволя? автоматизувати дуже багато процес?в, як? виникають у р?зних сферах, а тому попит на нього буде лише рости [3].Розп?знання рекв?зит?в та ?х ?дентиф?кац?я - нев?д?мний б?знес-процес у сучасному св?т?. Будь-яка компан?я збер?га? дан? сво?х закуп?вель, заяв, договор?в, замовлень у тому чи ?ншому вигляд?. Це можуть бути так? типи документ?в: рахунки;замовлення; листи; контракти;зв?ти та ?н;Зазвичай, рекв?зити розп?знаються вручну. Прац?вник перегляда? документ, запису? дан? ? зберга? ?х. Автоматизвати цей процес - означа? проводити розп?знавання та збереження данних рекв?зит?в засобами програмного забезпечення. В першу чергу, питання розп?знавання символ?в ?з скан?в документ?в та викор?нення корисних та потр?бних. Перший етап в цьому б?знес-процес? – сканування [4-5].Сканування - це новий п?дх?д у б?знес?, яка допомага? автоматизувати перех?д паперових документ?в в цифровий формат. В останн? роки сканування зазнало значних зм?н. Якщо ран?ше сканування виступало в якост? завершального етапу документооб?гу (сканування в арх?в), то тепер сканування ?запуска?? документооб?г, ?нтегруючи паперов? документи в б?знес-процес.Ран?ше сканери використовувалися в основному для арх?вац?? ?нформац??, тобто п?сля зак?нчення роботи з паперовими документами. Тепер же сканування ста? початковим етапом роботи з електронними документами: сьогодн? сканер - це т? ?ворота?, через як? документи потрапляють в систему управл?ння документац??ю ? управл?ння корпоративним контентом. Таким чином, ?нструменти сканування ? системи DMS ? ?СМ тепер т?сно ?нтегрован? м?ж собою.Тому перший етап – сканування, не менш важливий н?ж саме розп?знавання. Саме в?д якост? сканування залежить те, як добре OCR розп?зна? символи. Сьогодн?, сканери вже досягли то? якост?, яка дозволя? отримати цифрове зображення документа без перешкод. А отже вже можна говорити про використання систем OCR для розп?знавння тексту та подальшо? роботи ?з документом [6].1.2. Значення OCR у б?знес?OCR вбудований у велику к?льк?сть програм, включаючи текстов? редактори, якими користуються люди щодня. Сьогодн?, коли б?льш?сть ?нформац?? поширю?ться за допомогою ?нтернету, ми бачимо компан??, якбагато компан?й перетворюють ?нформац?йн? активи, так? як досл?дницьк? б?бл?отеки та документац??, в електронн? форми. OCR набула ново? значущост? та потенц?алу на ринку [7, 8]. Причиною того, що OCR ? критично корисною технолог??ю, ? те, що витрати на впровадження ново? технолог?? майже завжди менш? за витрати на робочу силу. У б?льшост? випадк?в, для д?лових видань та оф?сних документ?в варт?сть конвертац?? з паперового формату може бути м?н?м?зована - якщо OCR застосову?ться належним чином. Хоча основна мета OCR ? поляга? у зменшенн? витрат на оплату прац?, пов'язаних ?з розп?знаванням документ?в, OCR н?коли не може звести ц? витрати до нуля. Повн?стю автоматичний OCR на сьогодн?шн?й день – неможливий. З ц??? причини робоча сила залиша?ться найб?льшим фактором витрат нав?ть у найефективн?ших програмах. Основна задача – м?н?м?зувати цей фактор [9].Ось чому в наш? дн? багато орган?зац?й використовують програмне забезпечення, яке по?дну? OCR з ?ншими функц?ями, такими як експорт у PDF, що дозволя? витягувати дан? з арх?вованих коп?й документ?в [10]. Для розп?знавання тексту використовуються, зазвичай, два методи: матрична в?дпов?дн?сть (б?льш простий та поширений) ? витяг за характерними ознаками.Матрична в?дпов?дн?сть (також в?домий як пор?вняння з шаблоном). Суть даного методу в пор?внянн? того, що виявля? програма OCR як символ, з б?бл?отекою шаблон?в символ?в. Програмне забезпечення OCR з?ставля? це зображення з в?дпов?дним символом ASCII.Витяг за характерними ознаками (також в?домий, як ICR - Intelligent Character Recognition) - це метод оптичного розп?знавання тексту, який використову? комп'ютерний ?нтелект для пошуку характерних ознак, таких як в?дкрит? област?, замкнут? ф?гури, д?агональн? л?н??, перетин л?н?й ? т. д. Це набагато б?льш гнучкий ? багатогранний метод, але в?н ? б?льш вимогливим для надання усп?шного результату розп?знавання [11].Починаючи з можливост? б?льш швидкого пошуку ? б?льш простого редагування до економ?? цифрового ? ф?зичного простору збер?гання - для кожного знайдуться переваги використання програмного забезпечення з OCR технолог?ями:Повторний передрук. Якщо основним завданням сп?вроб?тника компан?? не ? в?дтворення в цифровому вигляд? надрукованих або в?дсканованих документ?в, то використання OCR програми для цих завдань заощадить масу часу сп?вроб?тнику для виконання його основних завдань.Швидкий цифровий пошук. Перетворюючи в?дсканований текст в ?ндексований PDF файл, за допомогою OCR програми, дозволить в подальшому виконувати пошук необх?дного документа, використовуючи ключов? слова або фрази.Введення нового тексту. Якщо у в?дсканованому документ? необх?дно редагувати, коп?ювати, вставляти ? додавати текст, то функц?онал б?льшост? OCR програм дозволя? це робити в сам?й програм?, без попередньо? конвертац??.Економ?я м?сця. Якщо в оф?с? компан?? збер?гаються паперов? документи, як? займають багато м?сця, використання OCR технолог?й дозволить в?дсканувати ?х в ?ндексован? ? редагован? PDF, як? можна збер?гати на цифрових нос?ях або в хмарних сховищах.Доступн?сть. У ситуац?ях, коли виника? необх?дн?сть надати будь-яку текстову ?нформац?ю людин? з? слабким зором, функц?онал сучасних OCR програм дозволить перетворити будь-як? документи ? файли з текстовою ?нформац??ю в ауд?офайли, як? пот?м можна буде прослухати [12-16]. В к?нц? минулого стол?ття на практиц? був реал?зований новий п?дх?д до OCR з використанням неч?тко? лог?ки. Програма висувала не одну, а к?лька г?потез щодо кожного символу, причому кожн?й з них привласнювала рейтинг, який мав в?дображати ступ?нь впевненост? в дан?й г?потез?. При обробц? списк?в г?потез до уваги бралися р?зн? обставини, наприклад наявн?сть або в?дсутн?сть слова в словнику, при цьому в?дпов?дно зм?нювався рейтинг кожно? г?потези. В к?нц? списки надходили в розпорядження так званого експерта - алгоритма вибору, за яким ? залишалося вир?шальне слово. Як правило, в таких системах правильним вважа?ться символ, чия г?потеза набрала максимальний сумарний рейтинг [17-18].Сл?д зазначити, що сучасн? OCR-системи вир?шують набагато складн?ш? завдання, н?ж ?х попередники. Простим розп?знаванням тексту тепер н?кого не здиву?ш. Потреби користувач?в зросли, ? п?дляга? розп?знаванню документ часто вигляда? набагато складн?ше, н?ж б?ла стор?нка з чорним текстом - ?люстрац??, таблиц?, колонтитули, фонов? зображення та ?нш? оформлювальн? елементи ускладнюють ?? структуру. Для того щоб коректно в?дтворювати в електронному вигляд? так? документи, вс? сучасн? OCR-програми починають розп?знавання саме з анал?зу структури. Як правило, при цьому вид?ляють к?лька ??рарх?чно орган?зованих лог?чних р?вн?в. Об'?кт найвищого р?вня т?льки один - власне стор?нка, на наступному ступен? ??рарх?? розташовуються таблиця ? текстовий блок, пот?м осередок таблиц?, абзац або картинка, за ними сл?ду? рядок, пот?м слово або картинка всередин? рядка ?, нарешт?, нижн?й р?вень – символ [19,20].Зрозум?ло, що будь-який високор?вневий об'?кт може бути представлений як наб?р об'?кт?в нижчого р?вня: л?тери утворюють слова, слова - рядки ? т.д. Тому анал?з завжди почина?ться в напрямку зверху вниз. Програма д?лить стор?нку на об'?кти, ?х, в свою чергу, на об'?кти нижчих р?вн?в ? т.д., аж до символ?в. Коли символи вид?лен? ? розп?знан?, почина?ться зворотн?й процес - зб?рка об'?кт?в вищих р?вн?в, яка завершу?ться формуванням ц?ло? стор?нки. Така процедура назива?ться багатор?вневим анал?зом документа, або MDA (Мultilevel document Analysis).Таким чином, завдання розп?знавання окремого символу, над яким працювали останн? п?встол?ття безл?ч фах?вц?в, хоча ? не ма? ?деального р?шення, але близьке до цього, а тому дещо в?д?йшла на задн?й план, ставши лише одн??ю з багатьох ступен?в лог?чних сход?в, що ведуть користувача в?д паперово? стор?нки до ?? електронно? коп??. Навчити комп'ютер читати - завдання не з легких, ?, незважаючи на значн? досягнення в ц?й сфер?, помилки час в?д часу (зазвичай в документах з рясними граф?чними вкрапленнями) прослизають. Але оск?льки розп?знавання, як правило, займа? набагато менше часу, н?ж введення того ж обсягу тексту з клав?атури, прогрес очевидний. Слова ?як правило? вжит? не випадково. Бувають кл?н?чн? випадки, коли доводиться помучитися з якою-небудь стор?нкою журналу, що м?стить багато ?люстрац?й ? таблиць, як? вперто не хочуть приймати в остаточному вар?ант? сво? початкове положення ? все намагаються куди-небудь сповзти, захоплюючи за собою текст.В даний час на ринку систем розп?знавання ?сну? ряд розробок, ор??нтованих як на р?зн? сфери д?яльност? користувача, так ? на р?зн? платформи [21].1.3. Огляд наи?популярн?ших реал?зац?и? OCRРозглянемо та пор?вня?мо готов? реал?зац??? б?бл?отек для автоматичного розп?знавання тексту для мови програмування Java.1.3.1. ABBYY FineReader1727224521200ABBYY FineReader - програма для автоматичного розп?знавання символ?в, що розроблена рос?йською компан??ю ABBYY. Рис. 1.1. ?нтерфейс Abbyy FineReaderПрограма швидко ? з точн?стю розп?зна? в?дсканован? або сфотографован? документи, перетворюючи ?х в електронн? редагован? формати або PDF з можлив?стю пошуку. При розп?знаванн? як?сних документ?в швидкий режим зб?льшить швидк?сть на 40?% без шкоди для точност?. А для чорно-б?лих документ?в можна використовувати також чорно-б?лий режим розп?знавання, який прискорить роботу ще на 30?%. Завдяки технолог?? Adaptive Document Recognition Technology, ABBYY FineReader 12 збер?га? вих?дну структуру багатостор?нкових документ?в, включаючи розташування тексту, таблиць, колонтитул?в, прим?ток, нумерац?ю стор?нок, зм?сту, зм?сту та ?н. Задати типи областей (Текст, Картинка, Таблиця ? ?н.) ? вказати ?х призначення, можна ? вручну. ABBYY FineReader 12 розп?зна? документи на 190 мовах, в будь-яких комб?нац?ях. ABBYY FineReader 12 вм?? справлятися як з спотвореннями, характерними для цифрових фотограф?й (трапец??под?бн? спотворення, викривленння рядка, цифровий шум, ? так дал?), так ? з дефектами зображення, пов'язаними з? станом вих?дних паперових документ?в (пожовклий в?д часу пап?р, рукописн? позначки, штампи) [22].Переваги: 1) ?П?дтимка велико? к?лькост? мов. 2) ?Висока точн?сть розп?знавання; 3) ?П?дтимка велико? к?лькост? формат?в. Недол?ки: 1) ?Платна л?ценз?я; 2) Так? переваги, як виявлення спотворень та дефект?в зменшують швидк?сть розп?знавання, та не мають сенсу у випадку розп?знвання в?дсканованих докумен?в.1.3.2. TesseractTesseract?—?в?льна?програмне забезпечення?для?розп?знавання текст?в, що розроблялася?Hewlett-Packard?з 1985 до 1994 року, а в наступне десятир?ччя залишалася практично без зм?н. Не так давно?Google?купив ?? та в?дкрив?початковий код?п?д?л?ценз??ю Apache 2.0?у 2006 роц??для продовження розробки. У цей час програма вже працю? з?UTF-8, розп?зна? багато мов, серед яких ??укра?нська. Tesseract був у тр?йц? найкращих двигун?в OCR за р?внем точност? символ?в у 1995 роц?. В?н доступний для Linux, Windows та Mac OS X [23].Tesseract до верс?? 2, включаючи верс?ю 2, м?г приймати лише зображення TIFF як вх?дн? дан?. Ц? ранн? верс?? не включали анал?з верстки, ? таким чином рукописний текст та зображененя створювали проблеми при розп?знаванн?. Починаючи з верс?? 3, Tesseract п?дтриму? форматування вих?дного тексту – hOCR ?з позиц?йною ?нформац??ю та анал?зом макет?в стор?нок. П?дтримка ряду нових формат?в зображень була додана за допомогою б?бл?отеки Leptonica. Tesseract може виявити, чи ? текст одноб?чним чи пропорц?йно розташованим.Початков? верс?? Tesseract могли розп?знавати лише англомовний текст. Tesseract v2 додав ш?сть додаткових зах?дних мов (французька, ?тал?йська, н?мецька, ?спанська, бразильська португальська, голландська). Верс?я 3 значно розширила п?дтримку мов, включаючи ?деограф?чну (китайську та японську) та праворуч-л?ву (наприклад, арабську, ?врит) мови, а також багато ?нших сценар??в. До нових мов належать арабська, болгарська, каталанська, китайська (спрощена та традиц?йна), хорватська, чеська, датська, н?мецька, грецька, ф?нська, ?врит, х?нд?, угорська, ?ндонез?йська, японська, корейська, латв?йська, литовська, норвезька, польська, португальська, румунська, рос?йська, сербська, словацька, словенська, шведська, тагалогська, там?льська, тайська, турецька, укра?нська та в'?тнамська. V3.04, випущенна у липн? 2015 року, додала ще 39 комб?нац?й мови / письма, що зб?льшило к?льк?сть мов п?дтримки у понад 100. Кр?м того, Tesseract може бути навчений працювати на ?нших мовах.Tesseract п?дходить для використання в якост? резервного серв?су ? може використовуватися для б?льш складних завдань OCR, включаючи анал?з верстки, використовуючи ?нтерфейс, такий як OCRopus.Робота Tesseract буде мати дуже низьку як?сть, якщо вх?дн? зображення не будуть попередньо оброблен? в?дпов?дно до нього: Зображення (особливо скр?ншоти) повинн? бути зменшен? таким чином, щоб висота тексту становила не менше 20 п?ксел?в, будь-яке обертання або перекос потр?бно виправити або жоден текст не буде розп?знаний, низькочастотн? зм?ни яскравост? повинн? бути в?дф?льтрован? високою прох?дн?стю, або етап б?наризац?? Tesseract знищить значну частину стор?нки, а темн? меж? потр?бно видалити вручну, або вони будуть неправильно трактуватися як символи [24].Ядро програми Tesseract було розроблено в Бристольской лаборатор?? Hewlett Packard ? в Hewlett Packard Co, Greeley штат Колорадо в 1985-1994 роках. У 1996 були проведен? значн? зм?ни ? п?дготовлений порт для Windows. Пот?м, з 1998 року - часткова м?грац?я з С? на С? ++. Значна частина коду спочатку написана на С?, але проводилися доопрацювання для сум?сност? з С? ++ компиляторами. В даний час Tesseract 3.0 збира?ться п?д Linux з GCC 2.95 ? старше ? п?д Windows з Visual C ++ 2008 Express ? старше (п?дтримка Visual C ++ 6 була видалена в верс?? 3.0).На даний момент останньою верс??ю ? Tesseract 4.0, заснована на LSTM.Переваги: 1) ?Apache л?ценз?я, а отже - безкоштовне використання; 2) ?П?дтримка велико? к?лькост? мов; 3) ?П?дтримка велико? к?лькост? формат?в; Недол?ки: 1) Невелика швидк?сть роботи; 2) Неяк?сне розп?знавання деяких шрифт?в;1.3.3. AspriseAsprise OCR ? комерц?йною оптичною розп?знаванням символ?в та б?бл?отекою SDK для розп?знавання штрих-код?в, яка нада? API для розп?знавання тексту, а також штрих-код?в ?з зображень (у форматах JPEG, PNG, TIFF, PDF тощо) ? виводиться у форматах, як звичайний текст, xml ? PDF для пошуку.Компан?я Asprise OCR активно розвива?ться з 1997 року. Верс?я 2.1 програмного забезпечення була переглянута компан??ю PC World.Багато досл?дник?в використовували OCR разом з ABBYY FineReader для тестування продуктивност? OCR. Павел Купковський ? Мар?уш Урбанський з Ун?верситету Адама М?цкевича в Познан? використовують Asprise OCR верс?? 4 ? ABBYY FineReader для виконання розп?знавання CAPTCHA. У робот? "Удосконалення процесу оптичного розп?знавання зображень для зображень з низькою розд?льною здатн?стю" досл?дники з Universiti Utara в Малайз?? використовують Asprise OCR v4.0 як один з ор??нтир?в ? пропону? "новий метод, спрямований на пол?пшення якост? зображення, щоб зменшити WER". Шуай Юань з Корнельського Ун?верситету реал?зував систему пошуку граф?к?в прим?щень за допомогою програми OCR. Seongwook Youn з Ун?верситету П?вденно? Кал?форн?? знайшов: ?За допомогою виб?рки з 200 електронних пов?домлень ми визначили, що оптичне розп?знавання Asprise викону?ться з точн?стю до 95%. Ад?л Фарук з ?нженерно-технолог?чного ун?верситету в Таксил? впровадив систему ?нтерфейсу для людей з вадами зору.Воно анал?зу? робочий процес двигуна Asprise OCR ? застосову? його для виявлення табло для бейсбольних в?део. для антиспаму за допомогою розп?знавального засобу Asprise.Наступн? мови п?дтримуються верс??ю Asprise 5: хорватська, чеська, датська, голландська, англ?йська, ф?нська, французька, н?мецька, грецька, угорська, ?сландська, ?ндонез?йська, ?тал?йська, малайська, мальт?йська, норвезька, польська, португальська, румунська, рос?йська, ?спанська, шведська або турецька. MRZ ? MICR п?дтримуються [25].Остання верс?я Asprise OCR SDK ? v15.Переваги: 1) Точне розп?знавання; 2) Висока швидк?сть роботи; 3) Досить зрохум?ле APIНедол?ки: 1) Дуже велика ц?на за л?ценз?ю.1.3.4. NicomsoftNicomsoft OCR SDK ? б?бл?отекою OCR, яка дозволя? розробникам легко вбудовувати високояк?сну функц?ю оптичного розп?знавання символ?в у сво? продукти. Заснована на ун?кальн?й технолог?? анал?зу символ?в, яка дозволя? точно розп?знавати будь-як? шрифти нав?ть при неяк?сних зображеннях.Нище приведений список основних можливостей б?бл?отеки:Використову? розширен? алгоритми для анал?зу зображень низько? якост?, як? можуть м?стити спотворен?, пов'язан? та розбит? символи.Використову? словники для кращого визнання.П?дтриму? 26 мов: болгарська, каталонська, хорватська, чеська, датська, голландська, англ?йська, естонська, ф?нська, французька, н?мецька, угорська, ?ндонез?йська, ?тал?йська, латиська, литовська, норвезька, польська, португальська, румунська, словацька ?спанська, шведська та турецька.Модуль аз?атського розп?знавання, який п?дтриму? 5 аз?атських мов: спрощений китайський, традиц?йний китайський, арабський, японський, корейський.Можна сканувати документи з TWAIN-сум?сних пристро?в.П?дтриму? штрих-коди: EAN-13 / UPC-A, UPC-E, EAN-8, Code 128, Code 39, Interleaved 2 of 5 ? QR Code.П?дтриму? багатоядерн? процесори для прискорення розп?знавання нав?ть окремих фрагмент?в тексту за допомогою ефективно? паралельно? обробки.П?дтриму? багато формат?в зображень, включаючи так? популярн?, як BMP, JPEG, PNG, TIFF ? GIF.Можна збер?гати розп?знан? документи як PDF, PDF / A, RTF, XML або TXT файли, а також як потоки пам'ят?.Ма? ?нту?тивно зрозум?лий API OCR ? включа? зразков? проекти з повним вих?дним кодом для р?зних мов програмування.? кросплатформенним р?шенням OCR: п?дтриму? платформи Windows та Linux. Можна завантажити зображення з файлу, пам’ят? або даних ?з необроблених п?ксел?в. Можна сканувати документи: п?дтримуються ? ?нтерфейси TWAIN, ? WIA (лише верс?я Windows, не п?дтриму?ться у верс?? Linux OCR SDK). П?дтриму? МРЗ (машинна зона читання) для паспорт?в, в?з, посв?дчень особи тощо.Використову?ться розширений алгоритм усунення.Вм?? виявляти неправильно ор??нтован? стор?нки (обертання на 90/180/270 градус?в) та автоматично ф?ксувати ор??нтац?ю. Перед обробкою можна перевернути / обертати / в?добразити все зображення або деяк? текстов? блоки. Може автоматично масштабувати зображення для кращого розп?знавання. Завдяки над?йн?й адаптивн?й б?наризац?? зображень, п?дтриму? зображення з поганою яскрав?стю або низькою контрастн?стю. Може налаштувати параметри б?наризац?? зображень для конкретних зображень. Використову?ться розширений алгоритм анал?зу макета стор?нки (зонування). Може виконувати OCR поетапно ? давати пром?жн? результати. Використову?ться розширений алгоритм виявлення та видалення л?н?й. Може виконувати зональний OCR, тобто дозволя? вибрати одну або к?лька областей для OCR. Дозволя? вказати р?зн? параметри OCR для р?зних областей. Дозволя? вказувати к?лька мов для OCR.Дозволя? вказувати р?зн? мови для р?зних областей в одному зображенн?. Може виявляти та обробляти перевернутий текст. Можна використовувати дек?лька ядер CPU для ще швидшого OCR, нав?ть якщо OCR викону?ться лише для одн??? стор?нки. ? безпечним для поток?в, тобто може обробляти к?лька зображень одночасно за допомогою дек?лькох поток?в. Базу?ться на ун?кальн?й технолог?? анал?зу символ?в, яка може точно розп?знати будь-як? шрифти. Використову? розширен? алгоритми для анал?зу зображень неяк?сно? якост?, як? можуть м?стити спотворен?, пов'язан? та зламан? символи. Використову? словники для найкращого розп?знавання. Дозволя? використовувати визначен? користувачем словники. Може форматувати текст автоматично: видаляти непотр?бн? розриви рядк?в, по?днувати розд?лен? слова, виявляти маркован? списки тощо. Високо оптим?зований для ?нструкц?й SSE для прискорення процесу OCR. Дозволя? зм?нити параметри за замовчуванням та покращити результати OCR, якщо в?дом? деяк? параметри зображення. Дозволя? виключати певн? символи з набору символ?в, якщо це необх?дно. Можна отримати додаткову ?нформац?ю про текстов? рядки, слова та символи: положення, розм?р, як?сть тощо. Дозволя? задавати регулярн? вирази для пол?пшення розп?знавання форматованих даних. Повн?стю п?дтриму? Unicode. Можна завантажувати зображення з пам'ят? та збер?гати розп?знан? документи у пам'ять, а не використовувати файли. ? високомоб?льним: б?нарн? файли OCR та файли даних менше 10 МБ на мову. Ма? простий ?нтерфейс API ? включа? зразки проект?в для р?зних мов програмування: C #, C / C ++, , Delphi, C ++ Builder, Visual Basic, VBScript, JScript. П?дтриму? широкий спектр рамок ? технолог?й: .NET, WPF, WCF, , Silverlight тощо.Б?нарн? файли x86, ? x64 доступн? для Windows та Linux [26].Переваги: 1) ?Точне розп?знавання; 2) ? Висока швидк?сть роботи; 3) Apache л?ценз?я, а отже - безкоштовне використання;4) Сканування штирх-код?в;5) Велика к?льк?сть ?нших можливостей;ВИСНОВОК ДО РОЗД?ЛУ 1Мною було досл?джено б?бл?отеки для розп?знавання символ?в. Основними недол?ками можна назвати високу ц?ну за л?ценз?ю та погана як?сть розп?знавання. Зазвичай це був компром?с м?ж як?стю та ц?ною. Також, деяк? б?бл?отеки досить важк? та незрозум?л? в розробц? через недосконалу документац?ю. Але найкращим р?шенням я вважаю Nicomsoft OCR. Ця б?бл?отека показу? достатню як?сть розп?знавання при в?дстуност? плати за л?ценз?ю. Тому саме ?? я вир?шив використовувати у розробц?.Також перевагою ц??й б?б?л?отеки ? п?дтримка велико? к?лькост? мов тексту для розп?знавання, що буде важливим при масштабуванн? системи. Кр?м того, велика к?льк?сть п?дтривуаних формат?в та вм?ння розп?знавати шртих-коди значно розширу? коло потенц?йних замовник?в.А доступн?сть використання б?б?л?отеки великою к?льк?стю мов програмування дозволя? розробити систему та впровадити ?? у будь-яку ?ншу.Пом?ж цього б?бл?отека ма? дуже орган?зовано та зрозум?ло скомпоноване API, що значно спрстить етап розробки.РОЗД?Л 2АНАЛ?З ЗАДАЧ? ТА ОГЛЯД ТЕХНОЛОГ?Й2.1. Опис предметно? област?2.1.1. Повний опис б?знес процесуДана система розроблялась задля автоматизац?? б?знес-процесу розп?знавання рекв?зит?в документ?в. Для розробки та тестування був в?дпрацьований та реал?зований б?знес процес ?з наступними вимогами:В автоматизован?й систем? забезпечення закуп?вель проводиться обл?к замовлень на здобуття товар?в ? пропозиц?й по ?х реал?зац??. Заявки формуються ? збер?гаються в баз? даних системи в формальному вигляд?, а друкована коп?я у вигляд? паперового документа або текстового файлу надсила?ться постачальникам. У в?дпов?дь на заявку постачальники нвдсилають рахунок, що м?стить пропозиц?ю на поставку ?з зазначеними обсягом ? варт?стю поставки, як? повинн? бути врахован? в систем? ? збережен? у базу даних у формальному вигляд? ? сп?вв?днесен? з наявними заявками. Рахунки надходять у вигляд? паперових документ?в або ?х скан коп?й у формат? растрового зображення (png, pdf, jpeg ? т. п.) ? вимагають введення в систему у вигляд? сукупност? рекв?зит?в документа. Через великий обсяг документ?в, що надходять потр?бна автоматизац?я отримання необх?дних рекв?зит?в у цифровому вигляд? ? занесення ?х в БД у прийнят?й структур? безпосередньо з растрового представлення документа з м?н?мальною участю оператора.Коп?? рахунк?в в?д контрагент?в надходять у вигляд? паперових документ?в, як? скануються, ? файл результату сканування у вигляд? растрового зображення в одному з стандартизованих формат?в, що збер?гаються в баз? даних в б?нарному вигляд?, ун?кально ?дентиф?куються ? позначаються як не оброблен?. Деяк? документи можуть надходити в?дразу у файл в?дсканованого документа ? також збер?гаються в баз? даних, як ? файли з в?дсканованих документ?в. Для формування електронних рахунк?в з растрових документ?в пер?одично запуска?ться модуль автоматичного розп?знавання, який:? перегляда? не оброблен? документи в баз? растрових зображень;? для кожного необробленого документа за певними ознаками розбива? растрове зображення на зони тексту ? зображення ? буквально розп?зна? растрове в?дображення букв в текстових зонах ? форму? ?х текстове представлення;? у сформованих текстових фрагментах за певними ключовими словами знаходить в текст? рекв?зити рахунка ? з?ставля? ?х з наявними рекв?зитами сутностей БД (контрагенти заявки) ? з?ставля? рахунок з цими сутностями;? у раз? усп?шного виявлення вс?х необх?дних рекв?зит?в ? сп?вв?днесення ?х з сутностями БД документ познача?ться як оброблений;? у випадку якщо з якихось причин не вдалося виявити в?дсутн?й рекв?зит або сп?вв?днести його з наявно? сутн?стю в БД, документ познача?ться як портебуючий ручного розп?знавання;Документи, як? не вдалося розп?знати ? сп?вв?днести з сутностями БД розп?знаються оператором ? сп?вв?дносяться з сутностями БД вручну за допомогою модуля ручного розп?знавання (?нтерфейсний модуль).Електронний документ ?рахунок? м?стить певний наб?р рекв?зит?в ? сп?в-в?дноситься з контрагентом (постачальником), в?д якого в?н над?йшов ? заявц?, для яко? в?н складений.Документи подаються контрагентами, як правило, на бланках певного типу. Кожен контрагент може використовувати певний наб?р тип?в бланк?в. Для кожного типу бланка п?дтриму?ться метаопис, в якому визначен? текстов? зони ? для кожного рекв?зиту вказан? зона, в як?й вони розташован? ? ключове слово, п?сля якого власне ? сл?д шукати цей рекв?зит. Процес розп?знавання почина?ться з того, що за певними ознаками бланк розбива?ться на текстов? зони. Серед метаопис?в бланк?в розшукуються бланки, як? зб?га?ться ?з рекв?зитами контрагента (адреса електроно? пошти, назва компан??, моб?льний номер). Для знайдених бланк?в, зони, що м?стять ключов? рекв?зити контрагента перетворюються в текст ? з них у вказаному м?сц? вичленяються рекв?зити, як? й мають бути виокремлен?. Якщо постачальник знайдений, в?дпов?дний бланк використову?ться для подальшого розп?знавання, якщо н?, то тип бланка познача?ться як новий. Зони, що м?стять необх?дн? рекв?зити перетворюються в текст ? значення рекв?зит?в виокремлюються. Проводиться перев?рка значень на достов?рн?сть ? сп?вв?днесення ?з сутностями.Якщо вс? рекв?зити розп?знан? й з?ставлен? - документ познача?ться як оброблений. Якщо н?, то познача?ться як ?вимага? ручного розп?знавання?.2.1.2. Основн? задач? та склад системиСистема розп?знавання рекв?зит?в документ?в по зображенню склада?ться ?з б?бл?отеки для розп?знавання тексту та реал?зац?? специф?чних б?знес-процес?в до яких в?дносяться ц? документи. В мо?му приклад?, в якост? таких документ?в рахунки за надан? послуги та товари.Будь-який рахунок ма? наб?р певних рекв?зит?в, таких як: номер рахунку, номер замовлення, дата замовлення, сума без ПДВ, ПДВ, загальна сума та рекв?зити постачальника. До рекв?зит?в постачальника в?дносяться його моб?льний номер, електронна пошта та назва компан?? постачальника. Така система розп?знавання рекв?зит?в документ?в по зображенню дозволя? значно скоротити час будь-якому п?дпри?мству, яке регулярно проводить закуп?вл? у великих об’?мах, завдяки тому, що автоматизу? процес завдення даних про закуп?вл? у базу даних.Основн? задач? системи розп?знавання рекв?зит?в документ?в по зображенню:Точно розп?знавати текст по зображенню;Виокремлювати потр?бн? дан? ?з тексту;Збер?гати дан? у базу даних;При розробц? системи виникла проблема точност? отримання необх?дних даних. П?сля того, як текст по зображенню розп?знаний - потр?бно в?докремити в?д нього необх?дн? рекв?зити. Також, складност? додавало те, що у кожного постачальника св?й тип рахунку, ? рекв?зити знаходяться в р?зних частинах документу. Часом рекв?зити н?як не промаркован?. Тому було прийнято р?шення впровадити в систему алгоритм навчання для отримання рекв?зит?в. При навчанн?, користувач розп?знаватиме рекв?зити самост?йно, введе ?х у систему, а система в свою чергу запамята? ?х м?сцезнаходження на документ? та ключов? слова за якими ?х можна знайти. Навчання потр?бно проводити откремо для кожного типу рахунку в залежност? в?д постачальника. При навчанн? для кожного типу бланку поставчальника створю?ться шаблон ?з даними про м?сцезнаходження рекв?зит?в на документ? та ?х ключов? слова.П?сля цього, система вже самост?йно зможе розп?знавати вс? рахунки в?д цього постачальника.Отже система ма? складатися ?з: модуля розп?знавання тексту, модуля навчання виокремлення потр?бних рекв?зит?в, модуля, який би перев?ряв документ що над?йшов на предмет ?снування шаблону його типу у баз? даних. Все це ма? бути пов’язано сп?льним ?нтерфейсом та зв’язком ?з базою даних.2.2. Виб?р технолог?и? та ??х об?рунтування 2.2.1. Виб?р платформи та мови програмування для системиВимоги як? ставляться до системи вимагають ?? бути досить гнучкою та легко-вбудованою в ?нш? корпоративн? системи, як? автоматизують б?знес-процеси. На сьогодн?шн?й день, мова програмування Java залиша?ться л?дером на ринку мов для розробки програмного забезпечення для автоматизац?? б?знес-процес?в. Розробка мо?? системи на мов? Java дозволить без проблем вбудувати ?? як окремий модуль. Та нав?ть якщо потр?бно буде вбудувати систему у ?ншу, написану не на мов? Java, це не стане проблемою.Java - одна з найнад?йн?ших мов програмування, яка використову?ться для розробки невеликих додатк?в до великого корпоративного програмного забезпечення. Розробка додатк?в Java допомага? п?дпри?мствам досягти конкурентних переваг завдяки сво?й баз? в?дкритого вих?дного коду та п?дтримц? величезно? сп?льноти користувач?в. Java допомага? ?Т-?ндустр?? вже б?льше 20 рок?в. З посиленням конкуренц?? на ринок вийшло багато нових ?нструмент?в для вир?шення проблем п?дпри?мства, але Java все ще дом?ну? на ринку. Найдавн?ша ? широко використовувана мова програмування - Java керу? галуззю з 90-х рок?в, коли веб-розробка починала дозр?вати, ? п?дпри?мства шукали б?льш над?йного програмування пор?вняно з C ? C ++. Java стала мовою за замовчуванням для б?льшост? п?дпри?мств завдяки незалежному в?д платформи коду та гнучкост? ?нтеграц??. Саме гнучк?сть Java зробило ?? мовою номер один, для розробки корпортативних систем. Java в св?й час зробила ?революц?ю? у св?т? розробки програмного забезпечення. Java п?дтриму? широкий наб?р б?бл?отек - б?бл?отеки служать основними складовими для будь-якого р?шення п?дпри?мства, а Java п?дтриму? м?льйони б?бл?отек та код?в. П?дпри?мства вибирають Java як найб?льш п?дходящу мову, оск?льки вона вир?шу? найпоширен?ш? проблеми, що виникають при розробц? корпоративних програм.Легка ?нтеграц?я та масштабован?сть - маючи величезну сп?льноту користувач?в, Java ? дуже зручним ?нструментом для розробки корпоративних систем. Багато хостинг-провайдер?в п?дтримують код Java для розм?щення сво?х веб-додатк?в. Hadoop, велике ?м'я у Big Data також написане на Java. Java також високо масштабована, що дозволя? п?дпри?мствам нарощувати потреби в розробц? додатк?в в?дпов?дно до потреб. П?дтриму? дек?лька пристро?в, низьку варт?сть обслуговування та б?льш швидку обробку - Java може працювати на будь-як?й апаратн?й ?нфраструктур? з поточними процесорами, зменшуючи техн?чну залежн?сть. Налаштування та обслуговування сервера Java дешевше пор?вняно з серверами Windows, Mac. Java п?дтриму? багато апаратних пристро?в, таких як моб?льн? телефони, що робить його б?льш придатним для б?знесу. Нав?ть системи невеликого сегмента можуть легко використовувати його для отримання максимальних переваг для б?знесу [26].Також з’являються вимоги в зв’язку з використанням б?бл?отеки Nicomsoft OCR. Розробники б?бл?отеки зробили ?? доступною для багатьох мов прогрумування та операц?йних систем. В тому числ? ? для Java.2.2.2. ?нтерфейси, функц?? та об’?кти б?бл?отеки Nicomsoft OCRБ?бл?отека Nicomsoft OCR (NSOCR) - це наб?р x86 / x64 б?нарних файл?в. Щоб використовувати таку б?бл?отеку на Java, потр?бна прокс?-б?бл?отека, розроблена в?дпов?дно до Java Native Interface (JNI). У SDK NSOCR вже включена прокс?-б?бл?отека "JNSOCR", яка реал?зу? ?нтерфейс JNE ? працю? м?ж в?ртуальною машиною Java та р?дною б?бл?отекою NSOCR.1639570512699000Схема вза?мод?? б?бл?отеки JNSOCR ?з ?ншими пакетами системи зображена на рис.2.1.Рис. 2.1. Схема вза?мод?? пакет?в JNSOCR та ?нших пакет?в системи [27]Для коректно? роботи б?б?лотеки та вс?х ?? функц?й, шлях до дириктор?й ?з б?нарними файлами потр?бно вказати у системних зм?нних. Б?льш детально розглянут? класи пакету NSOCR у табл. 2.2.Табл. 2.2.Класи пакету NSOCRColorКлас ?з набором статичних полей кольор?в типу Color, ?мпортовано? ?з пакету java.awt ConstantКлас ?з набором основних контант, як? використовуються у функц?ях.EngineОсновний клас пакету. В?н в?дпов?да? за завантаження б?нарних файл?в б?бл?отеки та нада? ?нтерфейс для виклику функц?й б?бл?отеки.ErrorКлас ?з набором код?в основних помилок.HBLKКлас, позначаючий блок розп?знаного тексту у систем? Nicomsoft.HCFGКлас, ?з параметрами для конф?гурац?? роботи б?бл?отеки.HIMGКлас, позначаючий зображення у систем? Nicomsoft.HOCRКлас для виклику модуля розп?знавання.HSCANКлас для виклику функц?? сканування файлу.HSVRКлас для збереження результат?в розп?знавання у файл.NSIntВласний тип натурального числа.Як бачимо, розробники б?б?л?отеки вже створили вс? типи та ?нтерфейси для виклику та використання б?нарних файл?в б?бл?отеки. Нище описано кожен об’?кт системи Nicomsoft б?льш детально.NSOCR використову? так? об’?кти:Об'?кт CFG. Об'?кт "Налаштування" збер?га? та керу? налаштуваннями OCR. У б?льшост? випадк?в потр?бно створити лише один об'?кт CFG, а вс? ?нш? створен? об’?кти використовуватимуть його для доступу до налаштувань OCR. Створення дек?лькох об'?кт?в CFG необх?дно лише в тому випадку, якщо використовуються р?зн? налаштування для к?лькох об'?кт?в OCR.Об'?кт OCR. Об'?кт "OCR" обробля? процес OCR. В?н управля? вс?ма ресурсами, необх?дними для OCR. У б?льшост? випадк?в потр?бно створити лише один об'?кт OCR, який буде обробляти зображення по одному. Створення дек?лькох об'?кт?в OCR необх?дне лише в тому випадку, якщо програма ? багатопотоковою ? треба обробляти к?лька зображень одночасно.Об'?кт IMG. Об'?кт "Зображення" обробля? зображення для OCR. Зображення можна завантажити з файлу на диску, з файлу в пам'ят? або з растрово? карти пам'ят?. Зображення може складатися з одн??? або дек?лькох стор?нок. П?дтримуються багато формат?в файл?в зображень, включаючи BMP, JPEG, PNG, TIFF та GIF. Формат PDF п?дтриму?ться через б?бл?отеку GhostScript.Об'?кт BLK. Об'?кт "Блок" обробля? зону зображення для OCR. Цей об'?кт використову?ться для визначення розм?ру, положення та типу зони, отримання розп?знаного тексту тощо.SVR об’?кт. Об'?кт "Saver" збер?га? результати OCR у файл або в пам'ять. П?дтриму?ться к?лька формат?в: ANSI TXT, Unicode TXT, RTF, PDF та XML. ?снують додатков? параметри збереження: виб?р розм?ру стор?нки, перекриття тексту для PDF, виб?р DPI для зображень, параметри форматування тощо.Об'?кт SCAN. Об'?кт "Скан" скану? зображення ?з сум?сних пристро?в TWAIN або WIA. В?дскановане зображення можна розм?стити в об’?кт? IMG або зберегти у файл або в пам'ять. Зображення може м?стити одну або к?лька стор?нок. Можна вибрати скануючий пристр?й. Також можна встановити DPI, глибину кольору та ?нш? настройки сканування.[27]Як було сказано вище, для роботи системи ?з файлами формату PDF, в операц?йн?й систем? ма? бути встановлений GhostScript. Ghostscript?— це комплекс?програмного забезпечення, яке склада?ться з:?нтерпретатора?мови?PostScript?? та?Adobe?Portable Document Format (PDF?формат);множини процедур (б?бл?отека Ghostscript)?C, як? забезпечують граф?чн? та ф?льтрувальн? (стиснення даних / декомпрес?я / конвертац?я) засоби, що наявн? як прим?тивн? операц?? на мов? PostScript та в PDF.?нструментар?й дозволя? обробляти як мову Postscript так ? документи PDF, переводити ?х в растров? формати для показу на екран? або для виведення на друк на?принтерах?без п?дтримки Postscript.GhostScript поширю?ться п?д л?ценз??ю AGPLv3, а вм?ст каталогу CMap за спец?альною л?ценз??ю?Adobe.Вже описаний пакет NSOCR ма? методи, завдяки яким ? в?дбува?ться освна вза?мод?я ?з процесом розп?знавання. Нище в таблиц? 2.3 будуть показан? основн? з них.Табл. 2.3.Основн? методи пакету NSOCREngine_Initialize?н?ц?ал?зац?я б?бл?отекиOcr_CreateСтворення об’?кта OCRImg_LoadFileЗавантаження зображення для розп?знавання ?з локального файлуImg_LoadFromMemoryЗавантаження зображення для розп?знавання ?з масиву байт?вImg_GetBmpDataОтримання розм?ру зображенняImg_OCRЗапуск процесу розп?знаванняImg_GetImgTextОтримання розп?знаного текстуImg_GetBlockОтримання блоку ?з розп?знаного документуBlk_GetTextОтримання тексту ?з певного блоку2.2.3. Виб?р б?бл?отеки для проектування ?нтерфейсу?нтерфейсний режим роботи системи був створений для реал?зац?? функц?? ?навчання? системи р?зних шаблон?в бланк?в. Основна вимога для ?нтерфейсу - бути ?нту?тивно зрозум?лим, щоб прац?вник ?з будь-якою квал?ф?кац??ю м?г проводити начання системи. Основна вимога для ?нтерфейсного модулю - мати можлив?сть лего вбудовуватись у ?нш? системи та не вимагати багато ресурс?в комп’ютера. Це дозволя? зробити б?бл?отека Swing. Swing?— ?нструментар?й для створення граф?чного ?нтерфейсу користувача (GUI) мовою програмування?Java. Це частина?б?бл?отеки базових клас?в Java?(JFC, Java Foundation Classes).Swing розробляли для забезпечення функц?ональн?шого набору програмних компонент?в для створення?граф?чного ?нтерфейсу користувача. Компоненти Swing п?дтримують специф?чн??look-and-feel?модул?, що динам?чно п?дключаються. Завдяки ним можлива емуляц?я граф?чного ?нтерфейсу платформи (тобто до компоненту можна динам?чно п?дключити ?нш?, специф?чн? для дано? операц?йно? системи вигляд ? повед?нку). Основним недол?ком таких компонент?в ? в?дносно пов?льна робота, хоча останн?м часом це не вдалося п?дтвердити через зростання потужност? персональних комп'ютер?в. У будь-якому випадку, нав?ть така повед?нка Swing може дати фору у оптим?зац?? ?ншим популярним ?нструментам для розробки граф?чного ?нтерфейсу. Позитивна сторона — ун?версальн?сть ?нтерфейсу створених програм на вс?х платформах.Незалежн?сть в?д платформи: Swing?— платформо-незалежна б?бл?отека, що означа?, що програму з використанням Swing можна запустити на вс?х платформах, як? п?дтримують?JVM.Можлив?сть для розширення: Swing?— дуже розпод?лена арх?тектура, яка дозволя? ?п?дключати? реал?зац?? користувача вказано? ?нфраструктури ?нтерфейс?в: користувач? можуть створити свою власну реал?зац?ю цих компонент?в, щоб зам?нити компоненти без обумовлення (за замовчуванням). Саме цей фактор робить Swing д?йсно об’?ктно-ор?ентовним ?нструментом для розробки граф?чного ?нтерфейсу. Взагал?, користувач? Swing можуть розширити структуру, продовжуючи (за допомогою?extends) ?снуюч? класи ?/або створюючи альтернативн? реал?зац?? основних компонент?в. ? питання з приводу актуальност? ц??? б?бл?отеки у наш? дн?, але на них легко в?дпов?сти.Swing - найменш вимоглива ?нтерфейсна б?бл?отека в план? потужностей та ресурс?в. Розроблений ?нтерфейсний модуль буде ?легким?, не вимогливим та матиме можлив?сть без проблем вбудовуватись у будь-яку ?ншу систему, на в?дм?ну в?д такого самого на баз? JavaFX.Б?льш?сть ?снуючих баз код?в Java GUI ? Swing ?, швидше за все, так ? залишиться. 2.2.4. Виб?р СУБДЗвичайно, кожне п?дпри?мство ма? свою базу даних ?з документами на р?зних СУБД. Питання вибору СУБД саме для системи розп?знавання рекв?зит?в документ?в по зображення не сто?ть. Лише питання орган?зац?? та схеми таблиць для збереження даних, необх?дних для системи.Тому в даному випадку я використовував СУБД Firebird, бо саме на баз? не? була база даних ?з документами, як? я використоував п?д час тестування та проектування системи.Firebird (FirebirdSQL) — в?льна платформна реляц?йна система управл?ння базами даних (РСУБД), що працю? на macOS, Linux, Microsoft Windows ? р?зноман?тних Unix платформах.Firebird використову?ться в р?зних промислових системах (складськ? та господарськ?, ф?нансовий ? державний сектори) з 2001 р. Це комерц?йно незалежний проект C ? C + + програм?ст?в, техн?чних радник?в.Firebird ? сервером баз даних. Один сервер Firebird може обробляти к?лька сотень незалежних баз даних, кожну з безл?ччю користувальницьких сполук. В?н ? повн?стю в?льним в?д л?ценз?йних в?драхувань нав?ть для комерц?йного використання.Основним параметром вибору СУБД саме Firebird SQL, була його гнучк?сть, а саме те, що його вбудована верс?я ма? дуже маленький об’?м, при цьому маючи можлив?сть зберегати величезну к?льк?сть даних. А самец ей параметр – основний при розробц? вбудовано? системи.В?дпов?дн?сть вимогам ACID: Firebird зроблений спец?ально, щоб задовольняти вимогам ?атомарностs, ц?л?сност?, ?золяц?? та над?йност?? транзакц?й (?Atomicity, Consistency, Isolation and Durability?) [28].Генератори: ?дея генератор?в (посл?довностей) робить можливою просту реал?зац?ю авто?нкрементних пол?в, ? не т?льки ?х. Генератори ? 64‐б?тними збереженими в баз? даних л?чильниками, як? працюють незалежно в?д транзакц?й. Вони можуть бути використан? для р?зних ц?лей, таких як генерац?я первинних ключ?в, управл?ння тривалими запитами в сус?дн?х транзакц??, ? т. д.Бази даних т?льки для читання: дозволяють поширювати бази даних, наприклад, на CD-ROM. Особливо спрощу? розповсюдження даних ?х використання в комб?нац?? з вбудовано? верс??ю сервера Firebird (Firebird Embedded).Верс?йна арх?тектура: Основна особлив?сть Firebird — верс?йна арх?тектура, що дозволя? серверу обробляти р?зн? верс?? одного й бого самого запису в будь-який час таким чином, що кожна транзакц?я бачить свою верс?ю даних, не заважаючи сус?дн?м (?читаюч? транзакц?? не блокують пишучи, а пишуть — не блокують блокуючи читанню?). Це дозволя? використовувати одночасно OLTP ? OLAP запити.Збережен? процедури: Використовуючи мову PSQL (процедурний SQL) Firebird, можна створювати складн? процедури для обробки даних на сторон? сервера. Для генерац?? зв?т?в особливо зручн? збережен? процедури з можлив?стю виб?рки, як? повертають дан? у вигляд? набору запис?в. Так? процедури можна використовувати в запитах точно так само, як ? звичайн? таблиц?.Под??: Збережен? процедури ? тригери можуть генерувати под??, на як? може п?дписатися кл??нт. П?сля усп?шного завершення транзакц?? (COMMIT) в?н буде спов?щений про минул? под?? та ?х к?лькост?.Повний контроль за транзакц?ями: Один кл??нтський додаток може виконувати безл?ч одночасних транзакц?й. У р?зних транзакц?ях можуть бути використан? р?зн? р?вн? ?золяц??. Протокол двофазного п?дтвердження транзакц?й забезпечу? гарантовану ст?йк?сть при робот? нав?ть з дек?лькома базами даних. Резервне коп?ювання на льоту: Для резервного коп?ювання нема? потреби зупиняти сервер. Процес резервного коп?ювання збер?га? стан бази даних на момент свого старту, не заважаючи при цьому роботи з базою. Кр?м того, ?сну? можлив?сть виробляти ?нкрементн? резервне коп?ювання БД.Тригери: Для кожно? таблиц? можливе призначення к?лькох тригер?в, що спрацьовують до або п?сля вставки, оновлення та видалення запис?в. Для тригер?в використову?ться мова PSQL, дозволяючи вносити початков? значення, перев?ряти ц?л?сн?сть даних, викликати виключення ? т. д. В Firebird 1.5 з'явилися ун?версальн? тригери, як? дозволяють в одному тригер? обробляти вставки, оновлення та видалення запис?в таблиц?.Зовн?шн? функц??: б?бл?отеки з UDF (User Defined Function) можуть бути написан? будь-якою мовою ? легко п?дключен? до сервера у вигляд? DLL/SO, дозволяючи розширювати можливост? сервера ?зсередини? [29].Декларативне опис посилально? ц?л?сност?: Забезпечу? несуперечн?сть ? ц?л?сн?сть багатор?вневих в?дносин ?master-detail? м?ж таблицями.Набори символ?в: Firebird п?дтриму? безл?ч м?жнародних набор?в символ?в (включаючи Unicode) з безл?ччю вар?ант?в сортування.Отже, Firebird SQL ма? так? основн? перваги:Д?йсно безкоштовний: на в?дм?ну в?д MySQL, ви можете використовувати Firebird в сво?х комерц?йних додатках без будь-яких ком?с?й або юридичних проблем. Вс? основн? функц?? великих СУБД: збережен? процедури, тригери, A.C.I.D. в?дпов?дн?сть вимогам, резервне коп?ювання в онлайн-сховище, генератори, дов?дкова ц?л?сн?сть ? т. д.Вбудована верс?я, що ма? об’?м 1Mb. Доступно на вс?х основних платформах ОС: Linux, Windows, Mac OS, Solaris ? ?н.Розумна продуктивн?сть: продуктивн?сть Firebird збер?га?ться м?ж MySQL ? PostgreSQL.Д?йсно активний проект: незважаючи на його низьку популярн?сть, це досить активний проект. Наприклад, в кв?тн? 2018 року була оголошена бета-верс?я проекту 3.0.4.Бази даних необмеженого розм?ру: обмеження розм?ру бази даних визнача?ться файлово? системою, в як?й збер?га?ться база даних. Але якщо ваша база даних перевищу? св?й л?м?т, завжди можна розбити ?? на к?лька файл?в.100% сум?сн?сть з SQL 92Зв'язок: в основному ви можете отримати доступ до Firebird SQL через будь-яку мову програмування2.3. Повний цикл роботи програмиДля уникнення неточностей розглянемо повний цикл роботи програми, вс? ?? етапи та дан?, ?з якими вона працю?. С самого початку роботи, користувач запуска? програму у ?нтерфейсному режим?, та почина? процес навчання. В залежност? в?д того, ск?льки та як? типи бланк?в будуть опрацьован? в автоматичному режим?, в?н ма? навчити систему ?х розп?знавати. Для цього в?н вибира? у списку документ?в один ?з необх?дних бланк?в та почина? процес навчання. По зак?нченню, система створю? шаблон для бланка та збер?га? його. П?сля цього, система може працювати в автоматичному режим?. Для цього ?? потр?бо запустити ?з параметром, який вкаже на етап, до якого проводити розп?знавання. Програма бере по черз? кожен не розп?знаний документ ?з бази даних, розп?зна? текст, шука? у розп?знаному текст? атрибути певного замовника. П?сля того, як тип бланку за замовником знайдений, програма використовуючи його шаблон, виокремлю? та збер?га? рекв?зити. Перед ?х збер?ганням дан? перев?ряються. П?сля збер?гання опрацьову?ться наступуний документ.ВИСНОВОК ДО РОЗД?ЛУ 2У цому розд?л? було повн?стю ? з ус?ма деталями розписано весь б?знес-процес. Проанал?зувавши його були винесен? загальн? вимоги до системи. Враховуючи ц? вимоги було обрано технолог?? для реал?зац?? проекту. Розглянуто аспекти вибору стеку технолог?и? та б?бл?отек для реал?зац??? системи, наведено об?рунтування вибору платформи для розробки системи. Враховуючи вимоги до програмного продукту вибрано мову програмування та платформи, обрано допом?жн? б?бл?отеки, як? спростять процес розробки та дозволять побудувати гнучку та просту арх?тектуру.Доступн?сть б?б?л?отеки Nicomsoft OCR на багатьох платформах та мовах програмування дозволя? розробляти вузькоспец?ал?зован? п?дсистеми, як? п?д?йшли би ?ншим, великим корпоративним системам. Але саме мова програмування Java дозволя? зробити систему ун?ерсальною. Було розглянуто систему управл?ння базою данних – Firebird, яка буде використовуватись в проект? на етап? тестування.Було вивчено арх?тектуру та внутр?шню структуру об’?кт?в Nicomsoft OCR. Розглянуто на приклад? б?б?л?отеки для мови програмування Java.Також було розглянуто та вибрано ?нструмент для створення ?нтерфейсу системи.РОЗД?Л 3ПРОЕКТУВАННЯ ТА РОЗРОБКА СИСТЕМИ3.1. Визначення вимог для проектування Основними функц?ями системи ?: Розп?знавання тексту та виокремлення рекв?зит?в; Навчання та створення шаблон?в бланк?в; Збереження рекв?зит?в у баз? даних; Основн? вимоги до системи: Точне розп?знавання тексту;Зрозум?лии? UI-дизаи?н та зручнии? UX-дизаи?н для користувача; Масштабування - систему ма? бути легко п?дстро?ти п?д ?нш? типи документ?в у майбутньому. Точне використання шаблон?в бланк?в.Проанал?зувавши вимоги та фукц?онал майбутьно? системи було прийнято р?шення впровадити роботу системи у двох режимах: ?нтерфейсний - використову?ться для навчання та створення шаблон?в бланк?в, та автоматичний - стоврений для автоматичного розп?знавання рекв?зит?в у документах на основ? ?снуючих шаблон?в бланк?в для них.3.2. Опис функц?оналу ?нтерфейсного та автоматичного режим?в Система у ?нтерфейсному режим? повина надавати користувачев? можлив?сть виконувати наступн? д???: Проводити навчання та створення шаблон?в бланк?в : Користувач вибира? документ для навчання; Користувач вручну вводить рекв?зити документу та вибира? постачальника ?з списку. Система самост?йно запам’ятову? м?сцезнаходження рекв?зит?в та збер?га? шаблон . Надавати користувачев? виб?р документу для навчання.Окр?м збереження шаблону також надавати користувачев? можлив?сть збер?гти вже розп?знанн? вручну рекв?зити.Перегляд списку постачальник?в та документ?в.П?д час ручного розп?знавання вибирати текстове значення рекв?зиту:Прямо на зображен? документу.В текстовому пол? розп?знаного документу.Перегляд збережених рекв?зит?в.Проводити ?перенавчання? бланку.У автоматичному режим? система самост?йно скану? базу даних на предмет нерозп?знаних документ?в. П?сля зак?нчення роботи, вс? розп?знан? рев?зити документ?в вже доступн? у баз? даних. При помилках, чи не точному розп?знаванн? програма познача? все у Log-файлах.3.3. Прецеденти3.3.1. Прецеденти високого р?вня?нтерфейсний режим – дужа важлива частина системи. Саме в?д не? залежить як?сть розп?знавння. Бо саме в н?й в?дбува?ться створення шаблон?в бланк?в, як? пот?м використовуються при розп?знавнн? у автоматичному режим?.Цю роботу виконуватиме спец?альний оператор, ? основна вимога до ?нтерфейсу – якомога сильн?ше спростити цю задачу опературу. Для цього потр?бний лакон?чний та зрозум?лий ?нтерфейс, який в?дтворюватиме ус? необх?дн? функц?? для процесу створення шаблону.П?сля визначення функц?и?, як? повина реал?зовувати система в кожному режим?, детал?зу?мо сценар??? використання системи та побуду?мо д?аграму вар?ант?в використання. На рис. 3.1 зображена д?аграма прецедент?в високого р?вня для ?нтерфейсного режиму. На н?и? зображен? можлив? д?и? користувача, абстрагован? в?д деталеи?. Детальн?ша ??рарх?я прецеденту створення шаблону зображена на рис. 3.2. 2483485228600000Рис. 3.1. Прецеденти високого р?вня для ?нтерфейсного режиму-107719524510Рис. 3.2. Детельна д?аграма прецеденту ?Створення шаблону?Розглянемо детальн?ше прецедент ?Створення шаблону?.3.3.2. Створення шаблону Дании? прецедент ? одним з основних д?и? у ?нтерфейсному режим?, в?н ? дозволя? створювати новий шаблон бланку. Цеи? прецедент може мати два сценар??? розвитку в залежност? в?д того, яким чином користувач хоче вибрати документ для створення шаблону: 1) Запуск програми ?з передачею ID документа, що треба в?дкрити; 2) Виб?р документа ?з списку документ?в у програм?. В першому випадку, користувач запуска? програму ?з певним набором команд. Приклад: -cfg_path C:\configdir -mode UI -doc_pi_import_id 21856Де, -cfg_path - папка ?з налаштуваннями (буде розглянуто у розд?л? 3), -mode - режим роботи програми (в нашому випадку ?нтерфейсний), -doc_pi_import_id - ?дентиф?катор документа у баз? даних.При такому набор? команд, програма в?дразу в?дкри?ться ?з розп?знаним документом, що указаний аргументом doc_pi_import_id.У випадку, коли користувач вибира? документ ?з списку у програм?, в?н ма? просто в?дкрити меню ?з списком документ?в. Скр?ншот зображений на рис. 3.3. П?сля вибору документа. користувач ма? сп?вп?ставити кожному рев?зиту - його текстове значення ?з в?кна ?з розп?знаним текстом, скр?ншот на 749304705350рис. 3.4. Кожне сп?вп?ставляння в?дм?ча?ться у таблиц? (рис. 3.5).Рис. 3.3. Скр?ншот у меню вибору документа-179705414020Рис. 3.4. Головне в?кно програми-1752606000750Рис. 3.5. Таблиця рекв?зит?вП?сля цього потр?бно перейти до меню вибору постачальник?в, та 71755394335вибрати постачальника, який надав послугу.Рис. 3.6. Меню вибору постачальникаДал? потр?бно перейти у меню збереження шаблон?в, перев?рити дан? та -80010485140зберегти шаблон.Рис. 3.7. В?кно збереження шаблон?вПро усп?шне збереження шаблону пов?домить вспливаюче в?кно (рис. 3.8). П?сля збереження шаблону можна також в?дразу зберегти вже розп?знан? вручну рекв?зити документа.1444720381133Рис. 3.8. Пов?домлення про усп?шно збережений шаблонП?сля цього створений шаблон зберг?а?ться у баз? даних. ? розп?знавання ?нших документ?в, його типу бланку вже буде доступно у автоматичному режим?. Щодо прецеденту ?переначання? бланку - воно проходить абсолютно так само як ? начання. Програма сама оновить дан? щодо шаблону у баз? даних. Таку процедуру навчання требе провести для ус?х тип?в бланк?в, як? будуть проходити розп?знавння у автоматичному режим?.Алгоритм роботи у ?нтерфейсному режим? представлений у рисунку 3.9.203748482383Рис. 3.9. Алгорим роботи у ?нтерфейсному режим?3.3.3. Робота програми у автоматичному режим? Для роботи програми у автоматичному режим? потр?бно запустити ?? ?з певними параметрами. Приклад: -cfg_path C:\configdir -mode BATCH -batch_goal_to DATA_EXTRACT_CHECK_SAVE, де: -batch_goal_to - до якого стану будуть розп?знан? документи.Також ?снують додатков? параметри для роботи у автоматичному режим?:-batch_count - к?льк?сть документ?в, як? необх?дно розп?знати.-doc_pi_import_id - ?дентиф?катор документа у баз? даних.П?д час роботи у автоматичному режим?, на початку програма сама скану? базу даних на предмет нерозп?знаних документ?в. Або в?дразу заватажу? потр?бний документ, якщо ? параметер doc_pi_import_id. П?сля цього почина? ?х розп?знавати. П?сля розп?знавння тексту, потр?бно знайти шаблон документу. Для цього у баз? даних ? дан? ус?х постачальник?в. У розп?знаному документ? шукають атрибути одного ?з збережених постачальник?в. Такими атрбиутами ? електронна пошта, номер телефону та назва. П?сля того як шаблон знайдений, за його допомогою виокоремлюються потр?б?н? рекв?зити. Перед збереженням, рекв?зити перев?ряються. Наприклад, що рекв?зит суми не м?стить в соб? л?тери. А вс? дати преводяться до одного формату. Вс? перев?рен? рекв?зити програма в?дразу зберг?? у баз? даних. При помилках чи не вдалому розп?знаванн?, наприклад не розп?знався певний рекв?зит чи не було знайдено шаблону для документа, програма познача? це у Log-файл?.У робот? в автоматичному режим? в?дсутн?й ?нтерфейс, програма лише запису? результати у Log-файл та в?добража? ?х у консол?. Саме можлив?сть запускати програму та задавати ?й ус? параметри ?з консол? дозволяють ?й бути незалежною та легко-вбудованою у ?нш? системи.Алгоритм роботи у автоматичному режим? представлений у рисунку 3.10.105346515621000Рис. 3.10. Алгоритм роботи системи у автоматичному режим?3.4. Проектування бази данихБаза даних потр?бна для реал?зац?? наступних процес?в:Збер?гання зображень документ?в.Збер?гання шаблон?в документ?в.Збереження розп?знаних рекв?зит?в.Nicomsoft OCR, б?б?л?отека, що була вибрана для розп?знавання тексту ма? вже реал?зован? методи для отримання координат знаходження певного тексту. Вони д?лять розп?знений документ на ?блоки? ?з тексту та вираховують координати кожного ?з них. Так як у кожного постачальника, як правило, документи одного типу бланку ? вс? рекв?зити знаходяться в одних и таких самих м?сцях, було вир?шено використовувти цю ознаку для створення тих самих ?шаблон?в? для кожного типу бланка. Б?льше детальн?ше цей процес буде описаний у третьому розд?л?.Отже, для збереження шаблон?в, було створену таблицю OCR_DOC_TEMPLATE. ?? поля розлянуто у таблиц? 3.11.Табл. 3.11.Поля таблиц? OCR_DOC_TEMPLATESUPPLIER_ID?дентиф?катор постачальникаDOC_TYPEтип документуMETAметадан?, де збер?гаються вс? координати для кожного рекв?зитуDOC_FILE_ID?дентиф?катор документа, з якого був створений шаблонУ пол? META записаний XML-код, в якому зберг?а?ться вся ?нформац?я по шаблону: координати кожного рекв?зиту, приблизний номер рядку та слова, де рекв?зит може знаходитись. Цей XML-код декоду?ться програмою при використанн? шаблону. У розп?знаних документах, треба позначати чи були вони розп?знан?, стан, до якого розп?знан?, чи було розп?знавання усп?шним, та вс? рекв?зити, як? програма мала розп?знати. Для цього ? таблиця DOC_PI_IMPORT. ?? поля роглянуто у таблиц? 3.12.Табл. 3.12.Поля таблиц? DOC_PI_IMPORTDOC_PI_IMPORT_ID?дентиф?каторSUPPLIER_ID?дентиф?катор постачальникаTEMPLATE_ID?дентиф?катор шаблонуRAW_INVOICE_NUMномер рахункуRAW_INVOICE_DATEдата рахункуRAW_ORDER_NUMBERномер замовленняRAW_NETсума без ПДВRAW_VATПДВOCR_SUCCESSусп?шн?сть розп?знаванняDOCUMENT_STATEстан документу (розп?знанався, чи н?)Для збереження зображень документ?в була створена таблиця DOC_FILE. ?? поля розглянуто у таблиц? 3.13.Табл. 3.13.Поля таблиц? DOC_FILEDOC_PI_IMPORT_ID?дентиф?катор документаDOC_FILE_DATAзображення документа, що зберг?а?ться у тип? BLOBТака орган?зац?я схеми баз даних дозволя? досить швидко та оптим?зовано керувати даними.3.5. Основн? р?шення з реал?зац??? системи та ?? компонент?в3.5.1. Арх?тектура системиК?нцева система - JAR файл з? специф?чними параметрами запуску.Обидва режими роботи мають в?дсл?дковуватися у центральному модул? системи, ? в залежност? в?д вибраного - запуска?ться специф?чний модуль.Вс? модул? системи пов’язан? м?ж собою тим, що мають доступ до сп?льних ресурс?в, таких як шаблони, документ який розп?зна?ться в даний момент, рекв?зити, метаопис, результати розп?знвання, анал?з результат?в на вимоги метаопису, запис та робота ?з базою даних.Кожний модуль, ма? сво? власн? специф?чн? об’?кти, для орган?зац?? роботи та керування процесом ? данними. Б?льш наглядно, арх?тектура 243944561340системи демонстру?ться в загальному вигляд? на рисунку 3.14.Рис. 3.14. Арх?тектура системи у загальному вигляд?Враховуючи той факт, що система ма? працювати у двох режимах, було вир?шено керувати вибором режиму через параметри запуску системи. А саме, за допомогою параметра ?-mode?. Параметр ?-mode? ма? два режими:-batch - автоматичний режим-UI - ?нтерфейсний режимОсновний модуль системи представлений у вигляд? класу OCR_Application. Цей клас анал?зу? параметри з якими була викликана програма та запуска? потр?бний режим роботи, передачи ?нш? специф?чн? параметри (наприклад: ?дентиф?катор документу? модулю, що в?дпов?да? за певний режим роботи.OCR_Batch - клас, який в?дпов?да? за роботу програми у автоматичному режим?. В?н отриму? к?льк?сть документ?в, яку потр?бно обробити за допомогою параметру ?-batch_count?, та стан, да якого потр?но розп?знавати документа ?з параметром ?-batch_goal?. В?н почина? брати документи для розп?знавання ?з бази даних по порядку. Дал? розп?зна? документ, п?сля чого шука? шаблон для нього. П?сля знайденого шаблону виокремлю? шукан? рекв?зити та зберг?? ?х у баз? даних.FwDrMainForm - клас, що в?дпов?да? за роботу програми у ?нтерфейсному режим?. В?н в?добража? в?кно програми ?з панелями, на яких зображений документ ?з розп?знаними зонами та можлив?стю масштабування, панель ?з розп?зн?ним текстом та панель ?з рекв?зитами з метаопису.RecognizeStage - клас, який опису? типи стану розп?знавання. Сама б?б?л?отека Nicomsoft OCR дозволя? проводити розп?знавання до заданного етапу, та продовжити ?з нього. За рахунок цього можна значно оптим?зувати систему. Основн? етапи розп?знавання: IMAGE_NOT_EXISTS;LOADED_NOT_PROCESSED;RECOGNIZED_NOT_ANALYZED;TEMPLATE_DETECTED_NOT_ANALYZED;DATA_EXTRACTED_NOT_CHECKED;DATA_CHECKED_OBJECTS_NOT_DETECTED; DOC_RECOGNIZED;OCR_ENGINE - клас, який опису? методи та функц?? для роботи ?з безпосередньо б?бл?отекою Nicomsoft OCR. В?н ма? дещо ?нший р?вень абстракц?? в?д корневих метод?в б?бл?отеки. Його метод getImage дозволя? в?дразу отримати завантажений документ у вигляд? зображення, а метод findPos, знайти певне слово за координатами на документ?. Враховучи той факт, що саме цей клас найближчий до корневих метод?в б?бл?отеки Nicomsoft OCR, саме тут впроваджено пошук шаблону бланку у метод? findTemplate().DOC_ENGINE - клас, який опису? методи роботи ?з документами. Масштабований, дозволя? у майбутньому працювати ?з ?ншими типами документ?в. Зараз зконф?гурований для роботи ?з типом Invoice. Клас займа?ться використанням знайденого шаблону, виокремленням рекв?зит?в та ?х перев?ркою. Перев?рка результат?в виклика?ться методом check() класу DocMetaType для кожного типу рекв?зиту. При невдалих результатах перев?рки виклика?ться метод refine() цього ж класу, задля перев?рки даних на порушення, наприклад неправильного розп?знавання одного ?з символ?в. П?сля цього знову в?дбува?ться перев?рка.П?сля розп?знавання та в?дображення документу, програма оч?ку?, щоб користувач сп?вп?дставив кожному рекв?зиту його фактичне значення ?з документу та вибере постачальника з? списну. П?сля цього програма перепров?ря?, чи п?дходять дан?, введен? користувачем до оч?куваних тип?в даних. Якщо так, то програма в?дкрива? наступне в?кно, де користувач може знов перев?рити введен? дан? та збер?гти шаблон та дан? у базу даних.3.5.2. Реал?зац?я блоку розп?знавання текстуП?сля запуску програми, незалежно в?д режиму роботи, система ма? розп?знати текст у документ?, ?дентиф?катор якого, передано параметром ?-doc_pi_import_id?. Цим займа?ться клас OCR_Engine. До його основних функц?й входять: розп?знавання переданого документу, вже переведеного до типу BufferedImage, поверення розп?заного тексту до ?нших модулей та пошук м?сцезнаходження специф?чного тексу на документ?в (використову?ться при створен? шаблон?в).OCR_Engine - ?диний клас, який ма? доступ до метод?в пакету JNSOCR. Саме в?н запуска? процес розп?знавання, та контролю? його на вс?х етапах.А п?сля розп?знавання - переда? рохп?знаний текст до ?нших частин системи. При робот? в ?нтерфейсному режим?, користувач сам сп?вп?дставля? кожен рекв?зит. Це потр?бно для того, щоб система знайшла вс? ц? рекв?зити на документ? та пам’ятала ?х приблизне м?сцезнаходження та ключов? слова ?з якими вони пов’язан?. На основ? цих даних ? створю?ться шаблон. База шаблон?в - основа, на як?й базу?ться система. Саме завдяки ?й ? вир?шу?ться питання автоматизац?? автоматичного розп?знавання рекв?зит?в документ?в. Саме OCR_Engine шука? специф?чний рекв?зит на документ? та поверта? наступн? дан? про нього:Координати зони, де знайшли рекв?зит;Координати л?н?? тексту в?дносно зони;Номер слова у л?н??;Координати де знаходиться сам рекв?зит;3.5.3. Реал?зац?я блоку пошуку шаблон?вП?сля розп?знавання, документ перев?ря?ться на ?снування шаблону для нього. ?з бази даних беруться шаблони, а саме рекв?зити, як? пов’язан? ?з постачальником, та повторюються кожен документ. Такими рекв?зитами являються:E-mail постачальника;Моб?льний номер;Адреса;Якщо був знайдений постачальник документа, база знаходить шаблони, як? в?дносяться до цього постачальника. Та почина? процес викор?нення рекв?зит?в.3.5.4. Реал?зац?я блоку викор?нення рекв?зит?вП?сля того, як шаблон був знайдений, потр?бно за домогою його викор?нити рекв?зити.Цим процесом та пов’язаними з ним процесами керу? клас Doc_Engine. Спочатку в?н парсить метадан? шаблону, як? були отриман? ?з бази даних. Метадан? мають наступний вигляд:<TMPL> <ELM NM="BlankKeyword" NMBR="1" REGEX="Partline" RL="867" RU="562" RW="464" RH="151" PZ="1" PL="1" PW="1" NW="1" /> <ELM NM="InvoiceNumberValue" NMBR="2" REGEX="" RL="8523" RU="2223" RW="579" RH="186" PZ="5" PL="1" PW="3" NW="1" /> <ELM NM="OrderNumberValue" NMBR="3" REGEX="" RL="4861" RU="3866" RW="550" RH="123" PZ="7" PL="1" PW="7" NW="1" /> <ELM NM="InvoiceDateValue" NMBR="4" REGEX="dd/mm/yy" RL="2928" RU="3869" RW="443" RH="120" PZ="7" PL="1" PW="4" NW="1" /> <ELM NM="InvoiceNetValue" NMBR="5" REGEX="\d*\.\d*" RL="8719" RU="7849" RW="334" RH="120" PZ="14" PL="1" PW="2" NW="1" /> <ELM NM="InvoiceVATValue" NMBR="6" REGEX="\d*\.\d*" RL="8774" RU="8089" RW="281" RH="120" PZ="14" PL="2" PW="2" NW="1" /> <ELM NM="InvoiceGrossValue" NMBR="7" REGEX="\d*\.\d*" RL="8710" RU="8328" RW="343" RH="120" PZ="14" PL="3" PW="2" NW="1", /></TMPL> Рис. 3.15. Приклад метаданих шаблонуУ таблиц? 3.16 б?льш детально розглянто кожен тег у метаданих.Табл. 3.16.Значення тег?в метаданихTMPLПочаток метаданих шаблонуELMПолчаток метаданих елементуNMНазва елементуNMBRНомер за порядкомREGEXРегулярний вираз, якому ма? в?дпов?дати значенняRLВ?дступ блоку тексту зл?ваRUВ?дступ блоку тексту зверхуRWШирина блокуRHВисота блокуPZНомер блокуPLНомер строкиPWНомер словаNWК?льк?сть сл?вВ цих метаданих, збер?га?ться вс? атрибути, як? шукав OCR_Engine ще п?д час створення шаблону, а саме:Координати зони, де знайшли рекв?зит;Координати л?н?? тексту в?дносно зони;Номер слова у л?н??;Координати де знаходиться сам рекв?зит; ? так для кожного рекв?зита. Як показу? практика, зазвичай у документах одного ? того самого типу кожен рекв?зит знаходиться у одному блоц?, який розм?щений у одному й тому самому м?сц?.П?сля парсингу метаданих, Doc_Engine почина? за ними викор?нювати сам? рекв?зити. Пот?м перев?ря? результати. Результати перев?ряються в?дношенням до певного типу даних (напр. датою може бути лише дата, а сума може м?стити лише цифри та крапку). При усп?шн?й перев?рц?, система зьер?га? результати у базу даних.3.6. Тестування системиТестування потр?бно було в першу чергу для оц?нки ефективност? системи, а саме який в?дсоток документ?в буде усп?шно розп?знаний в автоматичному режим?.Методолг?я тестування системи наступна: використовуючи якомога б?льше документ?в та ?х тип?в бланк?в в?дбува?ться навчання кожному типу, а пот?м автоматичне розп?знавання ус?х ?нших документ?в. Така методолог?я тестування максимально нагаду? реальне використання програми.Тестування системи в?дбувалось у два етапи. Спершу, п?сля повно? реал?зац?? ус?х блок?в. Це тестування мало моказити не ст?льки хорошу ефективн?сть системи, ск?льки те - на що потр?бно звернути увагу при автоматизац??.Часом б?бл?отека помилково розп?зна? деяк? символи. Це в першу чергу через деяк? шрифти, як? використовувались при створенн? документ?в. Особливо часто неправильно розп?знаються символи "/", "I", "i", "l", ?1". Це потр?бно буде врахувати п?д час отпим?зац?? блоку, що в?дпов?да? за перев?рку розп?знаних даних.Так само як ? р?зний шрифт, р?зн? типи бланк?в мають й р?зн? формати дат. Один постачальник пише "22/10/2019", а ?нший "22 Oct 19". Але збер?гати дати у баз? даних потр?бно у одному тип?. Тому так само, при перев?рц? розп?знаних даних потр?бно перев?ряти розп?знану дату вс?ма можливами форматами. А перед збереженням переводити ?? до якогось одного типу. Ще одн??ю частою проблемою було помилкове розп?знавння ?нтервал?в м?ж символами. Особливо у рев?зитах сум. Через що, п?д час перев?рки - система не збер?гала усп?шно розп?знан? значення сум.Другий етап тестування вже був виконаний для анал?зу та оц?нки ефективност? системи. Для тестування було використано 12 р?зних тип?в бланк?в в?д 11 р?зних постачальник?в. Загалом було автоматично розп?знано 93 документи. Серед яких усп?шно - 75. Тобто усп?шно розп?знано було 80% документ?в. Цей результат дозволя? назвати систему ефективною. Журнал тестування знаходиться у додатку Б.ВИСНОВКИ ДО РОЗД?ЛУ 3У цьому розд?л? був проведении? опис основних р?шень та п?дход?в щодо реал?зац??? проекту. За описаними р?шеннями було розроблено систему.Вир?шено под?лити систему на роботу у двох режимах, так як ?сну? досить велика р?зниця м?ж процесами, що кожен з них ма? реал?зовувати. Це, в свою чергу дозволятиме систем? бути легко-вбудованою у ?нш? корпоративн? системи. Бо для початку роботи програми потр?бно лише викликати ?? ?з певним набором параметр?в. При проектуванн? враховувалися вс? вимоги та виключн? ситуац??, як? можуть виникнути п?д час роботи системи.Була також спроектована база даних та спос?б збер?гання в н?й зображень документ?в у тип? BLOB та спос?б збер?гання шаблон?в документ?в.?нтерфейсний режим розроблявся з урахуванням досв?ду користувача та вс?х вимог, що були поставлен? перед системою. Користувач потр?бен лише для процесу навчання шаблон?в, для того, щоб у майбутньому система сама могла працювати в автоматичному режим?, анал?зуючи базу даних та самост?йно розп?знавати рекв?зити та збер?гати ?х.Повн?стю об?рунтуван? та показан? в?дносини м?ж класами, таблицями баз даних. Показано та пояснено повн?стю структуру та арх?тектуру системи та як реал?зову?ться кожний аспект системи. Досить детально описан? основн? класи, ?х фукнц??, об’?кти та методи.Також було описано процес та метадолог?я тестування та його основн? результати на кожному етап?. Результути проанал?зован?, можлив? недол?ки системи - виправлен?.РОЗД?Л 4РОЗРОБКА СТАРТАП ПРОЕКТУ4.1. Опис ?де? проектуСистема автоматизованого розп?знавання рекв?зит?в та даних документу створена для реал?зац??? одн??? ?з найрозповсюджен?ших б?знес-задач. В ц?лому ринок оптичного розп?знавння розвива?ться. Загальний об‘?м ринку оптичного розп?знавання символ?в був оц?нений у 5,27 м?льярда долар?в у 2018 роц?, ?, як оч?ку?ться, в?н зросте на 13,7% з 2019 по 2025 р?к. Компан??, як диджитал?зац?я стала нормою у п?дпри?мницькому сектор?, також почали використовувати так? ?нструменти, як OCR, для перетворення сво?х ф?зичних даних у цифрову форму. Ця технолог?я також знаходить все б?льш широке застосування в BFSI та в галуз? охорони здоров’я для створення цифрових коп?й чек?в, рахунк?в та ?нших документ?в [32]. Але без повного анал?зу ринку, неможливо створити конкурентноспрможний продукт.В межах дипломного проекту, можливо реал?зувати систему, яка буде реал?зувати автоматизац?ю б?знес-процесу розп?знавння рекв?зит?в документ?в та ?х зберг?ання у базу даних. В цьому розд?л?, буде описано розробку стартап-проекту програмного продукту для п?двищення ефективност? анал?зу даних великого обсягу у вигляд? веб-серв?су для анал?зу в?део. В табл 4.1 викладено зм?ст ?де?, яка пропону?ться, можлив? напрямки застосування ?де?, основн? вигоди, яка може отримати к?нцевий користувач за допомогою ?де? та чим в?др?зня?ться ?дея в?д ?снуючих аналог?в.Таблиця 4.1. Опис ?де?? стартап-проектуЗм?ст ?де?Напрямки застосуванняВигоди для користувачаСистема автоматизованого розп?знавання рекв?зиту документ?в Запис розп?знаних даних у БД Б?льше не потр?бно витрачати час сп?вроб?тник?в на ручне розп?знавання та запис даних. Анал?з та пор?вняння розп?знаних данихАвтоматизована система дозволя? зб?льшити к?льк?сть розп?знаваних документ?в за певний час, а отже й отримати б?льше даних для анал?зу.Пошук помилок П?сля розп?знавання документу, наприклад рахунку, можна пор?вняти дан? ?з вже записаними у базу даних ?з метою виявлення помилок.Анал?з потенц?и?них техн?ко-економ?чних переваг ?де?? (чим в?др?зня?ться в?д ?снуючих аналог?в та зам?нник?в). Попередн?м колом аналог?в ? така система, як Abbyy FineReader. Але нав?ть вона не дозволя? автоматизувати процес розп?знавння.Таблиця 4.2. Визначення сильних, слабких та неи?тральних характеристик ?де?? проекту№Техн?ко-економ?чн? характеристики ?де?М?й проектКонкурентиWNS121Система розп?знавння по зображенню++++2Система викор?нення рекв?зит?в +--+3Запис розп?знаних даних у БД ++-+4Вбудован?сть системи+--+Визначении? перел?к неи?тральних, сильних та слабких характеристик ? особливостей ?де?? потенц?и?ного продукту ? основою для формування и?ого конкурентоспроможност?. Як можно побачити в таблиц? 4.2, основною перевагою розроблюваного продукту ? саме система автоматичного викор?нення рекв?зит?в, на що ? варто зробити ставку.Технолог?чний аудит проектуТаблиця 4.3. Технолог?чна зд?и?сненн?сть ?де?? проекту№?дея проектуТехнолог?? ?? реал?зац??Наявн?сть технолог??Доступн?сть технолог?й1Система автоматизованого розп?знавання рекв?зиту документ?в Мова Java? в наявност?Доступн? безкоштовно2СУБД Firebird SQL? в наявност?Доступн? безкоштовно3Б?бл?отека Nicomsoft OCR? в наявност?Доступн? безкоштовно4Б?бл?отека Swing? в наявност?Доступн? безкоштовноОбрана технолог?я реал?зац?? ?де? проекту: розробка програми на мов? програмування Java, б?бл?отека для розп?знавння тексту, СУБД для збер?гання даних та ?нструмент для побудови ?нтерфейсу.4.3. Анал?з ринкових можливостей запуску стартап-проектуВизначення ринкових можливостеи?, як? можна використати п?д час ринкового впровадження проекту, та загроз ринку, як? можуть перешкодити реал?зац??? проекту, дозволя? спланувати напрями розвитку проекту ?з урахуванням стану ринкового оточення, потреби к?нцевих кл??нт?в ? пропозиц?и? конкурентних проект?в. В таблиц? 4.4 наведена попередня характеристика можливого ринку для розробляючого стартап-проекту.Таблиця 4.4. Попередня характеристика потенц?и?ного ринку стартап-проекту№Показники стану ринкуХарактеристика1К?льк?сть головних гравц?в, од>102Динам?ка ринку (як?сна оц?нка)Сфера автоматизованого електронного документооб?гу пост?йно зроста?3Наявн?сть обмежень для входу (вказати характер обмежень)На ринку розп?знавння зображень велика конкуренц?я, але це можна використовувати як ?нструмент для автоматизац??4Специф?чн? вимоги до стандартизац??? та сертиф?кац???Стандартизац??ю в сфер? обробки даних великого обсягу займаються орган?зац?? Apache License 2.0. Можливо деяк? документи мають бути захищен?.Таблиця 4.5. Характеристика потенц?и?них кл??нт?в стартап-проекту№Потреба, що форму? ринокЦ?льова аудитор?яВ?дм?нност? у повед?нц? р?зних потенц?йних ц?льових груп кл??нт?вВимоги споживач?в до товару1Розп?знаваня даних, рекв?зит?в ?з скан-коп?й документ?в Будь-як? компан??, що працюють ?з системами електронного документооб?гу Р?зн? типи документ?вЛегко-вбудован?сть у ?нш? системи2Анал?з та робота ?з розп?знаними данимиКомпан??, що зацмаються анал?зом данихТипи даних для збер?гання та анал?зуТочн?сть та як?сть розп?знавання, як джерело отрмання данихТаблиця 4.6. Фактори загроз№ФакторЗм?ст загрозиМожлива реакц?я компан??1Неточн?стьЗа результатами тестування, програма показала точн?сть – 80 %. Через низку причин, сьогодн? домогтися точност? у 100 % неможливо.Пост?йний анал?з типових помилок системи та ?х виправлення.2Вузький спектр функц?оналуТак як система розроблялась ?з можлив?стю бути вбудованою у ?нш?, вона явля?ться реал?зац?ю одного ?з б?знес-процес?в?нтеграц?я ?з ?ншими системами, можливо на комерц?йн?й основ?Таблиця 4.7. Фактори можливостей№ФакторЗм?ст можливост?Можлива реакц?я компан??1Пост?ний анал?з результат?вПост?йно анал?зуючи результати розп?знавння та виправляючи помилки можна вийти на висок? значення ефективност?.Анал?з результат?в та оновлення системи.2?нтеграц?я ?з великими корпоративними системами?нтегруючись у ?нш? велик? корпоративн? системи, можна викходити на ринок не вагаючись про вузьку спец?ал?зац?ю системи.Мати контакт ?з розробниками ?нших корпоративних систем.3Залучення ?нвестиц?йСклавши ч?ткий б?знес-план, можна залучити необх?дну к?льк?сть ?нвестиц?й, що дозволить розширити штат ? прискорити момент виходу на ринок.Зб?льшити штат, прискорити вих?д на ринок, вийти на пер?од самоокупност? ран?ше.Таблиця 4.8. Ступеневии? анал?з конкуренц??? на ринкуОсобливост? конкурентного середовищаВ чому проявля?ться дана характеристикаВплив на д?яльн?сть п?дпри?мства (можлив? д??? компан???, щоб бути конкурентос- проможною)Складн?сть входу на ринокРинок ? новим та велика к?льк?сть конкурент?в не укр?пили сво? позиц??, не завели зв'язки та мають налагоджену кл??нтську базуПропонувати б?льш виг?дн? умови (нав?ть з можлив?стю працювати без прибутку), анал?зувати та впроваджувати нов? розробки в сфер? ран?ше конкурент?в, як?сна рекламна кампан?яВисок? вимоги до ефективност?Ринок ?з корпоративних систем перенасичений та ма? висок? вимоги до ефективност?. Пост?на робота над системою та регулярн? оновлення.Незац?кавлен?сть у систем?Вузька спец?ал?зац?я системи зазвичай не да? можливост? в?дразу продаватись.?нтеграц?я ?з великими системами.Таблиця 4.9. Анал?з конкуренц??? в галуз? за М. ПортеромСкладов? анал?зуПрям? конкуренти в галуз?Потенц?йн? конкуренти в галуз?ПостачальникиКл??нтиТовари-зам?нники-Abbyy FinereaderNicomsoft OCRКомп?н??, що використовують системи електронного документооб?гуOpen Source-р?шенняВисновки:Повн?стю аналог?чних систем не ?сну?? конкуренти, як? виконують схож? процесиПостачальниками не ? св?тов? л?дери у сфер? розп?знавння текстуБ?льш?сть кл??нт?в уже давно на ринку та мають контакти з виликими гравцями? безкоштовн? р?шення розроблен? ентуз?астами для виконання розп?знавння текстуТаблиця 4.10. Об?рунтування фактор?в конкурентоспроможност?№Фактор конкурентоспроможност?Об?рунтування (наведення чинник?в, що роблять фактор для пор?вняння конкурентних проект?в значущим)1Автоматизац?я процес?вОсновне завдання системи – автоматизувати процес розп?знавння даних у документах. Саме цього поки що не вм?? жодна ?нша корпоративна система.2Зручний ?нтерфейсЗручний ?нтерфейс дозволить компан?ям не залучати дорогих спец?ал?ст?в.3Пост?йн? оновленняПост?йний анал?з отриманих даних, дозволятиме виправляти проблеми на зб?льшувати ефективн?сть системи.Таблиця 4.11. Пор?вняльнии? анал?з сильних та слабких стор?н№Фактор конкурентоспроможност?Бали 1-20Реи?тинг товар?в-конкурент?в у по- р?внянн? з розроблюваним продуктом-3-2-101231Автоматизац?я процес?в19?2Зручний ?нтерфейс10?3Пост?йн? оновлення15?Таблиця 4.12. SWOT - анал?з стартап-проектуСильн? сторони: Пост?йн? оновлення, максимальна автоматизац?я б?знес-процесу, зручний ?нтерфейс.Слабк? сторони:Наявн?сть opensource р?шеньНедов?ра великих кл??нт?вМожливост?:?нтеграц?я ?з великими системами.Загрози:Незац?кавлнен?сть ринку.Таблиця 4.13. Альтернативи ринкового впровадження стартап-проекту№Альтернатива ринково? повед?нкиЙмов?рн?сть отримання ресурс?вСтроки реал?зац??1В?дкриття проекту та розповсюдження в рамках opensource л?ценз??Низька, так як в основному це будуть пожертви ентуз?аст?в. Можлив?сть продажу компан?? у випадку зац?кавленост? з боку великих компан?йПрактично митт?во2Розповсюдження проекту через конференц??, публ?чн? виступиВисока, оск?льки публ?чними заходами можна поширити ?дею проекту та завести знайомства з потенц?йними ?нвесторами та кл??нтамиДо року, з можлив?стю продовження3Участь в тендерах ? укладення договор?в з державними установамиСередня, так як на це впливають економ?чн?, пол?тичн?, особист? мотиви ? не можна гарантувати абсолютну прозор?сть та добросов?сну конкуренц?ю на цьому ринкуК?лька м?сяц?в, в залежност? в?д наявност? запиту з боку держави4.4. Розроблення ринково? стратег?? проектуТаблиця 4.14.Виб?р ц?льових груп потенц?и?них споживач?в№Опис проф?лю ц?льово?? групи потенц?и?них кл??нт?вГотовн?сть споживач?в сприи?няти продуктОр??нтовнии? попит в межах ц?льово? групи (сегменту)?нтенсивн?сть конкуренц??? в сегмент?Простота входу у сегмент1Розробники великих корпортативних системНе вс? розробники хочуть вбудовувати р?щення сторонн?х розробник?вПродукт необх?днийКонкуренц?я низькаВх?д пом?рно-складний2Приватн? компан??Не вс? користувач? готов? прийнятиПродукт необх?дний не вс?мКонкуренц?я низькаВх?д складний3Навчальн? та досл?дницьк? програмиКористувач? готов? прийняти продуктНе вс? зац?кавлен? в продукт?Конкуренц?я середняВх?д не ? складнийЯк? ц?льов? групи обрано:Потр?бно працювати з? вс?ма ц?льовими групами, перевагу надати приватними компан?ямТаблиця 4.15. Визначення базово?? стратег??? розвитку№Обрана альтернатива розвитку проектуСтратег?я охоплення ринкуКлючов? конкурентос- проможн? позиц??? в?дпов?дно до обрано?? альтернативиБазова стратег?я розвитку1Розвиток шляхом маркетингово?? компан?? та публ?чних демонстрац?? можливостейсистемиВпливати на обран? ц?льов? групи в порядку значимост? та перспективВиступ на конференц?ях, в?льне розповсюдження для навчально-досл?дницьких ц?лейПост?йний анал?з результат?в та оновлення системи. Таблиця 4.16. Визначення базово?? стратег??? конкурентно?? повед?нки№Чи ? проект ?першопрох?дцем? на ринку?Чи буде компан?я шукати нових споживач?в, або забирати ?снуючих у конкурент?в?Чи буде компан?я коп?ювати основн? характеристики товару конкурента, ? як??Стратег?я конкурентно?? повед?нки1Так, проект ? ?першопрох?дцем?Через низьку конкуренц?ю, скор?ше шукати нових.Н?Пропонувати функц?онал на кращих умовах, оперативно оновлювати.Таблиця 4.17. Визначення стратег??? позиц?онування№Вимоги до товару ц?льово?? аудитор???Базова стратег?я розвиткуКлючов? конкуренто- спроможн? позиц??? власного стартап- проектуВиб?р асоц?ац?и?, як? мають сфо- рмувати комплексну позиц?ю власного проекту (три ключових)1Висока частота оновлення, широкий функц?онал,доступн?сть через ?нтернетПост?ний анал?з проблем на оновленняМожлив?сть автоматизувати процес розп?знаванняРозп?знавння рекв?зит?в документ?в, розп?знавння тексту, розп?знавння даних.4.5. Розроблення маркетингово? програми стартап-проектуТаблиця 4.18. Визначення ключових переваг концепц??? потенц?и?ного товару№ПотребаВигода, яку пропону? товарКлючов? переваги перед конкурентами (?снуюч? або так?, що потр?бно створити1Розп?знавння даних документу та ?х збер?ганняСистема розп?знавання, робота ?з базою денизАвтоматизац?я процесу розп?знавання2Часте оновлення програмиАнал?з та виправлення помилок.Створення в?дд?лу п?дтримки для реагування на в?дгуки кл??нт?в3Анал?з даних Можлив?сть переглядати вс? збережен? дан?.Модель для анал?зу та пор?вняння статистичних даних. Таблиця 4.19. Опис трьох р?вн?в модел? товаруР?вн? товаруСутн?сть та складов??. Товар за задумомСистема автоматизованого розп?знавння даних документ?в??. Товар у реальному виконанн?Властивост?/характеристикиПотребаСистема розп?знавання данихКоп?? документ?вСистема збер?гання данихБаза даних Система анал?зу данихБаза даних Як?сть: публ?чне тестування програми, логування збо?в та система зворотнього зв’язку для пов?домлення про неналежну роботу програмиПоширення: впровадження у ?нш? системи Марка: назва орган?зац??-розробника та назва товару???. Товар ?з п?дкр?пленнямДо продажу: програмний кодП?сля продажу: повноц?нна система Таблиця 4.20. Визначення меж встановлення ц?ни№ п/пР?вень ц?н на товари-зам?нникиР?вень ц?н на товари-аналогиР?вень доход?в ц?льово? групи споживач?вВерхня та нижня меж? становлення ц?ни на товар/послугу14000$ - 8000$1500$-5000$>10000$/м?сяць4000$-6000$Таблиця 4.21. Формування системи збуту№ п/пСпециф?ка закуп?вельно?? повед?нки ц?льових кл??нт?вФункц??? збуту, як? ма? виконувати постачальник товаруГлибина каналу збутуОптимальна система збуту1?нтеграц?я у велику систему?нтеграц?я ?з п?дключенням до ресурс?вКанал збуту однор?вневий Вертикальна (право власност? залиша?ться у розробника ПЗ)Таблиця 4.22. Концепц?я маркетингових комун?кац?й№ п/пСпециф?ка повед?нки ц?льових кл??нт?вКанали комун?кац?и?, якими користуються ц?льов? кл??нтиКлючов? позиц???, обран? для позиц?онуванняЗавдання рекламного пов?домленняКонцепц?я рекламного звернення1Куп?вля функц?? та послуг на ресурс?Тематичн? зустр?ч?, соц?альн? мереж?, конференц??, презентац?? тощоНадання послуг для обробки та анал?зу Демонстрац?я основних функц?й розробленого продуктуОхоплення аудитор??, пояснення функц?й та можливостей розробленого продукту та його перевагВИСНОВКИ ДО РОЗД?ЛУ 4Четвертий розд?л призначений для розробки стартап-проекту для розроблено? системи, створено опис ?де? продукту, наведено детальний анал?з конкурент?в та можливостей, що доступн? на даному ринку. Для досл?дження в рамках розробки стартап-проекту було обрано наступн? завдання:Наведено загальний опис ?де? продукту для виходу на ринок, описаний функц?? проекту, визначено основн? конкуренти та сп?вставлено функц?? конкурент?в для визначення переваг розроблюваного продукту над обраними конкурентами.Проанал?зовано ринков? можливост? для запуску проекту, пор?вняно перспективи запуску в пор?внянн? з конкурентами, встановлено план та ринкову стратег?ю розвитку продукту, визначено ц?льов? групи та способи просування проекту.Проведено техн?чний аудит проекту ? визначено можливост? реал?зац?? програмного продуктуРозроблено маркетингову програму для просування продукту на ринку, описано способи та основн? канали збуту, визначено пр?оритетн? ц?льов? групи та маркетингов? пов?домлення для розширення кл??нтсько? базиВ п?дсумку, було отримано стартап-проект для запуску розробленого програмного продукту на ринок.ЗАГАЛЬН? ВИСНОВКИТака звичайна, проста та буденна на перший погляд задача, як розп?знавання рекв?зит?в документ?в та збереження даних насправд? забира? дуже багато часу. Вона необх?дна, майже для кожного п?дпри?мства, але не потребу? спец?ал?ст?в. А для будь-якого сучасного п?дпри?мства задача автоматизац?? ус?х простих та елементарних процес?в - пр?ор?тетна.Д?джитал?зац?я у б?знес? вже досягла таких усп?х?в, що ми не можемо уявити велику компан?ю без бази ?з данними ?? сп?вроб?тник?в, зашифорвано? системи комун?кац??, автоматично? вал?дац?? сп?вроб?тник?в п?д час приходу на роботу та системи яка самост?йно веде частину бухгалтерського обл?ку. Але нав?ть серед всього цього знаходять найпрост?ш? та елементарн? задач?, як? до сих п?р не були автоматизован?.Одн??ю ?з таких задач ? автоматичне розп?знавання рекв?зит?в документу та збереження ?х.Неможлив?сть ран?ше вир?шити цю задачу полягала в тому, що системи ?з розп?знавння тексту були неточн?. Вони розроблялись скор?ш ?з досл?дницьких ц?лей, як ? ?нш? технолог?? комп’ютерного зору. Але сьогодн? як?сть та результат, який показують продукти ц??? технолг?? вже дозволяють ?х використовувати у комерц?йних ц?лях. Тому безл?ч приклад?в, в?д магазин?в - до машин. У розвинених кра?нах дуже багато державних компан?й у сфер? безпеки стали замовниками ?з систем автоматичного розп?знавння облич на вулицях м?ст. Важко уявити масштаб тако? системи, як?сть розп?знавання яку вона ма? давати та к?льк?сть даних ?з якими вона працю?.Так само точно вже можна розп?знавати надрукований та рукописний текст, написаний на б?льшост? мов св?ту. Саме це й дозволя? автоматизувати процес ?з розп?знавання тексту у надрукованих та в?дсканованих документах.П?сля цього залиша?ться останн? завдання - виокремити ?з пом?ж усього тексту документу саме потр?бн? рев?зити. Для р?шення ц??? задач? було розроблено алгоритм навчання системи, за яким перше розп?знавання документу в?дбува?ться вручну. Запам’ятав м?сцезнаходження рекв?зиту на документ?, система збер?гатиме цю ?нформац?ю та використовуватиме ?? п?д час наступних розп?знавань, вже щоб зробити цей процес автоматичним.Все що залишалось - оптим?зувати процес виокремлення даних. Досить часто у документ?в р?зн? формати даних, наприклад дат. А деяк? символи можуть бути неправильно розп?знанн?. Вс? ц? ситуац?? не повинн? створювати проблем для системи та впливати на результат ?? роботи. Звичайно можуть бути документи, як? не зможуть бути розп?знанн? по р?зним причинам. Але ?х к?льк?сть не ма? виходити за меж?, щоб систему можна було вважати ефективною.Загалом тестування да? право називати розроблену систему еффективною. Було розп?знано велику к?льк?сть документ?в р?зного виду, й загальна к?льк?сть усп?шно розп?знаних документ?в досягла 80%.А комерц?йна та ?нвестиц?йна складова проекту ма? великий потенц?ал, що було доведено у останньому розд?л?. Проанал?зувавши ринок ?з програмного забезпечення, яке використову? б?бл?отеки ?з розп?знавання тексту, я д?йшов висновку, що на ринку нема? ун?версальних програм ?з автоматизац?? процесу розп?знавання тексту, виокремленню отриманих даних та збер?гання ?х у баз? даних. Програма Abbyy FineReader, яка використову? одно?менну б?б?л?отеку ?з розп?знавання тексту дозволя? лише перевести тип файлу ?з зображення (напр. pdf) до текстовогу типу (напр. doc).Але враховуючи той факт, що б?б?л?отек ?з розп?знавання тексту чимало, а отже попит на них ? та програмне забезпечення на ?х основ? розробля?ться, а задача ?з автоматизац?? процесу розп?знавання рекв?зит?в доументу актуальна, можна д?йти висновку, що под?бн? системи, до то?, що розроблена у цьому проект? ?снують, але вони вир?шують б?льш вузьк? задач? саме того п?дпри?мства, яке було ?х замовником.Саме тому, потр?бно щоб система в?дпов?дала наступним вимогам: масштабован?сть, ун?ерсальн?сть, на оптим?зован?сть. Система ма? працювати ?з багатьма типами документ?в на багатьох мовах св?ту та бути легко-впровадженою у ?нш? велик? корпоративн? системи.СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛMIT Sloan Management - How to go Digital: Practical Wisdom of Digital Transformation - 222 с. Access – The Future of Scanning in the Digital Age [Електроннии? ресурс] - Режим доступу: – Digitalization in Business World [Електроннии? ресурс] - Режим доступу: Markovitch and Paul Willmott/McKinsey – Accelerating the digitalization of business processes[Електроннии? ресурс] - Режим доступу: Bloomberg/Forbes - Digitalization [Електроннии? ресурс] - Режим доступу: Domingues/Ehorus - Digitalization in Business[Електроннии? ресурс] - Режим доступу: Spirina InData labs How OCR can help Employees fighthrough most mendane tasks [Електроннии? ресурс] - Режим доступу: Mindset The Benefits of OCR Systems for your Business [Електроннии? ресурс] - Режим доступу: Luksza Insane Lab What is OCR [Електроннии? ресурс] - Режим доступу: How today’s business use OCR [Електроннии? ресурс] - Режим доступу: The business uses of OCR [Електроннии? ресурс] - Режим доступу: Gulipalli Invensis Advantages of OCR-based Data Entry Methods [Електроннии? ресурс] - Режим доступу: View Research Optical Character Recognition Market Size [Електроннии? ресурс] - Режим доступу: OCR in Business [Електроннии? ресурс] - Режим доступу: Nield Techradar Best OCR Software of 2019 [Електроннии? ресурс] - Режим доступу: Sable Nanonets Automating Invoice Processign with OCR [Електроннии? ресурс] - Режим доступу: Sable Nanonets Automating Invoice Processign with Building Custom Deep Learning OCR Based models [Електроннии? ресурс] - Режим доступу: Cambridge and RSA Why OCR for new Maths A Levels [Електроннии? ресурс] - Режим доступу: Neuberg Dropbox Modern OCR Pipeline [Електроннии? ресурс] - Режим доступу: Shperber A gentle Introduction to OCR [Електроннии? ресурс] - Режим доступу: G. Biondich PMC A modern Optical Character Recognition System in a real worldc clinical setting[Електроннии? ресурс] - Режим доступу: Finereader Documentation[Електроннии? ресурс] - Режим доступу: Tesseract Documentation Tesseract Open Source Engine [Електроннии? ресурс] - Режим доступу: Wai Foong Tesseract Guide [Електроннии? ресурс] - Режим доступу: Documentation [Електроннии? ресурс] - Режим доступу: - Is Java still relevant? [Електроннии? ресурс] - Режим доступу: Ltd - Nicomsoft OCR (NSOCR) API and List of Features - 2018Helen Borrie - The Firebird Book: A Reference for Database Developers - 2017 - 1128 с.Sergey Vasiliev - Code Quality Comparison of Firebird, MySQL, and PostgreSQL [Електроннии? ресурс] - Режим доступу: and Markets - Computer Vision Market Research [Електроннии? ресурс] - Режим доступу: ДОДАТКИДОДАТОК АЛ?СТИНГ КОДУКлас OCR_Engineimport NSOCR.NSInt;import NSOCR.Constant;import NSOCR.Engine;import NSOCR.HBLK;import static com.sun.javafx.util.Utils.split;import static fwdocumentrecognizer.OCR_APPLICATION.fwOcrAPP;import java.awt.Dimension;import java.awt.Rectangle;import java.awt.image.BufferedImage;import static java.lang.Math.abs;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.ArrayList;import java.util.*;import java.util.logging.Level;import java.util.logging.Logger;/** * класс отвечающий за распознавание текста в растровом изображении * * * @pdOid 7ff97e5d-2817-43f9-8b98-e1a11bea0602 */public class OCR_ENGINE { private BufferedImage fullSizeBmp; private final EngineObj engineObj; private EngineObj engineObj2; //private final String licenseKey = "AB2A4DD5FF2A"; private int stage; //** стадия процесса /* -2 не проинициализирован * -1 - документ не загружен * 0 OCRSTEP_FIRST 0x00 документ не загружен The first step in the OCR process. It only marks the OCR process as started. * 1 OCRSTEP_PREFILTERS 0x10 Applies image filters: image scaling, inversion, rotation, mirroring, and deskewing algorithms. See the "ImgAlizer" section in the configuration file for possible options. This step is performed only once, you cannot call it twice. * 2 OCRSTEP_BINARIZE 0x20 Calculates the binarized image. See the "Binarizer" section in the configuration file for possible options. If necessary, this step can be called several times with different parameters. * 3 OCRSTEP_POSTFILTERS 0x50 Applies filters to the binarized image. See such options as "BigGarbageMinWidth" or "SmallGarbageMaxPixCnt". If necessary, this step can be called several times with different parameters. * 4 OCRSTEP_REMOVELINES 0x60 Finds lines and removes them from the image. If necessary, this step can be called several times with different parameters. * 5 OCRSTEP_ZONING 0x70 If the image doesn’t have any defined blocks or has the BT_ZONING blocks, the page will be analyzed, and text and picture blocks will be created automatically. If necessary, this step can be called several times. * 6 OCRSTEP_OCR 0x80 Performs OCR of the image. If necessary, this step can be called several times with different parameters. * 7 OCRSTEP_LAST документ распознаный * * */ private int nBlocks; // число блоков private Invoice docProcessed; // документ который обрабатывается public static int TRANSFORM_COEF = 10000; private boolean drawBinary = true; /** * текущий блок =0 если блоков нет или текст ещё не распознан. Иначе * устанавливается в 1 * * private int curBlock; private int curWord; private int curLine; * * */ /** * конструктор движка OCR */ public OCR_ENGINE() { setStage(-2); // движок не проинициализирован engineObj = new EngineObj(); if (engineObj.isReady()) { setStage(-1); // движок проинициализирован } // создаём элементы инфраструктуры распознавания // Engine.Engine_InitializeAdvanced(CfgObj, ocr, img); // Engine.Scan_Create(CfgObj, hscan); сканер нам не нужен } /** * назначить обрабатываемый документ */ public void setDocProcessed(Invoice newDoc) { docProcessed = newDoc; fullSizeBmp = null; } /** * выдать обрабатываемый документ */ public Invoice getDocProcessed() { return docProcessed; } /** * @pdOid e25a13b0-c305-47d6-b5dd-6cb8d2775d81 */ public int getStage() { return stage; } /** * @param newStage * @pdOid c073faae-2d77-433d-a298-14a989f0df69 */ public void setStage(int newStage) { stage = newStage; } /** * загружает конфигурацию из указанного файла. возвращает код ошибки (0 * -успешно) * * @param configFile файл конфигурации (null если стандартный файл из * bin_common) * @pdOid 78ec092e-be91-4223-ac52-8fa65a160a95 */ public int loadCfg(String configFile) { // TODO: implement return 0; } /** * cохраняет текущие опции в указанном файле возвращает код ошибки (0 * -успешно) * * @param configFile * @pdOid ef9bfd72-bbdd-48e7-85fa-b168411f2d3a */ public int saveCfg(String configFile) { // TODO: implement return 0; } /** * разрушает старый и загружает новый документ. устанвыливает статус * процесса в OCRSTEP_FIRST или в -1 (проинициализировано не загружено). * * @return 0 успешно или код завершения */ public int loadImg() { byte[] fileContent; int err = -1; setStage(-1); // изображение не загружено fileContent = docProcessed.getInvoiceImage(); // получили изображение документа if (fileContent != null) { // есть изображение err = engineObj.Img_LoadFromMemory(fileContent, fileContent.length); if (err == 0) { setStage(Constant.OCRSTEP_FIRST); OCR_APPLICATION.logger.log(, "image loaded successfully"); //Logger.getLogger(OCR_ENGINE.class.getName()) } // успешно загружен else { OCR_APPLICATION.logger.log(Level.SEVERE, "image not loaded err={0}", err); } } else { OCR_APPLICATION.logger.log(Level.SEVERE, "image not obtained fom DB err={0}", err); } return err; } /** * выполняет распознавание до указанного шага * * @param lastStep * @return 0 успешно или код завершения */ public int run(int lastStep, boolean inOtherThread) { int err = -1; if (getStage() > 0 & lastStep > getStage()) { err = engineObj.Img_OCR(getStage(), lastStep, inOtherThread ? Constant.OCRFLAG_THREAD : Constant.OCRFLAG_NONE); if (err != 0) { OCR_APPLICATION.logger.log(Level.SEVERE, "image not recognised err={0}", err); } else { setStage(lastStep); } } else { OCR_APPLICATION.logger.log(Level.SEVERE, "stage not valid err={0}", err); } return err; } public int run(boolean inOtherThread) { int err = -1; if ((getStage() >= 0) & (getStage() < Constant.OCRSTEP_LAST)) { err = engineObj.Img_OCR(Constant.OCRSTEP_FIRST, Constant.OCRSTEP_LAST, inOtherThread ? Constant.OCRFLAG_THREAD : Constant.OCRFLAG_NONE); if (err != 0) { OCR_APPLICATION.logger.log(Level.SEVERE, "image not recognised err={0}", err); } else { setStage(Constant.OCRSTEP_LAST); } } else { OCR_APPLICATION.logger.log(Level.SEVERE, "stage not valid err={0}", err); } return err; } /** * возвращает текст указанной зоны (или всего документа если null/0) * * @param zoneNumber номер блока. null * @pdOid 5286b091-34b1-4212-beac-1d12b9629a37 */ public StringBuffer getText(Integer zoneNumber) { StringBuffer text = new StringBuffer(); if (zoneNumber == null) { engineObj.Img_GetImgText(text, Constant.FMT_EXACTCOPY); return text; } else { HBLK BlkObj = new HBLK(); engineObj.Img_GetBlock(zoneNumber - 1, BlkObj); getEngine().Blk_GetText(BlkObj, text, Constant.FMT_EXACTCOPY); return text; } } public String getText(int zone, int line, int word, int wordCount) { String res = ""; StringBuffer text = new StringBuffer(); HBLK BlkObj = new NSOCR.HBLK();// ид зоны int znCnt = engineObj.Img_GetBlockCnt(); //число зон if ((zone <= znCnt) & (zone > 0)) { // номер зоны в нужном диапазоне engineObj.Img_GetBlock(zone - 1, BlkObj); //получили зону int lnCnt = getEngine().Blk_GetLineCnt(BlkObj); // число строк if ((line <= lnCnt) & (line > 0)) { // номер линииы в нужном диапазоне int wdCnt = getEngine().Blk_GetWordCnt(BlkObj, line - 1); //число слов if ((word <= wdCnt) & (word > 0)) { // номер слова в нужном диапазоне getEngine().Blk_GetWordText(BlkObj, line - 1, word - 1, text); //get word text res = text.toString().trim(); if (wordCount > 1) { for (int i = word + 1; i < word + wordCount; i++) { if ((i <= wdCnt) & (i > 0)) { // номер слова в нужном диапазоне StringBuffer textI = new StringBuffer(); getEngine().Blk_GetWordText(BlkObj, line - 1, i - 1, textI); //get word text String sI = textI.toString().trim(); if (!sI.isEmpty()) { if (res.isEmpty()) { res = sI; } else { res = res + " " + sI; } } } } } } else { if (word == -1) { getEngine().Blk_GetLineText(BlkObj, line - 1, text); //get line text } else { //text.setLength(0);//номер слова вне диапазона } } } else { if (line == -1) { getEngine().Blk_GetText(BlkObj, text, Constant.FMT_EXACTCOPY); } else { //text.setLength(0);//номер слова вне диапазона } } } else { //text.setLength(0);//номер зоны вне диапазона } return res; } /** * save recognized text in data base * @return number of blocks saving or -1 if unsuccesful */ public int saveText(){ Integer blockCount=0; Integer res=-1; Invoice invoice=docProcessed; blockCount = DocFileOCRBlock.getDocFileOCRBlockCount(invoice.getDb().getMainDB(), invoice.getIdImg()); if (blockCount==null) return -1; if (blockCount>0){//delete old text if(!DocFileOCRBlock.delDocFileOCRBlocks(invoice.getDb().getMainDB(), invoice.getIdImg()) ) return -1; // unsuccessful deletion } try { invoice.getDb().getMainDB().setAutoCommit(false); try { for (int i = 1; i <= getZonesNumber(); i++) { StringBuffer blockText = getText(i); int[] zp = getZoneProp(i); int blockType = zp[10]; int blockXPOS = zp[0]; int blockYPOS = zp[1]; int blockWIDTH = zp[2]; int blockHEIGHT = zp[3]; if (DocFileOCRBlock.addDocFileOCRBlock(invoice.getDb(), invoice.getIdImg(), blockType, blockText.toString(), blockText.toString().hashCode(), blockXPOS, blockYPOS, blockWIDTH, blockHEIGHT) > 0) { blockCount++; } else { OCR_APPLICATION.logger.log(, "New block {0}insertion failed for DOC_FILE_ID = {1}", new Object[]{blockCount, invoice.getIdImg()}); invoice.getDb().getMainDB().rollback(); } } if (Invoice.saveRecognizeStageToDb(invoice.getDb().getMainDB(), invoice.getIdentifier(), RecognizeStage.RECOGNIZED_NOT_ANALYZED, 0, true) == 0) { invoice.getDb().getMainDB().rollback(); } invoice.getDb().getMainDB().commit(); OCR_APPLICATION.logger.log(, "{0} blocks inserted for DOC_FILE_ID = {1}", new Object[]{blockCount, invoice.getIdImg()}); res=blockCount; } finally { invoice.getDb().getMainDB().setAutoCommit(true); } } catch (SQLException ex) { OCR_APPLICATION.logger.log(Level.SEVERE, null, ex); } return res; } /** * получить размеры текстового блока * * * @param zoneNumber блок текста * @return параметры зоны (0) -лево (1) -верх (2) -длино (3) -высота в % 4) * -верх 5) -лево 6) -длино 7) -высота 8 число линий 9 ширина строки в * символах 10 тип блока */ public int[] getZoneProp(int zoneNumber) { int j; int[] prop = new int[12];// список свойств HBLK BlkObj = new NSOCR.HBLK();// ид зоны NSOCR.NSInt Xpos = new NSOCR.NSInt(0); NSOCR.NSInt Ypos = new NSOCR.NSInt(0); NSOCR.NSInt Width = new NSOCR.NSInt(0); NSOCR.NSInt Height = new NSOCR.NSInt(0); StringBuffer txt = new StringBuffer(); engineObj.Img_GetBlock(zoneNumber - 1, BlkObj); //get Block object prop[10] = getEngine().Blk_GetType(BlkObj); //get zone type getEngine().Blk_GetRect(BlkObj, Xpos, Ypos, Width, Height); //get zone position and size prop[0] = Xpos.GetValue(); prop[1] = Ypos.GetValue(); prop[2] = Width.GetValue(); prop[3] = Height.GetValue(); engineObj.Img_GetSize(Width, Height); prop[4] = prop[0] * OCR_ENGINE.TRANSFORM_COEF / Width.GetValue(); prop[6] = prop[2] * OCR_ENGINE.TRANSFORM_COEF / Width.GetValue(); prop[5] = prop[1] * OCR_ENGINE.TRANSFORM_COEF / Height.GetValue(); prop[7] = prop[3] * OCR_ENGINE.TRANSFORM_COEF / Height.GetValue(); prop[8] = getEngine().Blk_GetLineCnt(BlkObj); //get number of text lines for zone // res = NSOCR.Engine.Blk_Inversion(BlkObj, NSOCR.Constant.BLK_INVERSE_GET); //get zone inversion // res = NSOCR.Engine.Blk_Rotation(BlkObj, NSOCR.Constant.BLK_ROTATE_GET); //get zone rotation // res = NSOCR.Engine.Blk_Mirror(BlkObj, NSOCR.Constant.BLK_MIRROR_GET); //get zone mirror flag // res = NSOCR.Engine.Blk_GetBackgroundColor(BlkObj); //get zone background color // NSOCR.Engine.Blk_GetText(BlkObj, txt, NSOCR.Constant.FMT_EDITCOPY); //get zone text // System.out.println(txt); prop[9] = 0; for (j = 0; j < prop[8]; j++) { getEngine().Blk_GetLineText(BlkObj, j, txt); //get line text if (txt.length() > prop[9]) { prop[9] = txt.length(); } } // NSOCR.Engine.Blk_GetTextRect(BlkObj, j, -1, Xpos, Ypos, Width, Height); //get text line position and size // System.out.println(txt); // wcnt = NSOCR.Engine.Blk_GetWordCnt(BlkObj, j); //get number of words of "j"-th text line of zone // for (k = 0; k < wcnt; k++) // { // NSOCR.Engine.Blk_GetTextRect(BlkObj, j, k, Xpos, Ypos, Width, Height); //get word position and size // res = NSOCR.Engine.Blk_GetWordFontColor(BlkObj, j, k); //get word font color // res = NSOCR.Engine.Blk_GetWordFontSize(BlkObj, j, k); //get word font size // res = NSOCR.Engine.Blk_GetWordFontStyle(BlkObj, j, k); //get word font style // res = NSOCR.Engine.Blk_GetWordQual(BlkObj, j, k); //get word quality // res = NSOCR.Engine.Blk_IsWordInDictionary(BlkObj, j, k); //check if this word is in dictionary // NSOCR.Engine.Blk_GetWordText(BlkObj, j, k, txt); //get word text return prop; } /** * найти слово в позиции * * @param position позиция слова в % от размеров бланка * * @param left левый край в % от размеров бланка * @param up верхний край в % от размеров бланка * @param width ширина в % от размеров бланка * @param height высота в % от размеров бланка * @param presize точность совпадения в % от размеров бланка * @param fashion способ поиска 0- границы не отличаются в пределах заданной * точности 1 начальная позиция совпадает в пределах заданной точности * @param realPosition принимает реальные координаты 0- номер зоны 1 номер * строки 2 номер слова 3456 - положение слова в пикселях 78910 положение * слова в % размеров бланка 11121314 положение слова в % размеров зоны * @return выдаёт слово и его реальную позицию в изображении */ public String findPos(int left, int up, int width, int height, int presize, int fashion, int[] realPosition, int wordCount) { int right = left + width; int down = up + height; HBLK BlkObj = new NSOCR.HBLK();// ид зоны NSOCR.NSInt Xpos = new NSOCR.NSInt(0); NSOCR.NSInt Ypos = new NSOCR.NSInt(0); NSOCR.NSInt Wdth = new NSOCR.NSInt(0); NSOCR.NSInt Hght = new NSOCR.NSInt(0); engineObj.Img_GetSize(Wdth, Hght); int wBlank = Wdth.GetValue(); int hBlank = Hght.GetValue(); // получили размер бланка int znCnt = engineObj.Img_GetBlockCnt(); //число зон int zoneLeft = 0, zoneRight = 0, zoneUp = 0, zoneDown = 0; realPosition[0] = -1; //пока не нешли зону for (int k = 0; k < znCnt; k++) {// ищем зону engineObj.Img_GetBlock(k, BlkObj); //получили зону getEngine().Blk_GetTextRect(BlkObj, -1, -1, Xpos, Ypos, Wdth, Hght); zoneLeft = OCR_ENGINE.TRANSFORM_COEF * Xpos.GetValue() / wBlank; zoneRight = zoneLeft + OCR_ENGINE.TRANSFORM_COEF * Wdth.GetValue() / wBlank; zoneUp = OCR_ENGINE.TRANSFORM_COEF * Ypos.GetValue() / hBlank; zoneDown = zoneUp + OCR_ENGINE.TRANSFORM_COEF * Hght.GetValue() / hBlank; //получили позицию зоны в % от размеров бланка if ((zoneLeft <= (left + presize)) && (zoneUp <= (up + presize)) && ((zoneRight + presize) >= right) && ((zoneDown + presize) >= down)) { realPosition[0] = k + 1; break; // нашли зону которая содержит заданную область } } if (realPosition[0] == -1) { return null; //не нашли зону которая содержит заданную область } realPosition[1] = -1; //пока не нешли строку int lnCnt = getEngine().Blk_GetLineCnt(BlkObj); // число строк for (int k = 0; k < lnCnt; k++) {// ищем строку getEngine().Blk_GetTextRect(BlkObj, k, -1, Xpos, Ypos, Wdth, Hght); zoneLeft = OCR_ENGINE.TRANSFORM_COEF * Xpos.GetValue() / wBlank; zoneRight = zoneLeft + OCR_ENGINE.TRANSFORM_COEF * Wdth.GetValue() / wBlank; zoneUp = OCR_ENGINE.TRANSFORM_COEF * Ypos.GetValue() / hBlank; zoneDown = zoneUp + OCR_ENGINE.TRANSFORM_COEF * Hght.GetValue() / hBlank; //получили позицию строки в % от размеров бланка //if ((zoneLeft <= (left + presize)) && (zoneUp <= (up + presize)) && ((zoneRight + presize) >= right) && ((zoneDown + presize) >= down)) { if ((zoneLeft <= (left + presize)) && (zoneUp <= (up + presize)) && ((zoneDown + presize) >= down)) { realPosition[1] = k + 1; break; // нашли строку которая содержит заданную область } } if (realPosition[1] == -1) { return null; //не нашли строку которая содержит заданную область } realPosition[2] = -1; // пока не нашли слова int wdCnt = getEngine().Blk_GetWordCnt(BlkObj, realPosition[1] - 1); //число слов for (int k = 0; k < wdCnt; k++) {// ищем слово getEngine().Blk_GetTextRect(BlkObj, realPosition[1] - 1, k, Xpos, Ypos, Wdth, Hght); zoneLeft = OCR_ENGINE.TRANSFORM_COEF * Xpos.GetValue() / wBlank; zoneRight = zoneLeft + OCR_ENGINE.TRANSFORM_COEF * Wdth.GetValue() / wBlank; zoneUp = OCR_ENGINE.TRANSFORM_COEF * Ypos.GetValue() / hBlank; zoneDown = zoneUp + OCR_ENGINE.TRANSFORM_COEF * Hght.GetValue() / hBlank;//получили позицию слова в % от размеров бланка if ((Math.abs(zoneLeft - left) < presize) && (Math.abs(zoneUp - up) < presize)) { // начало совпадает в пределах точности if (fashion == -1) { // режим совпадения только начала realPosition[2] = k + 1; break; // нашли слово которая содержит заданную область } } if ((Math.abs(zoneRight - right) <= presize) && (Math.abs(zoneDown - down) <= presize)) { // конец совпадает в пределах точности if (fashion == 1) { // режим совпадения только конца realPosition[2] = k + 1; break; // нашли слово которая содержит заданную область } else { // // режим совпадения обоих концов if (realPosition[2] != -1) { // и начало совпало realPosition[2] = k + 1; break; } } } } if (realPosition[2] == -1) { for (int k = 0; k < wdCnt; k++) {// ищем слово getEngine().Blk_GetTextRect(BlkObj, realPosition[1] - 1, k, Xpos, Ypos, Wdth, Hght); zoneLeft = OCR_ENGINE.TRANSFORM_COEF * Xpos.GetValue() / wBlank; zoneRight = zoneLeft + OCR_ENGINE.TRANSFORM_COEF * Wdth.GetValue() / wBlank; zoneUp = OCR_ENGINE.TRANSFORM_COEF * Ypos.GetValue() / hBlank; zoneDown = zoneUp + OCR_ENGINE.TRANSFORM_COEF * Hght.GetValue() / hBlank;//получили позицию слова в % от размеров бланка if ((Math.abs(zoneDown - down) <= presize) && (Math.abs(zoneUp - up) < presize)) { // попали по высоте в пределах точности if (Rect.intervalsAreCrossing(zoneLeft, zoneRight, left, right)) {//пересеклись по горизонтали realPosition[2] = k + 1; break; } } } } if (realPosition[2] == -1) { return null; //не нашли слову в заданную область } realPosition[3] = Xpos.GetValue(); realPosition[4] = Ypos.GetValue(); realPosition[5] = Wdth.GetValue(); realPosition[6] = Hght.GetValue(); realPosition[7] = zoneLeft; realPosition[8] = zoneUp; realPosition[9] = zoneRight - zoneLeft; realPosition[10] = zoneDown - zoneUp; // сформировали его позицию // выдали слово return getText(realPosition[0], realPosition[1], realPosition[2], wordCount); } /** * найти слово в позиции * * @param position позиция слова в % от размеров бланка * * @param left левый край в % от размеров бланка * @param up верхний край в % от размеров бланка * @param width ширина в % от размеров бланка * @param height высота в % от размеров бланка * @param realPosition принимает реальные координаты 0- номер зоны 1 номер * строки 2 номер слова 3456 - положение слова в пикселях 78910 положение * слова в % размеров бланка 11121314 положение слова в % размеров зоны * @return выдаёт слово и его реальную позицию в изображении */ public String findPos2(int left, int up, int width, int height, int[] realPosition) { //EngineObj engineObj2 = fwOcrAPP.getTextRecognizer().getEngineObj2(); int res; Rect frame2 = new Rect(); frame2.left = (int) ((float) left * (float) getFullSizeBmp().getWidth() / (float) TRANSFORM_COEF); frame2.right = (int) (((float) left * (float) getFullSizeBmp().getWidth() / (float) OCR_ENGINE.TRANSFORM_COEF + (float) width * (float) getFullSizeBmp().getWidth() / (float) OCR_ENGINE.TRANSFORM_COEF - 1)) + 1; = (int) ((float) up * (float) getFullSizeBmp().getHeight() / (float) TRANSFORM_COEF); frame2.bottom = (int) (((float) up * (float) getFullSizeBmp().getHeight() / (float) OCR_ENGINE.TRANSFORM_COEF + (float) height * (float) getFullSizeBmp().getHeight() / (float) OCR_ENGINE.TRANSFORM_COEF - 1)) + 1; if (frame2.getWidth() > 0 && frame2.getHeight() > 0) { int[] resArr; resArr = getFullSizeBmp().getRGB(frame2.left, , frame2.getWidth(), frame2.getHeight(), null, 0, frame2.getWidth()); res = getEngineObj2().Img_LoadBmpData(resArr, frame2.getWidth(), frame2.getHeight(), NSOCR.Constant.BMP_32BIT); if (res > NSOCR.Error.ERROR_FIRST) { //JOptionPane.showMessageDialog(this, "Error Img_LoadBmpData " + Integer.toHexString(res)); Logger.getLogger(OCR_ENGINE.class.getName()).log(Level.SEVERE, "Error Img_LoadBmpData {0}", Integer.toHexString(res)); return null; } res = getEngineObj2().Img_OCR(Constant.OCRSTEP_FIRST, Constant.OCRSTEP_LAST, Constant.OCRFLAG_NONE); //res = engineObj2.Img_OCR(0, 0, Constant.OCRFLAG_NONE); if (res > NSOCR.Error.ERROR_FIRST) { Logger.getLogger(OCR_ENGINE.class.getName()).log(Level.SEVERE, "error Img_OCR {0}", Integer.toHexString(res)); return null; } //Logger.getLogger(DocImagePanel.class.getName()).log(, "engineObj2.Img_GetBlockCnt() = {0}", getEngineObj2().Img_GetBlockCnt()); StringBuffer text = new StringBuffer(); getEngineObj2().Img_GetImgText(text, Constant.FMT_EXACTCOPY); return text.toString().trim(); //curItem.setRegex(text.toString()); // записали текущее слово в шаблон } return null; } /** * @param zone номер зоны * @param line номер линии в зоне * @param word номер слова в линии * @return выдаёт позицию слова [0;1;2;3] - позиция слова относительно * бланка в % [4;5;6;7] - позиция слова относительно бланка в пикселях * [8;9;10;11] - позиция (лево верх длина высота )слова относительно зоны в * пикселях [12;13;14;15] - позиция (лево верх длина высота )слова * относительно зоны в % */ public int[] getWordPos(int zone, int line, int word) { int[] prop = new int[16];// список свойств HBLK BlkObj = new NSOCR.HBLK();// ид зоны NSOCR.NSInt Xpos = new NSOCR.NSInt(0); NSOCR.NSInt Ypos = new NSOCR.NSInt(0); NSOCR.NSInt Width = new NSOCR.NSInt(0); NSOCR.NSInt Height = new NSOCR.NSInt(0); int znCnt = engineObj.Img_GetBlockCnt(); //число зон if ((zone <= znCnt) & (zone > 0)) { // номер зоны в нужном диапазоне engineObj.Img_GetSize(Width, Height); int wBlank = Width.GetValue(); int hBlank = Height.GetValue(); // получили размер бланка engineObj.Img_GetBlock(zone - 1, BlkObj); //получили зону int lnCnt = getEngine().Blk_GetLineCnt(BlkObj); // число строк getEngine().Blk_GetTextRect(BlkObj, -1, -1, Xpos, Ypos, Width, Height); //get zone position and size prop[12] = Xpos.GetValue(); prop[13] = Ypos.GetValue(); prop[14] = Width.GetValue(); prop[15] = Height.GetValue(); if ((line <= lnCnt) & (line > 0)) { // номер линииы в нужном диапазоне int wdCnt = getEngine().Blk_GetWordCnt(BlkObj, line - 1); //число слов if ((word <= wdCnt) & (word > 0)) { // номер линииы в нужном диапазоне getEngine().Blk_GetTextRect(BlkObj, line - 1, word - 1, Xpos, Ypos, Width, Height); //get word position and size prop[4] = Xpos.GetValue(); prop[5] = Ypos.GetValue(); prop[6] = Width.GetValue(); prop[7] = Height.GetValue(); prop[0] = OCR_ENGINE.TRANSFORM_COEF * prop[4] / wBlank; prop[1] = OCR_ENGINE.TRANSFORM_COEF * prop[5] / hBlank; prop[2] = OCR_ENGINE.TRANSFORM_COEF * prop[6] / wBlank; prop[3] = OCR_ENGINE.TRANSFORM_COEF * prop[7] / hBlank; prop[8] = prop[4] - prop[12]; prop[9] = prop[5] - prop[13]; prop[10] = prop[6]; prop[11] = prop[7]; wBlank = prop[14]; hBlank = prop[15]; prop[12] = OCR_ENGINE.TRANSFORM_COEF * prop[8] / wBlank; prop[13] = OCR_ENGINE.TRANSFORM_COEF * prop[9] / hBlank; prop[14] = OCR_ENGINE.TRANSFORM_COEF * prop[6] / wBlank; prop[15] = OCR_ENGINE.TRANSFORM_COEF * prop[7] / hBlank; } else { prop[0] = -3;//номер слова вне диапазона } } else { prop[0] = -2;//номер линии вне диапазона } } else { prop[0] = -1;//номер зоны вне диапазона } return prop; } /** * смещает текущую позицию в тексте на указанное число строк и слов * возвращает возвращает 0 смещение корректно 1- выход строки за пределы 2- * выход слова за пределы * * @param lineShift * @param wordShift * @param lineOut 0 не менять позицию если вышли за пределы 1 устанавливать * позицию в граничную если вышли за пределы * @param wordOut 1не менять позицию если вышли за пределы 2 устанавливать * позицию в граничную если вышли за пределы * @param wordShiftType 1- смещать номер слова независимо от изменения * строки 2 -смещать относительно начала строки если строка изменяется 3 - * смещать номер слова в зоне * @return * */ public int[] movePos(int lineShift, int wordShift, int lineOut, int wordOut, int wordShiftType) { // TODO: implement return null; } /** * выдаёт * * @return изображение звгруженног в движок */ public BufferedImage getImage() { return getImage(isDrawBinary()); } /** * выдаёт * * @return изображение звгруженног в движок */ public BufferedImage getImage(boolean drawBinary) { if (!isImgLoaded()) { return null; } NSInt width = new NSInt(0); NSInt height = new NSInt(0); if (engineObj.Img_GetSize(width, height) > NSOCR.Error.ERROR_FIRST) { return null; } return getImage(width.Value, height.Value); } /** * выдаёт * * @return изображение звгруженног в движок */ public BufferedImage getImage(int newWidth, int newHeight) { return getImage(newWidth, newHeight, isDrawBinary()); } /** * выдаёт * * @return изображение звгруженног в движок */ public BufferedImage getImage(int newWidth, int newHeight, boolean drawBinary) { if (!isImgLoaded()) { return null; } NSInt width = new NSInt(newWidth); NSInt height = new NSInt(newHeight); if (width.Value <= 0 || height.Value <= 0) { return null; } int bmpdata[] = new int[width.Value * height.Value]; if (drawBinary) { engineObj.Img_GetBmpData(bmpdata, width, height, NSOCR.Constant.DRAW_BINARY); } else { engineObj.Img_GetBmpData(bmpdata, width, height, NSOCR.Constant.DRAW_NORMAL); } if (width.Value == 0 || height.Value == 0) { return null; } BufferedImage bmp = new BufferedImage(width.Value, height.Value, BufferedImage.TYPE_INT_ARGB); bmp.setRGB(0, 0, width.GetValue(), height.GetValue(), bmpdata, 0, width.GetValue()); return bmp; } public int[] getImgSize() { NSInt width = new NSInt(0); NSInt height = new NSInt(0); int[] size = new int[2]; int err = engineObj.Img_GetSize(width, height); // if (err > NSOCR.Error.ERROR_FIRST) { не пущает т.к NSOCR.Error.ERROR_FIRST=1879048192 что гораздо более 0 при нормальном возврате if (err == 0) { // успешно получила размер size[0] = width.Value; size[1] = height.Value; } return size; } private boolean isImgLoaded() { NSInt width = new NSInt(0); NSInt height = new NSInt(0); if (engineObj.Img_GetSize(width, height) > NSOCR.Error.ERROR_FIRST) { return false; } return (width.Value > 0) && (height.Value > 0); } /** * выдаёт число зон * * @return число зон и 0 если текст ещё не распознан */ public int getZonesNumber() { int nz = 0; if (Constant.OCRSTEP_LAST == getStage()) { nz = engineObj.Img_GetBlockCnt(); //get number of zones setnBlocks(nz); } return nz; } public int getnBlocks() { return nBlocks; } public void setnBlocks(int nBlocks) { this.nBlocks = nBlocks; } public float getCurDocScale(int w, int h) { if (!isImgLoaded()) { return 1.0f; } NSInt width = new NSInt(0); NSInt height = new NSInt(0); engineObj.Img_GetSize(width, height); float kX = (float) w / width.Value; float kY = (float) h / height.Value; float k; if (kX > kY) { k = kY; } else { k = kX; } return k; } /** check if template applicable for loaded document * * @param dt template for check * @return true if recognized document text contains all keywords of template */ public boolean isTemplateApplicable(DocTemplate dt) { boolean isApplicable=true; StringBuffer text = new StringBuffer(); engineObj.Img_GetImgText(text, Constant.FMT_EXACTCOPY); for (DocMeta dm : dt.getData()) { if (dm.getType() == DocMetaType.BLANK_KEY_WORD){ String keyWord = dm.getRegex(); if (text.indexOf(keyWord)==-1) { return false; } } } return isApplicable; } /** find templates applicable for loaded document * @return list of template's id applicable for loaded document * null in case of exeption */ public List<Integer> findTemplate() { List<Integer> templPull; Supplier supplier=getDocProcessed().getSupplier(); if (supplier == null)supplier = new Supplier(OCR_APPLICATION.fwOcrAPP.getDocDb()); int supplierId=supplier.getIdentifier(); DocTemplate dt=new DocTemplate(OCR_APPLICATION.fwOcrAPP.getDocDb()); if (supplierId == DbObject.NOT_EXIST){ if (OCR_APPLICATION.fwOcrAPP.getDocRecognizer().getTmplPull().loadNextPull()>0){ // todo обрабатывается только 1 пулл !!!! если темплейтов станет больше то будут просматриваться только первые 50!! // todo сделать цикл по пулам пока не просканируем всю базую При этом начинать с тек пула до конца бд и поом сначала до первого templPull=OCR_APPLICATION.fwOcrAPP.getDocRecognizer().getTmplPull().getPull(); for (Integer id:templPull) { dt.loadObject(id); if (isTemplateApplicable(dt)){ supplier=dt.getSupplier(); break; } } }else { return null; } } return supplier.getTemplList(DocType.INVOICE); } /** * @return the drawBinary */ public boolean isDrawBinary() { return drawBinary; } /** * @param drawBinary the drawBinary to set */ public void setDrawBinary(boolean drawBinary) { this.drawBinary = drawBinary; } /** * @return the engine */ private Engine getEngine() { return engineObj.getEngine(); } public int Img_GetSize(NSInt Width, NSInt Height) { return engineObj.Img_GetSize(Width, Height); } public EngineObj getEngineObj() { return engineObj; } public EngineObj getEngineObj2() { if (engineObj2 == null) { engineObj2 = new EngineObj(); } return engineObj2; } /** * @return the fullSizeBmp */ public BufferedImage getFullSizeBmp() { if (fullSizeBmp != null) { return fullSizeBmp; } else { fullSizeBmp = fwOcrAPP.getTextRecognizer().getImage(true); } return fullSizeBmp; }/** определяет расположение ключевого слова в тексте документа * * @param recvDef метаописание ключевого слова * @param precision точность опредеоения * @return */ Rectangle getKeyRect(DocMeta recvDef) { String[] keywords; // ключевое слово Rectangle keyRect=null; // область найденного совпадения int dist,oldDist; // различия в расположении int fConsidence; // 1e coвпадение под слов int nConsidence,oldConsidence; // число совп слов int iNextSubWord; int iNextWord; int iPreviousSubWord; int iPreviousWord; StringBuffer TextStr=new StringBuffer (); HBLK BlkObj = new NSOCR.HBLK();// ид зоны NSOCR.NSInt Xpos = new NSOCR.NSInt(0); NSOCR.NSInt Ypos = new NSOCR.NSInt(0); NSOCR.NSInt Wdth = new NSOCR.NSInt(0); NSOCR.NSInt Hght = new NSOCR.NSInt(0); keywords =split(recvDef.getRegex()," "); // слова в ключевой фразе int nKsubWords=keywords.length; if (recvDef.getWord()==0){// реквизит не был распознан в исходном документе return null; } engineObj.Img_GetSize(Wdth, Hght); int wBlank = Wdth.GetValue(); int hBlank = Hght.GetValue(); // получили размер бланка int znCnt = engineObj.Img_GetBlockCnt(); //число зон int zoneLeft = 0, zoneRight = 0, zoneUp = 0, zoneDown = 0; // все строки в них и все слова на предмет совпадения с ключевым oldDist=-1; oldConsidence=-1; boolean isFind; for (int k = 0; k < znCnt; k++) {//просмотреть все зоны engineObj.Img_GetBlock(k, BlkObj); //получили зону getEngine().Blk_GetTextRect(BlkObj, -1, -1, Xpos, Ypos, Wdth, Hght); int lnCnt = getEngine().Blk_GetLineCnt(BlkObj); // число строк в этой зоне for (int l = 0; l < lnCnt; l++) {// все строки в ней int wdCnt = getEngine().Blk_GetWordCnt(BlkObj, l); //число слов for (int w= 0; w < wdCnt; w++) {// ищем слово engineObj.getEngine().Blk_GetWordText(BlkObj, l, w, TextStr) ; // выдрали слово if (fConsidence>=0){// есь совпадение с 1 словом в ключевой фразе isFind=true; nConsidence++; getEngine().Blk_GetTextRect(BlkObj, l, w, Xpos, Ypos, Wdth, Hght); // определили прямоугольник содержащий это слово zoneLeft = OCR_ENGINE.TRANSFORM_COEF * Xpos.GetValue() / wBlank; zoneRight = zoneLeft + OCR_ENGINE.TRANSFORM_COEF * Wdth.GetValue() / wBlank; zoneUp = OCR_ENGINE.TRANSFORM_COEF * Ypos.GetValue() / hBlank; zoneDown = zoneUp + OCR_ENGINE.TRANSFORM_COEF * Hght.GetValue() / hBlank; //получили позицию зоны в % от размеров бланка // if (fConsidence>0){ // не первое слово // iPreviousSubWord=fConsidence-1; // iPreviousWord=w-1; // while(iPreviousSubWord>=0 && iPreviousWord>=0 ){ // пристыковываем к нему все слова слева из движка // iPreviousSubWord--; // iPreviousWord--; // } // getEngine().Blk_GetTextRect(BlkObj, l, iPreviousWord+1, Xpos, Ypos, Wdth, Hght); // определили прямоугольник содержащий это слово // zoneLeft = OCR_ENGINE.TRANSFORM_COEF * Xpos.GetValue() / wBlank; // } if (nKsubWords>1){// не последнее подслово iNextSubWord=1; iNextWord=w+1; while(iNextSubWord< nKsubWords && iNextWord<wdCnt ){ // определяем правое крайнее engineObj.getEngine().Blk_GetWordText(BlkObj, l, iNextWord, TextStr) ; // выдрали слово int indx=TextStr.indexOf(keywords[iNextSubWord]); if (indx>=0){// есь совпадение со след словом в ключевой фразе nConsidence++; //увеличиваем число совпавших } else { // подслово в ключевой фразе не то isFind=false; break; } iNextSubWord++; iNextWord++; } getEngine().Blk_GetTextRect(BlkObj, l, iNextWord-1, Xpos, Ypos, Wdth, Hght); // рихтуем правую границу zoneRight = OCR_ENGINE.TRANSFORM_COEF *( Xpos.GetValue() + Wdth.GetValue()) / wBlank; // w=iNextWord-1; рихтуем счётчик слов (w) с учётом проверенных подслов } if (isFind){ dist=abs(recvDef.getUp()-zoneUp)+ abs(recvDef.getLeft()-zoneLeft); if ((oldDist==-1) ||( dist <oldDist)){// среди всех найденых совпадений выбрать ближайший к шаблону по совпадению ирасположению if (keyRect==null )keyRect = new Rectangle(); keyRect.setLocation(zoneLeft,zoneUp); keyRect.setSize(zoneRight-zoneLeft,zoneDown-zoneUp); oldDist=dist; // oldConsidence=nConsidence; } } } } } } return keyRect; } /** * для указанного реквизита по его метаописанию и заданному смещению разыскивает в распознанном тексте слово имеющее * такое же расположение с указанной точностью усли таковых несколько выбирается наиболее близкое * заносит его в спецификацию результата * @param recv спецификация результата * @param shift - смещение * @return труй если успешно найдено и сформировано результат фалсе если не удалось * причина осаждается в спецификации в поле статус */ boolean findDataByPos(DocRecv recv, Dimension shift,int presize) { Rectangle dataRect=null; // область поиска Rectangle findedRect=null;// область найденного текста DocMeta dataDef=recv.getRecvDef(); HBLK BlkObj = new NSOCR.HBLK();// ид зоны NSOCR.NSInt Xpos = new NSOCR.NSInt(0); NSOCR.NSInt Ypos = new NSOCR.NSInt(0); NSOCR.NSInt Wdth = new NSOCR.NSInt(0); NSOCR.NSInt Hght = new NSOCR.NSInt(0); engineObj.Img_GetSize(Wdth, Hght); StringBuffer lineText; int wBlank = Wdth.GetValue(); int hBlank = Hght.GetValue(); // получили размер бланка int znCnt = engineObj.Img_GetBlockCnt(); //число зон int zoneLeft = 0, zoneRight = 0, zoneUp = 0, zoneDown = 0; Rectangle inters; int sizeOfintersection; int oldSize; dataRect=new Rectangle(dataDef.getLeft()+shift.width, dataDef.getUp()+shift.height, dataDef.getWidth(), dataDef.getHeight()); // область поиска recv.setZone(-1); //пока не нешли зону oldSize=-1; for (int k = 0; k < znCnt; k++) {// ищем зону engineObj.Img_GetBlock(k, BlkObj); //получили зону lineText=this.getText(k+1); getEngine().Blk_GetTextRect(BlkObj, -1, -1, Xpos, Ypos, Wdth, Hght); Rectangle zoneRect=new Rectangle(OCR_ENGINE.TRANSFORM_COEF * Xpos.GetValue() / wBlank, OCR_ENGINE.TRANSFORM_COEF * Ypos.GetValue() / hBlank, OCR_ENGINE.TRANSFORM_COEF * Wdth.GetValue() / wBlank, OCR_ENGINE.TRANSFORM_COEF * Hght.GetValue() / hBlank ); //получили позицию зоны в % от размеров бланка inters= zoneRect.intersection(dataRect); // пересечение области с зоной if ((!inters.isEmpty()) && (!lineText.toString().trim().isEmpty())) {// нашли зону которая пересекается с заданной область sizeOfintersection=inters.height+inters.width; if ((oldSize==-1) || (sizeOfintersection > oldSize) ) {// она певрая или лучше уже найденной recv.setZone(k + 1); oldSize=sizeOfintersection; } } } if (recv.getZone()>=0) {//нашли зону которая содержит заданную область продолжаем поиск oldSize=-1; engineObj.Img_GetBlock(recv.getZone()-1, BlkObj); //получили зону recv.setLine(-1); //пока не нешли строку int lnCnt = getEngine().Blk_GetLineCnt(BlkObj); // число строк for (int k = 0; k < lnCnt; k++) {// ищем строку getEngine().Blk_GetTextRect(BlkObj, k, -1, Xpos, Ypos, Wdth, Hght); lineText=new StringBuffer(); getEngine().Blk_GetLineText(BlkObj, k, lineText); Rectangle lineRect=new Rectangle(OCR_ENGINE.TRANSFORM_COEF * Xpos.GetValue() / wBlank, OCR_ENGINE.TRANSFORM_COEF * Ypos.GetValue() / hBlank, OCR_ENGINE.TRANSFORM_COEF * Wdth.GetValue() / wBlank, OCR_ENGINE.TRANSFORM_COEF * Hght.GetValue() / hBlank ); //получили позицию строки в % от размеров бланка inters= lineRect.intersection(dataRect); // пересечение области с линией if (!inters.isEmpty()) {// нашли строку которая пересекается с заданной областью sizeOfintersection=inters.height+inters.width; if ((oldSize==-1) || (sizeOfintersection > oldSize) ) {// она певрая или лучше уже найденной recv.setLine(k + 1); oldSize=sizeOfintersection; } } } if (recv.getLine()>=0) {//нашли строку которая содержит заданную область продолжаем поиск int nLine=recv.getLine()-1; int wdCnt = getEngine().Blk_GetWordCnt(BlkObj, nLine); oldSize=-1; recv.setWord(-1); //пока не нашли слово recv.setNwords(0); for (int k = 0; k < wdCnt; k++) {// ищем слово getEngine().Blk_GetTextRect(BlkObj, nLine, k, Xpos, Ypos, Wdth, Hght); Rectangle wordRect=new Rectangle(OCR_ENGINE.TRANSFORM_COEF * Xpos.GetValue() / wBlank, OCR_ENGINE.TRANSFORM_COEF * Ypos.GetValue() / hBlank, OCR_ENGINE.TRANSFORM_COEF * Wdth.GetValue() / wBlank, OCR_ENGINE.TRANSFORM_COEF * Hght.GetValue() / hBlank ); inters= wordRect.intersection(dataRect); // пересечение области с словой if (!inters.isEmpty()) {// нашли слову которая пересекается с заданной областью if (recv.getNwords()==0) {// певрая слова recv.setWord(k + 1); recv.setNwords(1); } else{ recv.setNwords(recv.getNwords()+1); } } } if (recv.getNwords()!=0){ // нашлось слово recv.setRecvValue(getText(recv.getZone(), recv.getLine(), recv.getWord(), recv.getNwords())); recv.setStatus(0); } else{// слова не нашлась recv.setStatus(3); } } else{ // линия не нашлась recv.setStatus(2); } } else { // зона не нашлась recv.setStatus(1); } if (recv.getStatus()==0){//выделилась реквизита return true; } else{ return false; } } /** *для указанного реквизита по его метаописанию и заданному смещению разыскивает в распознанном тексте слово * заносит его в спецификацию результата * @param recv спецификация результата * @param shift - смещение * @return труй если успешно найдено и сформировано результат фалсе если не удалось * причина осаждается в спецификации в поле статус */ boolean findData(DocRecv recv, Dimension shift,int method,int precision) { switch (method){ case 1: return findDataByPos(recv,shift,precision); case 2: return findDataByEngine(recv,shift,precision); default: return false; } } /** *для указанного реквизита по его метаописанию и заданному смещению определяет зону в движке и распознаёт в ней текст * @param recv спецификация результата * @param shift - смещение * @return труй если успешно найдено и сформировано результат фалсе если не удалось * причина осаждается в спецификации в поле статус */ private boolean findDataByEngine(DocRecv recv, Dimension shift, int precision) { Rectangle dataRect=null; // область поиска DocMeta dataDef=recv.getRecvDef(); dataRect=new Rectangle(dataDef.getLeft()+shift.width, dataDef.getUp()+shift.height, dataDef.getWidth(), dataDef.getHeight()); // область поиска int res=0; int nStep=5; int iStep=0; String protocol=""; if (dataRect.width > 0 && dataRect.height > 0) { while (iStep<nStep){ int left= (int) ( (float)dataRect.x * (float) getFullSizeBmp().getWidth() / (float) TRANSFORM_COEF); int top=(int) ((float)dataRect.y * (float) getFullSizeBmp().getHeight() / (float) TRANSFORM_COEF); int hght=(int)((float)dataRect.height * (float) getFullSizeBmp().getHeight() / (float) OCR_ENGINE.TRANSFORM_COEF ); int wdth=(int)((float)dataRect.width * (float) getFullSizeBmp().getWidth() / (float) OCR_ENGINE.TRANSFORM_COEF ); int[] resArr; try { resArr = getFullSizeBmp().getRGB(left, top, wdth, hght, null, 0, wdth); res = getEngineObj2().Img_LoadBmpData(resArr, wdth, hght, NSOCR.Constant.BMP_32BIT); } catch (Exception ex){ recv.setStatus(9); protocol=protocol+"Load rectangle image failed for "+recv.getRecvDef().getName().name()+" step"+Integer.toString(iStep); protocol=protocol+"("+Integer.toString(left)+","+Integer.toString(top)+","+Integer.toString(wdth)+","+Integer.toString(hght)+")"; break; } if (res <= NSOCR.Error.ERROR_FIRST) { // образ загружен в движок успешно res = getEngineObj2().Img_OCR(Constant.OCRSTEP_FIRST, Constant.OCRSTEP_LAST, Constant.OCRFLAG_NONE); if (res <= NSOCR.Error.ERROR_FIRST) {// образ распознан успешно StringBuffer text = new StringBuffer(); getEngineObj2().Img_GetImgText(text, Constant.FMT_EXACTCOPY); recv.setRecvValue(text.toString().trim()); if (!recv.getRecvValue().isEmpty()){ recv.setStatus(0); break; // return true; } else { // OCR_APPLICATION.logger.log(Level.SEVERE, "extracted text is empty {0}", Integer.toHexString(res)); protocol=protocol+"extracted text is empty "+Integer.toString(iStep); recv.setStatus(10); // return false; } } else { //OCR_APPLICATION.logger.log(Level.SEVERE, "error Img_OCR {0}", Integer.toHexString(res)); protocol=protocol+"error Img_OCR"+Integer.toHexString(res)+" on step "+Integer.toString(iStep); recv.setStatus(9); //return false; } } else { //JOptionPane.showMessageDialog(this, "Error Img_LoadBmpData " + Integer.toHexString(res)); //OCR_APPLICATION.logger.log(Level.SEVERE, "Error Img_LoadBmpData {0}", Integer.toHexString(res)); protocol=protocol+"Error Img_LoadBmpData on step "+Integer.toString(iStep); recv.setStatus(8); // return false; } dataRect.grow( precision, precision); iStep++; } //curItem.setRegex(text.toString()); // записали текущее слово в шаблон }else { recv.setStatus(11); protocol=protocol+"data rectangle has zero size "; } if (!protocol.isEmpty()){ OCR_APPLICATION.logger.log(Level.SEVERE, protocol); } if (recv.getStatus()==0) { return true; }else{ return false; } }} Клас DOC_Engineimport java.awt.Dimension;import java.awt.Rectangle;import static java.lang.Math.abs;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.*;import javax.swing.JOptionPane;/** * анализатор текста * */public class DOC_ENGINE { private OCR_ENGINE textRecognizer;// движок распознавания текста. private final CurZoneModel curZone; // навигатор зон private final CurLineModel curLine;// навигатор строк private final CurWordModel curWord; // навигатор слов // private final CurRecvModel curRecv; // навигатор метаописания private ArrayList<DocRecv> result;//** массив распознанных реквизитов */ private int precision; // точность совпадения позиций при распознавании private int fashion; // метод обнаружения позиции private static final SimpleDateFormat[] dateFormats = new SimpleDateFormat[]{new SimpleDateFormat("dd/MM/yy"), new SimpleDateFormat("dd/MM/YYYY"), new SimpleDateFormat("dd MMM yy", Locale.ENGLISH), new SimpleDateFormat("dd MMM YYYY", Locale.ENGLISH)}; private TmplPull pull; // pull of templates private String extractReport; /** * конструктор анализатора текста * * @param tr - распознаватель текста */ public DOC_ENGINE(OCR_ENGINE tr) { textRecognizer = tr; // распознаватель текста curZone = new CurZoneModel(textRecognizer); // навигатор зон curLine = new CurLineModel(curZone); // навигатор строк curWord = new CurWordModel(curLine); // навигатор слов result = new java.util.ArrayList<>(); // результаты распознавания // docTemplate = new DocTemplate(tr.getDocProcessed().getDb()); // curRecv = new CurRecvModel(); // tr.getDocProcessed().setTemplate(docTemplate); precision = 50; // точность совпадения позиций при распознавании 0.5% от размера бланка fashion = -1; // обнаруживать совпадение начала и конца } /** * * @return выдаёт распознаватель текста */ public OCR_ENGINE getTextRecognizer() { return textRecognizer; } /** * * @return выдаёт обрабатываемый документ */ public Invoice getInvoice() { return textRecognizer.getDocProcessed(); } /** * * @return выдаёт текущую зону */ public CurZoneModel getCurZone() { return curZone; } /** * * @return выдаёт текущую строку в зоне */ public CurLineModel getCurLine() { return curLine; } /** * * @return выдаёт текущее слово в строке */ public CurWordModel getCurWord() { return curWord; } /** * * @return выдаёт текущий пункт метаописания */ // public CurRecvModel getCurRecv() { // return curRecv; // } /** * задаёт распознаватель текста * * @param newOcrObj */ public void setTextRecognizer(OCR_ENGINE newOcrObj) { textRecognizer = newOcrObj; } public void setTmplPull(TmplPull newPull) { pull = newPull; } public TmplPull getTmplPull() { if (pull==null){ pull=new TmplPull(); } return pull; } /** * * @return выдаёт метаописание бланка */ public DocTemplate getDocTemplate() { if (getInvoice() == null) { return null; } else { return getInvoice().getTemplate(); } } /** * @return возвращает массив выделенных реквизитов */ public ArrayList<DocRecv> getResult() { if (result == null) { result = new ArrayList<>(); } return result; } /** * @return возвращает реквизит по номеру null если i вне диапазона такового */ public DocRecv getResult(int i) { if ((i >= result.size()) | (i < 0)) { return null; } else { return result.get(i); } } /** * @return возвращает реквизит по метаописанию null если нет такового */ public DocRecv getResult(DocMeta meta) { int i = 0; if (result != null) { while (i < result.size()) { DocRecv rItem = result.get(i); if (rItem.getRecvDef() == meta) { return rItem; } i++; } } return null; } /** * задаёт метаописание бланка * * @param newDocTemplate */ public void setDocTemplate(DocTemplate newDocTemplate) { if (getInvoice() != null) { getInvoice().setTemplate(newDocTemplate); }// getCurRecv().setSource(newDocTemplate); } public int inputPrecision() { String answer = (String) javax.swing.JOptionPane.showInputDialog(null, "Input precision", "Input precision", JOptionPane.PLAIN_MESSAGE, null, null, getPrecision()); if (answer == null) { //throw new Error("User aborted operation!"); return -1; } try { setPrecision(Integer.parseInt(answer)); } catch (java.lang.NumberFormatException ex) { JOptionPane.showMessageDialog(null, "Can''t convert " + answer + " to integer!", "Message", JOptionPane.ERROR_MESSAGE); return -1; } return getPrecision(); } /** * анализирует текст . Формирует список распознаных реквизитов возвращает * код завершения 0 -успешно распознаны все реквизиты n>0 не распознано n * реквизитов * */ public int analyze() { removeAllResult(); // почистили результат распознавания return analyze(getDocTemplate(), getPrecision(), getResult()); } /** * анализирует текст . Формирует список распознаных реквизитов возвращает * код завершения 0 -успешно распознаны все реквизиты n>0 не распознано n * реквизитов * */ public int analyze(DocTemplate docTemplate) { removeAllResult(); // почистили результат распознавания return analyze(docTemplate, getPrecision(), getResult()); } /** * анализирует текст . Формирует список распознаных реквизитов возвращает * код завершения 0 -успешно распознаны все реквизиты n>0 не распознано n * реквизитов * */ public int analyze(DocTemplate docTemplate, ArrayList<DocRecv> result) { return analyze(docTemplate, getPrecision(), result); } /** * анализирует текст . Формирует список распознаных реквизитов возвращает * код завершения 0 -успешно распознаны все реквизиты n>0 не распознано n * реквизитов * */ public int analyze(DocTemplate docTemplate, int precision, ArrayList<DocRecv> result) { int errKod = 0; // пока нет ошибок распознавания extractReport="";// и протокол пустой ArrayList<Dimension> shiftList; Dimension bestshift; shiftList = getShift(docTemplate,precision); // получили смещение бланка for (DocMeta recvDef : docTemplate.getData()) { DocMetaType rType=recvDef.getType(); if (rType.getTypeId() > 0) { // не ключевое слово DocRecv recv = new DocRecv(); addResult(result, recv); // добавили значение recv.setRecvDef(recvDef); // прописали ссылку на метаописание rType.setRegEx(recvDef.getRegex()); int method=1; bestshift=shiftList.get(0); for (int m=1;m<3;m++){ // перепробуем последовательно все метоты вычленения for (int i=0; i<shiftList.size();i++){ // пройтись по разным смещениям if (textRecognizer.findData(recv,shiftList.get(i),m,precision)){// извлечение удалось проверим и улучшим если надо Integer nStep=1; // процедура улучшения boolean isRefinmentdone=false; while((! rType.check(recv,extractReport))&&(!isRefinmentdone) ){// пока не прошла проверка и есть ещё не проведенные процедуры улучшение isRefinmentdone=rType.refine(recv,nStep,extractReport);// проведём очередную процедуру улучшения nStep++; }// закончили улучшения и проверки if (recv.getStatus()==0){ // удалось if (i>0){ // переместим наверх удачное смещение bestshift=shiftList.get(i); //смещение которое подошло shiftList.set(i,shiftList.get(0)); shiftList.set(0, bestshift); } break; // больше не испытываем другие смещения } } else{ extractReport=extractReport+recv.getStatusAsString(); } }// закончили испытывать смещения if (recv.getStatus()==0){ // удалось break; // больше не испытываем другие методыя } } // закончили испытывать методы if (recv.getStatus()!=0){ // не удалось errKod++ ; } } }// закончили выделять все элементы return errKod; } /** * jопределяет смещение текущего бланка относительно шаблона по расположению ключевых слов * @param docTemplate метеописание шаблона * @param precision точность сравнения * @return null если нет ключевых слов или смещение меньше точности или средняя величина смещения */ public ArrayList<Dimension> getShift(DocTemplate docTemplate, int precision){ // получили смещение бланка Dimension shift=null; Rectangle keyRect; boolean isFit; ArrayList<Dimension> shList= new ArrayList<>(); shift=new Dimension(0,0); shList.add(shift); for (DocMeta recvDef : docTemplate.getData()) { // DocMetaType rType=recvDef.getType(); if (rType.getTypeId() ==0) { // для каждого ключевого слова htrdbpbnf в метаописании // для каждого ключевого слова в метаописании поискать его в тексте keyRect = textRecognizer.getKeyRect(recvDef); // определить его положение if (keyRect !=null){ shift=new Dimension(); shift.setSize(keyRect.x-recvDef.getLeft(),keyRect.y-recvDef.getUp()); // найти смещение isFit=false; for (Dimension oldShift : shList) { // сравнить с имеющимися if ((abs(oldShift.height-shift.height)<=precision) && (abs(oldShift.width-shift.width)<=precision) ){ isFit=true; break; } } if(!isFit) { shList.add(shift); }// добавить если ни с одним не совпало } } } if (shList.isEmpty()){ shift=new Dimension(0,0); shList.add(shift); } return shList; } /**extract data string from ocr Engine for given item in result and put this value * to recvValue item property and error code in status property * comments add to extractReport property of docEngine * * @param recv result item for extraction * @return true if extracted, false if not extracted */ public boolean extractDataValue(DocRecv recv){ String rValue; // принимает значение реквизита int[] realPosition = new int[15]; DocMeta recvDef=recv.getRecvDef(); rValue = textRecognizer.findPos(recvDef.getLeft(), recvDef.getUp(), recvDef.getWidth(), recvDef.getHeight(), precision, getFashion(), realPosition, recvDef.getNwords()); if (rValue == null || rValue.isEmpty()) { rValue = textRecognizer.findPos2(recvDef.getLeft(), recvDef.getUp(), recvDef.getWidth(), recvDef.getHeight(), realPosition); } recv.setRecvValue(rValue); if (rValue == null) {// не обнаружился реквизит if (realPosition[0] == -1) { recv.setStatus(1); extractReport=extractReport+"zone not found"; } if (realPosition[1] == -1) { recv.setStatus(2); extractReport=extractReport+"line not found"; } if (realPosition[3] == -1) { recv.setStatus(3); extractReport=extractReport+"word not found"; } return false; } else { recv.setStatus(0); return true; } } public int check(ArrayList<DocRecv> result) { int errs = 0; // пока нет ошибок String rValue; // значение реквизита DocMeta recvDef;// метаописание реквизита DocMetaType type; // тип реквизита // int[] realPosition = new int[15]; for (DocRecv recv : result) {// для каждого реквизита // for (DocMeta recvDef : result) { recvDef = recv.getRecvDef(); type = recvDef.getType(); rValue = recv.getRecvValue(); if (rValue == null) { recv.setStatus(4); // реквизит не определён errs++; extractReport=extractReport+"item "+recvDef.getType().getKod()+"not defined "; } else { if (rValue.trim().isEmpty()) { recv.setStatus(5); // пустой реквизит errs++; extractReport=extractReport+"item "+recvDef.getType().getKod()+"is empty"; } switch (type) { // в зависимости от типа реквизита // case BLANK_KEY_WORD: не проверяем // case REQ_KEY_WORD не проверяем // case STRING_VALUE : не проверяем case INT_VALUE: try { int nmb = Integer.parseInt(rValue.trim().replace(" ", "")); } catch (NumberFormatException ex) { recv.setStatus(6); // не соответствует формату extractReport=extractReport+"item "+type.getKod()+" = "+rValue+"wrong format"; } break; case FLOAT_VALUE: try { float net = Float.parseFloat(rValue.trim().replace("?", "").replace(" ", "")); } catch (NumberFormatException ex) { recv.setStatus(6); // не соответствует формату extractReport=extractReport+"item "+type.getKod()+" = "+rValue+" wrong format"; } break; case DATE_VALUE: if (!checkDateFormat(rValue)) { recv.setStatus(6); // не соответствует формату errs++; extractReport=extractReport+"item "+type.getKod()+" = "+rValue+" wrong format"; } break; } } } // Пока есть элементы, return errs; } public String getExtractReport(){ return extractReport; } public int check() { return check(getResult()); } /** * @pdGenerated default iterator getter */ public java.util.Iterator getIteratorResult() { if (result == null) { result = new java.util.ArrayList<>(); } return result.iterator(); } /** * @pdGenerated default setter * @param newResult */ public void setResult(java.util.Collection<DocRecv> newResult) { removeAllResult(); for (java.util.Iterator iter = newResult.iterator(); iter.hasNext();) { addResult((DocRecv) iter.next()); } } /** * @pdGenerated default add * @param newDocRecv */ public void addResult(DocRecv newDocRecv) { addResult(this.result, newDocRecv); } /** * @pdGenerated default remove * @param oldDocRecv */ public void removeResult(DocRecv oldDocRecv) { if (oldDocRecv == null) { return; } if (this.result != null) { if (this.result.contains(oldDocRecv)) { this.result.remove(oldDocRecv); } } } /** * @pdGenerated default removeAll */ public void removeAllResult() { if (result != null) { result.clear(); } } /** * @return the precision */ public int getPrecision() { return precision; } /** * @param precision the precision to set */ public void setPrecision(int precision) { this.precision = precision; } /** * @return the fashion */ public int getFashion() { return fashion; } /** * @param fashion the fashion to set */ public void setFashion(int fashion) { this.fashion = fashion; } private void addResult(ArrayList<DocRecv> result, DocRecv newDocRecv) { if (newDocRecv == null) { return; } if (result == null) { result = new java.util.ArrayList<>(); } if (!result.contains(newDocRecv)) { result.add(newDocRecv); } } public static boolean checkDateFormat(String date) { boolean dateParsed = false; if (date != null && !date.trim().isEmpty()) { for (SimpleDateFormat stamp : dateFormats) { try { Date d = stamp.parse(date.trim()); dateParsed = true; break; } catch (ParseException ex) { } } } return dateParsed; }}Клас DocMetaTypeimport java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Locale;public enum DocMetaType { BLANK_KEY_WORD { @Override public String getDecription() { return "template key word"; } @Override public int getTypeId() { return -1; } @Override public String getRegEx() { return ".*"; } @Override public void setRegEx(String regEx) { return; } @Override public String getName() { return "template key word"; } @Override public String getKod() { return "IdKey"; } @Override public boolean check(DocRecv dataItem, String prot) { dataItem.setStatus(0); return true; // не проверяется } @Override public boolean refine(DocRecv dataItem, Integer nStep, String prot) { return true; // не улучшается } }, REQ_KEY_WORD { @Override public String getDecription() { return "value key word"; } @Override public int getTypeId() { return 0; } @Override public String getRegEx() { return ".*"; } @Override public void setRegEx(String regEx) { return; } @Override public String getName() { return "value key word"; } @Override public String getKod() { return "v_key"; } @Override public boolean check(DocRecv dataItem, String prot) { dataItem.setStatus(0); return true; // не проверяется } @Override public boolean refine(DocRecv dataItem, Integer nStep, String prot) { return true; // не проверяется } }, INT_VALUE { @Override public String getDecription() { return "Integer"; } @Override public int getTypeId() { return 1; } @Override public String getRegEx() { return "\\d*"; } @Override public void setRegEx(String regEx) { return; } @Override public String getName() { return "INT"; } @Override public String getKod() { return "INT"; } @Override public boolean check(DocRecv dataItem, String prot) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } @Override public boolean refine(DocRecv dataItem, Integer nStep, String prot) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } }, FLOAT_VALUE { @Override public String getDecription() { return "Money"; } @Override public int getTypeId() { return 2; } @Override public String getRegEx() { return "\\d*\\.\\d*"; } @Override public void setRegEx(String regEx) { return; } @Override public String getName() { return "FLOAT"; } @Override public String getKod() { return "FLOAT"; } @Override public boolean check(DocRecv dataItem, String prot) { String rValue=dataItem.getRecvValue(); if (rValue==null){ dataItem.setStatus(1); prot=prot+dataItem.getRecvDef().getName()+"hasn't value"; return false; }else{ if (rValue.isEmpty()){ dataItem.setStatus(2); prot=prot+dataItem.getRecvDef().getName()+"is empty"; return false; } try { float net = Float.parseFloat(rValue); dataItem.setStatus(0); // соответствует формату // prot=prot+"item "+dataItem.getRecvDef().getName()+" = "+rValue+" is valid"; return true; } catch (NumberFormatException ex) { dataItem.setStatus(6); // не соответствует формату prot=prot+"item "+dataItem.getRecvDef().getName()+" = "+rValue+" wrong format"; return false; } } } @Override public boolean refine(DocRecv dataItem, Integer nStep, String prot) { boolean isLast=false; String rValue=dataItem.getRecvValue(); switch (nStep) { // в зависимости от номера процедуры case 1: // удаление пробелов dataItem.setRecvValue(rValue.replaceAll("\\s", "")); break; case 2: // удаление неправильных символов dataItem.setRecvValue(rValue.replaceAll("[^0123456789.,]", "")); break; case 3: // замена запятых на точку rValue= rValue.replace(",","."); dataItem.setRecvValue(rValue); break; case 4: // удаление лишних точек String[] parts=rValue.split("\\.");//Развалили на части if (parts.length>2){ //есть более 1 точки rValue=""; for (int i=0;i<parts.length-1;i++){ rValue=rValue+parts[i]; } rValue=rValue+"."+parts[parts.length-1]; } dataItem.setRecvValue(rValue); isLast=true; break; default: isLast=true; break; } return isLast; } }, STRING_VALUE { @Override public String getDecription() { return "String"; } @Override public int getTypeId() { return 3; } @Override public String getRegEx() { return ""; } @Override public void setRegEx(String regEx) { return; } @Override public String getName() { return "String"; } @Override public String getKod() { return "String"; } @Override public boolean check(DocRecv dataItem, String prot) { String rValue=dataItem.getRecvValue(); if (rValue==null){ dataItem.setStatus(1); prot=prot+dataItem.getRecvDef().getName()+"hasn't value"; return false; }else{ if (rValue.isEmpty()){ dataItem.setStatus(2); prot=prot+dataItem.getRecvDef().getName()+"is empty"; return false; } } dataItem.setStatus(0); return true; } @Override public boolean refine(DocRecv dataItem, Integer nStep, String prot) { return true; // улучшение не производится } }, DATE_VALUE { String regExFormat = "dd/mm/yy"; @Override public String getDecription() { return "Date"; } @Override public int getTypeId() { return 4; } @Override public String getRegEx() { return regExFormat; } @Override public void setRegEx(String regEx) { this.regExFormat = regEx; } @Override public String getName() { return "DATE"; } @Override public String getKod() { return "DATE"; } @Override public boolean check(DocRecv dataItem, String prot) { String rValue=dataItem.getRecvValue(); if (rValue==null){ dataItem.setStatus(1); prot=prot+dataItem.getRecvDef().getName()+"hasn't value"; return false; }else{ if (rValue.isEmpty()){ dataItem.setStatus(2); prot=prot+dataItem.getRecvDef().getName()+"is empty"; return false; } try { SimpleDateFormat stamp=new SimpleDateFormat(regExFormat, Locale.ENGLISH); Date d = stamp.parse(rValue); String dateFormatted = stamp.format(d); dataItem.setRecvValue(dateFormatted); // prot=prot+"item "+dataItem.getRecvDef().getName()+" = "+rValue+" is valid"; dataItem.setStatus(0); return true; } catch (ParseException ex) { prot=prot+"item "+dataItem.getRecvDef().getName()+" = "+rValue+" wrong format"; dataItem.setStatus(3); return false; } } } @Override public boolean refine(DocRecv dataItem, Integer nStep, String prot) { boolean isLast=false; String rValue=dataItem.getRecvValue(); switch (nStep) { // в зависимости от номера процедуры case 1: // удаление пробелов dataItem.setRecvValue(rValue.replaceAll("\\s", "")); break; case 2: // перевод альтернативных форматов (без пробелов) SimpleDateFormat[] dateFormats = new SimpleDateFormat[]{new SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH) , new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH), new SimpleDateFormat("dd/MM/yy", Locale.ENGLISH) , new SimpleDateFormat("MM/dd/yy", Locale.ENGLISH), new SimpleDateFormat("yyyy/MM/dd", Locale.ENGLISH) , new SimpleDateFormat("dd-MM-yyyy", Locale.ENGLISH), new SimpleDateFormat("MM-dd-yyyy", Locale.ENGLISH) , new SimpleDateFormat("dd-MM-yy", Locale.ENGLISH), new SimpleDateFormat("MM-dd-yy", Locale.ENGLISH) , new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH)}; SimpleDateFormat stdStamp = new SimpleDateFormat("dd/MM/yy"); for (SimpleDateFormat stamp : dateFormats) { try { Date d = stamp.parse(rValue); rValue=stdStamp.format(d); dataItem.setRecvValue(rValue); break; } catch (ParseException ex) { } } break; case 3: // перевод альтернативных форматов (с пробелами) String regex = "((?<=[a-zA-Z])(?=[0-9]))|((?<=[0-9])(?=[a-zA-Z]))"; String[] array = rValue.split(regex); rValue = String.join(" ", array); //вставляем пробелы обратно, что бы отделить буквы от цифр dateFormats = new SimpleDateFormat[]{new SimpleDateFormat("dd MMM yyyy", Locale.ENGLISH) , new SimpleDateFormat("dd MMMM yyyy", Locale.ENGLISH) , new SimpleDateFormat("EEEE dd MMMM yyyy", Locale.ENGLISH)}; stdStamp = new SimpleDateFormat("dd/MM/yy"); for (SimpleDateFormat stamp : dateFormats) { try { Date d = stamp.parse(rValue); rValue=stdStamp.format(d); dataItem.setRecvValue(rValue); break; } catch (ParseException ex) { } } isLast = true; break; default: isLast=true; break; } return isLast; } }, UNDEFINED { @Override public String getDecription() { return "UNDEFINED"; } @Override public int getTypeId() { return 5; } @Override public String getRegEx() { return ""; } @Override public void setRegEx(String regEx) { return; } @Override public String getName() { return ""; } @Override public String getKod() { return "IdKey"; } @Override public boolean check(DocRecv dataItem, String prot) { String rValue=dataItem.getRecvValue(); if (rValue==null){ dataItem.setStatus(1); prot=prot+dataItem.getRecvDef().getName()+"hasn't value"; return false; }else{ if (rValue.isEmpty()){ dataItem.setStatus(2); prot=prot+dataItem.getRecvDef().getName()+"is empty"; return false; } } dataItem.setStatus(0); return true; } @Override public boolean refine(DocRecv dataItem, Integer nStep, String prot) { return true; // улучшение не производится } }; public abstract String getDecription(); public abstract int getTypeId(); public abstract String getRegEx(); public abstract void setRegEx(String regEx); public abstract String getName(); public abstract String getKod(); /** * проверяет данное на всхожесть результат проверки осаждает в статусе данного и в протоколе * @param dataItem данное для проверки * @param prot протокол проверки * @return труй если всё нормально фалес если есть проблемы */ public abstract boolean check(DocRecv dataItem,String prot); /** выпоняет указанную процедуру улучшения для заданного данного * в случае проблем направляет в протокол комментарии * @param dataItem элемент данных результата распознавания * @param nStep номер процедуры улучшения * @param prot протокол * @return труй если процедура была последняя фалес если не последняя */ public abstract boolean refine(DocRecv dataItem,Integer nStep,String prot); public static DocMetaType parse(int type) { for (DocMetaType t : values()) { if (t.getTypeId() == type) { return t; } } return UNDEFINED; } public static DocMetaType parse(String type) { try { return valueOf(type); } catch (Exception ex) { return UNDEFINED; } }};ДОДАТОК БЖУРНАЛ ТЕСТУВАННЯ#Task descriptionsRemarks1First run of batch for document with doc_pi_import_id 21820. Template not found.2Teach of 21820, which NET and VAT was recognized with spaces " ". Teached including these spaces. Then run batch #2. Stop at 21821Add autodeletion of spaces3Teach of 21821, which ORDER_NUMBER was recognized as "№R76882" as one word. Teached including this symbol "№". Then run batch #3. Next 20822 succesfully recognized. 21824 - don’t have NET, VAT. Probably on the second page, but cannot see it in UI mode. 21825 - date (02/07/2014) was recognized as "02,'07/2014". 21826 - has attributes written by hand. 21827 - succesfully recognized.Problems with date recognizing4Teach of 21828 is impossible, cause zone is recognized as an image without any text in it.Bad blank5Teach of 21829. Batch #3 for documents 21829 -21835 - success. 6Teach of 21836, which order number is written by hand. So used another alphanumeric attribute for testing. Batch #4 for 21836-21840. All succesful.7Teach of 21841. Batch #5 for 21841-21844. Success.8Teach of 21845. Batch #6 for 21845-21851. All documents successful.9Teach of 21852. In every document date(like 12/06/18) was recognized like "12:R6'/1'8". Used other date in document in teaching for testing. Batch #7 for 21852-21855. 2 documents - success. 2 - had in NET,VAT letters.Date recognizing problems.One document was opened as vertical, but others of the same type was opened as horizontal.10Teach of 21856.Batch #8 for 21856-21869. All documents successful.11Teach of 21870. Batch #9 for 21870-21876. Success.12Teach of 21877. Batch #10 for 21877-21884. Success13Teach of 21885. Batch #11 for 21885-21890. Succesful - 2 documents. Other - not all attributes recognized.14Teach of 21891. Batch #12 for 21891-21898. Should be successful, but in every document same problem. Example - NET:"426.61", VAT:"85. ", Total: 511. 93"". Add autodeletion of spaces.After that error - SUM NOT BALANCED.15Teach of 21899. Batch #13 for 21899-21908. 7 documents - success. 3 - not found template. The template is same, but for some reasons really no keyword in them.Bad blank16Teach of 21909. Batch #14 for 21909-21913. Only 3 document succesful. 1 - not ................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download