Программные средства для заполнения базы персональных данных

Исследование возможностей ускорения процессов заполнения базы персональных данных за счет сокращения ручного ввода данных путем применения технологий оптического распознавания символов. Проектирование, реализация и тестирование автоматизированной системы.

Рубрика Программирование, компьютеры и кибернетика
Вид дипломная работа
Язык русский
Дата добавления 10.07.2017
Размер файла 2,6 M

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru/

Размещено на http://www.allbest.ru/

СОДЕРЖАНИЕ

автоматизированный ввод база данные

ВВЕДЕНИЕ

1. ПОСТАНОВКА ЗАДАЧИ

Общее описание разрабатываемой системы

2. АНАЛИТИЧЕСКИЙ ОБЗОР

2.1 Теоретические основы

3. ПРОЕКТИРОВАНИЕ

3.1 Диаграмма вариантов использования

3.2 Архитектура приложения

3.3 Выбор инструментальных средств разработки

3.4 Проектирование структур данных и алгоритмов

3.5 Проектирование пользовательского интерфейса

4. РЕАЛИЗАЦИЯ

4.1 Создание проекта

4.2 Операция выбора режима

4.3 Операция распознавания

4.4 Корректировка и подтверждение распознанных данных

4.5 Механизм аутентификации

4.6 Просмотр документов

4.7 Обучение Tesseract

4.8 Сборка приложения

5. ТЕСТИРОВАНИЕ

5.1 Обоснование методики тестирования

5.2 Результаты тестирования

ЗАКЛЮЧЕНИЕ

СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ

ПРИЛОЖЕНИЯ

ВВЕДЕНИЕ

Несмотря на то, что в настоящее время большинство документов составляется на компьютерах, задача создания полностью электронного документооборота ещё далека до полной реализации. Как правило, существующие системы охватывают деятельность отдельных организаций, а обмен данными между организациями осуществляется с помощью традиционных бумажных документов.

Задача перевода информации с бумажных на электронные носители актуальна не только в рамках потребностей, возникающих в системах документооборота. Современные информационные технологии позволяют нам существенно упростить доступ к информационным ресурсам, накопленным человечеством, при условии, что они будут переведены в электронный вид.

Наиболее простым и быстрым способом перевода данных документов в цифровой формат является сканирование документов с помощью сканеров или захват изображения цифровой фотокамерой. Результатом их работы является цифровое изображение документа - графический файл. Более предпочтительным, по сравнению с графическим, является текстовое представление информации. Этот вариант позволяет существенно сократить затраты на хранение и передачу информации, а также позволяет реализовать все возможные сценарии использования и анализа электронных документов. Поэтому наибольший интерес с практической точки зрения представляет именно перевод бумажных носителей в текстовый электронный документ.

Цель данной ВКР - исследование возможностей ускорения процессов заполнения базы персональных данных. Это может быть достигнуто за счет сокращения ручного ввода персональных данных путем применения технологий оптического распознавания символов.

Данное исследование выполняется по предложению руководителя отдела разработки АО «Сбебанк-Технологии».

В ВКР решены следующие задачи:

1. Аналитический обзор существующих средств для автоматического заполнения базы персональных данных

2. Проектирование автоматизированной системы

3. Реализация системы

4. Тестирование системы

5. Проведен эксперимент по занесению персональных данных с помощью разработанной системы

Результаты работы докладывались на международной студенческой конференции «Молодые исследователи - регионам».

1. ПОСТАНОВКА ЗАДАЧИ

Одной из задач ввода формализованных документов является индексирование -- присвоение каждому документу набора атрибутов с возможностью автоматического ввода индексных полей с помощью распознавания. На рисунке 1 показаны основные этапы ввода формализованных документов [1].

Рисунок 1 - Схема системы ввода формализованных документов

После контроля данные отправляются в базу данных. Таким образом, результатом ввода форм чаще всего является не сам документ в исходном виде, а определенная запись в некоторой базе данных. Технологии распознавания печатных символов обозначаются термином оптическое распознавание символов (англ. optical character recognition, OCR). Задачи распознавания при вводе форм не обязательно связаны с распознаванием текста. При вводе форм может потребоваться распознавание различных меток и знаков, для которого тоже существует свой термин: OMR (Optical Mark Recognition).

В нашем случае индексируемыми документами являются документы, удостоверяющие личность, в частности, в работе исследование выполнялось над двумя типами документов - паспорт РФ и страховое свидетельство обязательного пенсионного страхования.

В качестве универсального устройства для проведения эксперимента был использован смартфон, поскольку он имеет цифровую камеру и обладает хорошими вычислительными возможностями для организации распознавания.

Общее описание разрабатываемой системы

Разрабатываемая система будет представлять собой приложение по ОС Android. Она должна предоставлять возможность автоматического ввода данных документов, удостоверяющих личность, а именно паспортов и страховых свидетельств государственного пенсионного страхования.

Приложение должно иметь базовый механизм аутентификации в целях конфиденциальности персональных данных. Введенные документы должны сохраняться в памяти устройства, а перед сохранением пользователю должна быть предоставлена возможность ручной корректировки распознанных данных. Сохраненные документы могут быть просмотрены или удалены. Разрабатываемая система должна работать исключительно в оффлайн-режиме.

Анализируя функции системы можно выделить следующие:

1. Регистрация и аутентификация пользователя

2. Получение изображения документа при помощи цифровой фотокамеры

3. Распознавание данных документа

4. Возможность корректировки распознанных данных

5. Сохранение данных документа в БД

6. Возможность просмотра ранее внесенных документов

7. Возможность удаления ранее внесенных документов

2. АНАЛИТИЧЕСКИЙ ОБЗОР

Аналитический обзор существующих решений по распознаванию данных документов

Поиск существующих свободно распространяемых решений, специализированных именно на распознавании документов, удостоверяющих личность, не дал результатов. Поэтому был проведен анализ продуктов, предлагающих возможности OCR, которые предлагают API или SDK для использования в собственном проекте [2]. Список ПО, удовлетворяющего условиям свободного распространения и наличия SDK, получился следующим: Tesseract, Puma.NET, CuneiForm, MeOCR, FreeOCR, Ocrad.

1. Tesseract

Наиболее популярная OCR-библиотека, разрабатываемая компанией Google. Поддерживает более 100 языков. Написана на языке C++, однако имеет обертку (wrapper) для языка Java.

2. Puma.NET

Обертка для CuneiForm для платформы .NET, следовательно, не может быть использована в приложении для ОС Android.

3. CuneiForm

Разработанная в России система оптического распознавания символов. Поддерживает 28 языков, в том числе русский. Последняя версия выпущена в 2011 году. Не предоставляет интерфейса для Java.

4. MeOCR

Не поддерживается с 2012 года. Средства разработки доступны только для платформы .NET

5. FreeOCR

Оболочка для Microsoft OCR Library. Может быть использована только на устройствах под управлением ОС Windows.

6. Ocrad

Написанная на C++ OCR-библиотека. Поддерживает только латинский алфавит, вследствие чего не может быть использована в проекте.

Таким образом, в качестве средства распознавания, наиболее подходит библиотека Tesseract. Однако изображение перед передачей на распознавание в Tesseract необходимо обработать: произвести фильтрацию и выделить блоки текста [3].

Существуют комплексные системы оптического распознавания символов, такие как ABBYY FineReader, CuneiForm и т.д., однако их использование в данном проекте не представляется возможным в связи с невозможностью или сложностью интеграции и громоздкостью пакетов.

2.1 Теоретические основы

Распознавание образов исследуется в рамках теории компьютерного зрения. Компьютерное зрение -- теория и технология создания машин, которые могут производить обнаружение, отслеживание и классификацию объектов [4]. В задачах компьютерного зрения входными данными является двумерный массив данных - то есть, изображение.

Процесс распознавания текста можно разбить на три этапа:

1. предварительная фильтрация и подготовка изображения;

2. логическая обработка результатов фильтрации;

3. алгоритмы принятия решений на основе логической обработки.

Границы между этапами очень условные. Для решения задачи далеко не всегда нужно применять методы из всех групп, бывает достаточно двух, а иногда даже одного.

2.1.1 Предварительная фильтрация и подготовка изображения

Большинство методов фильтрации используют операцию свертки. Значение каждого пикселя в выходном изображении равно сумме произведений значений матрицы свертки и соответствующих точек входного изображения.

Операции, выполняемые на этапе фильтрации:

1. Преобразование цветного изображения в оттенки серого для упрощения дальнейшей обработки. Пример приведен на рисунке 2.

Рисунок 2 - Преобразование изображения в оттенки серого

2. Сглаживание изображения - выполняется в целях уменьшения шума. Для выполнения операции сглаживания к изображению применяется фильтр. Пример сглаживания изображен на рисунке 3.

Рисунок 3 - Сглаживание изображения фильтром Гаусса

Существует множество фильтров, но наиболее часто используются следующие:

1) Размытие по рамке (box blur)

Простейший из фильтров. Каждый выходной пиксель равен среднему арифметическому соседних пикселей. Матрица свертки:

2) Размытие по Гауссу (Gaussian blur)

Несмотря на то, что этот алгоритм не самый быстрый, он нашел наибольшее применение. Функция свертки для одномерного изображения выглядит как представлено на рисунке 4.

Рисунок 4 - Функция свертки размытия по Гауссу

Если предположить, что изображение одномерное, можно заметить, что пиксель, находящийся в центре будет иметь больший коэффициент. Коэффициенты соседних пикселей уменьшаются с увеличением расстояния между ними и центральным пикселем.

3) Медианный фильтр (Median blur)

Заменяет каждый пиксель медианным значением соседних пикселей.

4) Двустороннее размытие (Bilateral blur)

Главной целью описанных выше фильтров является сглаживание изображения. Однако иногда фильтры не только снижают уровень шума, но также сглаживают границы, что не всегда допустимо. Для того, чтобы это избежать, применяются фильтры двустороннего размытия.

Так же, как и фильтр Гаусса, двусторонний фильтр ставит в соответствие каждому соседнему пикселю определенный коэффициент. Эти коэффициенты имеют две составляющих: первая соответствует коэффициенту фильтра Гаусса, а вторая учитывает разницу в интенсивности между соседними пикселями и тем, который рассчитывается.

3. Выделение границ

Для выделения символов на окружающем фоне применяют методы выделения признаков, в частности - методы выделения границ.

Выделение границ - метод для поиска границ объекта в пределах изображения. Он нацелен на поиск точек изображения, где резко меняется яркость.

Существует множество подходов к выделению границ, но практически все можно разделить на две категории: методы, основанные на поиске максимумов, и методы, основанные на поиске нулей. Методы, основанные на поиске максимумов, выделяют границы с помощью вычисления «силы края», обычно выражения первой производной, такого как величина градиента, и затем поиска локальных максимумов силы края, используя предполагаемое направление границы, обычно перпендикуляр к вектору градиента. Методы, основанные на поиске нулей, ищут пересечения оси абсцисс выражения второй производной, обычно нули лапласиана или нули нелинейного дифференциального выражения [5].

1) Оператор Собеля

Широко известным и довольно простым фильтром выделения границ является оператор Собеля. Он вычисляет приближенное значение градиента яркости изображения. Оператор Собеля использует две матрицы свертки для вычисления приблизительных значений производных по горизонтали и по вертикали изображения.

Если исходное изображение обозначить A, а изображения, где каждая точка соответствует приближенному значению производной в горизонтальном и вертикальном направлениях - и соответственно, то изображения производных будут рассчитываться следующим образом:

где - оператор свертки.

Координата x здесь возрастает «вправо», а y - «вниз». Значение градиента в каждой точке может быть вычислено, используя:

Имея эту информацию, мы также можем вычислить направление градиента:

Пример использования оператора Собеля изображен на рисунке 5.

Рисунок 5 - Пример использования оператора Собеля

2) Оператор Кэнни

Более широкое применение нашел оператор Кэнни. Он использует многоступенчатый алгоритм для обнаружения широкого спектра границ в изображении. Хотя он был разработан на заре компьютерного зрения, оператор обнаружения границ Кэнни до сих пор является одним из лучших детекторов. Кроме особенных частных случаев трудно найти детектор, который бы работал существенно лучше, чем детектор Кэнни [6].

Алгоритм оператора Кэнни состоит из следующих шагов:

· Применение фильтра Гаусса для снижения шума.

· Поиск градиентов (выполняется аналогично оператору Собеля). Направление градиента округляется до 0, 45, 90 или 135 °.

· Подавление немаксимумов - удаляются пиксели, которые скорее всего не являются частью границы. Остаются только тонкие линии.

· Двойная пороговая фильтрация и трассировка области неоднозначности. Задаются два пороговых значения (верхнее и нижнее), пиксель, градиент которого выше верхнего порога, принимается как граница, пиксель с градиентом ниже нижнего порога - отклоняется, пиксель с градиентом, находящимся между пороговыми значениями принимается как граница, только в случае, если рядом с ним находится пиксель с градиентом выше верхнего порога. Кэнни рекомендует, чтобы соотношение верхний порог/нижний порог находилось между 2 и 3. Пример использования оператора Кэнни приведен на рисунке 6.

Рисунок 6 - Пример использования оператора Кэнни

Из алгоритма следует, что выходное изображение является бинарным (это также видно на рисунке), что исключает необходимость пороговой фильтрации изображения для дальнейшего процесса распознавания, в отличие от оператора Собеля.

4. Морфологические операции

На заключительном этапе предварительной обработки символы должны быть объединены в блоки текста. Это может быть достигнуто путем применения морфологических операций. Рассмотрим 3 морфологических операции, которые необходимы при выполнении данного этапа: наращивание, эрозия, замыкание.

1) Наращивание (dilation):

Эта операция состоит из свертки изображения A с некоторой матрицей свертки B, обычно имеющей форму прямоугольника или эллипса.

Проходя каждый пиксель изображения, находится максимальное значение среди значений, перекрываемых матрицей свертки пикселей и значение текущего пикселя (расположенного в центре матрицы свертки) заменяется этим значением. Вследствие этого яркие области изображения «растут». Пример использования операции наращивания приведен на рисунке 7.

Рисунок 7 - Пример использования операции наращивания

2) Эрозия (erosion)

Эта операция обратна операции наращивания: вместо максимального значения среди значений, перекрываемых матрицей свертки пикселей, ищется минимальное значение. Это приводит к тому, что яркие области изображения становятся меньше, в то время как темные - «растут». Пример использования операции эрозии приведен на рисунке 8.

Рисунок 8 - Пример использования операции эрозии

3) Замыкание (closing)

Является последовательным выполнением операций наращивания и эрозии.

Операция замыкания «закрывает» небольшие внутренние «дырки» в изображении, и убирает углубления по краям области. Если к изображению применить сначала операцию наращивания, то мы сможем избавиться от малых дыр и щелей, но при этом произойдёт увеличение контура объекта. Избежать этого увеличения позволяет операция эрозия, выполненная сразу после наращивания с тем же структурным элементом [7]. Пример использования операции замыкания приведен на рисунке 9.

Рисунок 9 - Пример использования операции замыкания

2.1.2 Логическая обработка результатов фильтрации

Полученное на этапе предварительной обработки изображение содержит выделенные белым цветом области расположения блоков текста и может быть использовано для нахождения контуров блоков текста.

Контур - кривая, огибающая непрерывные блоки пикселей, имеющих одинаковый цвет и интенсивность.

После нахождения контуров, они должны быть заключены в прямоугольники - части изображения, находящиеся в этих прямоугольниках, и будут блоками текста, подлежащими распознаванию. Прямоугольники должны быть классифицированы в соответствии со структурой документа - например, в паспорте наименование органа выдачи расположено выше даты выдачи.

Для быстрого построения сложных приложений, использующих компьютерное зрение, существуют различные библиотеки. Одной из самых известных является библиотека компьютерного зрения OpenCV.

OpenCV имеет модуль обработки изображений imgproc, который включает весь спектр операций, описанных выше. Несмотря на то, что библиотека реализована на языке C++, она имеет обертку (wrapper) для языка Java, на котором ведется разработка под ОС Android, что избавляет от необходимости ручной настройки взаимодействия с кодом, написанным на C++, используя интерфейс JNI. Кроме обертки, поддерживаемой командой OpenCV, в которой отсутствует приличная часть интерфейсов, существует обертка JavaCPP, разрабатываемая командой Bytedeco.

Таким образом, для реализации первых двух этапов распознавания изображения - предварительной фильтрации и логической обработки изображения будет использована библиотека OpenCV, подключаемая через обертку JavaCPP.

2.1.3 Алгоритмы принятия решений на основе логической обработки

После выделения блоков текста, их фильтрации и классификации в соответствии со структурой полей в документе, отдельные блоки должны быть переданы для распознавания.

Распознавание символов может быть реализовано средствами OpenCV, например, при помощи алгоритма k ближайших соседей:

Алгоритм k ближайших соседей - один из простейших алгоритмов классификации, доступных для обучения с учителем. Основным принципом метода ближайших соседей является то, что объект присваивается тому классу, который является наиболее распространённым среди соседей данного элемента. Соседи берутся исходя из множества объектов, классы которых уже известны, и, исходя из ключевого для данного метода значения k высчитывается, какой класс наиболее многочислен среди них. Каждый объект имеет конечное количество атрибутов (размерностей). Пример классификации k ближайших соседей приведен на рисунке 10.

Рисунок 10 - Пример классификации k ближайших соседей. Тестовый образец (зеленый круг) должен быть классифицирован как синий квадрат (класс 1) или как красный треугольник (класс 2). Если k = 3, то она классифицируется как 2-й класс, потому что внутри меньшего круга 2 треугольника и только 1 квадрат. Если k = 5, то он будет классифицирован как 1-ый класс (3 квадрата против 2ух треугольников внутри большего круга).

Однако процессы разработки механизма распознавания и обучения алгоритма могут быть упрощены при использовании библиотеки оптического распознавания символов Tesseract. Преимущество Tesseract заключается в максимальной автоматизации процесса обучения шрифту и простоте его использования. Tesseract так же, как и OpenCV, имеет обертку в JavaCPP, дающую возможность использования его в проекте.

Распознанный в ходе предыдущих этапов текст будет использован для построения текстового представления документа и выведен на экран устройства для подтверждения корректности распознавания пользователем.

3. ПРОЕКТИРОВАНИЕ

3.1 Диаграмма вариантов использования

На основе технического задания была построена диаграмма вариантов использования. Она изображена на рисунке 11.

Рисунок 11 - Диаграмма вариантов использования разрабатываемой системы

3.2 Архитектура приложения

Все взаимодействие пользователей с приложениями в ОС Android построено на операциях (activity, активность). Операция - это компонент приложения, который выдает экран, и с которым пользователи могут взаимодействовать для выполнения каких-либо действий, например, набрать номер телефона, сделать фото, отправить письмо или просмотреть карту [8]. С программной точки зрения операция представляет Java-класс, наследующийся от класса android.app.Activity. С каждым activity должен быть ассоциирован определенный макет. Макет представляет собой XML-файл, в котором определена визуальная структура пользовательского интерфейса [9].

Архитектура приложения представлена на рисунке 12.

Рисунок 12 - Архитектура приложения

3.3 Выбор инструментальных средств разработки

Разработка приложения будет выполняться в интегрированной среде разработки Android Studio 2.3.2 - она является официально поддерживаемым компанией Google средством разработки под ОС Android.

Для обучения Tesseract предлагается официальная консольная утилита. Однако в таком случае, BOX-файлы необходимо вручную составлять в текстовом редакторе. Поэтому удобнее будет воспользоваться сторонними визуальными редакторами BOX-файлов. На ОС Windows может быть использован редактор jTessBoxEditor запускаемый на Java [10].

3.4 Проектирование структур данных и алгоритмов

3.4.1 Схема БД

База данных приложения будет состоять из трех таблиц:

1. USER - пользователи. Столбцы:

_ID - идентификатор,

USERNAME - имя пользователя,

PASSWORD - хеш-сумма пароля;

2. DOCUMENT_TYPE - типы документов. Столбцы:

_ID - идентификатор,

CODE - код (например, PASSPORT),

NAME - локализованное наименование;

3. DOCUMENT -документы.

_ID - идентификатор,

DOC_TYPE_ID - ID типа документа,

USER_ID - ID владельца документа,

DATA - данные документа

Схема БД представлена на рисунке 13.

Рисунок 13 - Схема БД

3.4.2 Алгоритмы

Основным и наиболее сложным алгоритмом в приложении является обработка изображения предпросмотра, которая включает в себя обнаружение и в случае необходимости распознавание полей. Алгоритмы для документов типа паспорт и страховое свидетельство отличаются только в том, что для паспорта необходимо учитывать вертикальное расположение серии и номера паспорта. В связи с этим целесообразно рассмотреть алгоритм для паспорта, как более сложный. Блок-схема алгоритма представлена на рисунке 14.

Рисунок 14 - Блок-схема алгоритма обработки изображения предпросмотра

Алгоритм подпрограммы обнаружения полей представлена на рисунке 15.

Рисунок 15 - Алгоритм подпрограммы обнаружения полей

Алгоритм подпрограммы распознавания текста в полях представлен на рисунках 16, 17.

Рисунок 16 - Алгоритм подпрограммы распознавания текста

Рисунок 17 - Алгоритм подпрограммы распознавания текста

3.5 Проектирование пользовательского интерфейса

Проектирование пользовательского интерфейса будет произведено путем создания макетов в Android Studio.

Макет формы аутентификации представлен на рисунке 18.

Рисунок 18 - Макет формы аутентификации

Макет формы выбора режима представлен на рисунке 19.

Рисунок 19 - Макет формы выбора режима

Макет формы списка документов представлен на рисунке 20.

Рисунок 20 - Макет формы списка документов

Макет формы верификации и просмотра документа представлен на рисунке 21.

Рисунок 21 - Макет формы верификации и просмотра документа

Макет операции распознавания содержит единственный компонент - окно предпросмотра, поэтому представление его здесь не имеет смысла.

4. РЕАЛИЗАЦИЯ

4.1 Создание проекта

Первым делом был создан проект в Android Studio. Минимальным необходимым для установки приложения уровнем API выбран уровень 15, поскольку с этого уровня добавлена поддержка непрерывного автофокуса, который будет необходим в приложении, и в тоже время обеспечивает поддержку приложений на устройствах с ОС Android 4.0 и выше, что на момент разработки ВКР покрывает 97,4 % используемых устройств на ОС Android [11].

4.2 Операция выбора режима

Сперва необходимо создать операцию средствами Android Studio. Для нее автоматически будет создан пустой макет. Класс операции будет иметь имя OperationActivity, а сгенерированный файл макета - соответственно, activity_operation.xml.

Визуальные компоненты в Android называются представлениями (view), и их базовым классом является android.view.View. Роль данной операции заключается в предоставлении пользователю выбора между режимами работы: внесением нового документа и просмотром существующего. Возможность выбора может быть реализована при помощи переключателя, который в Android представлен компонентом RadioButton. Несколько переключателей, из которых может быть выбран один, должны быть помещены в представление RadioGroup. Таким образом, на макет необходимо добавить RadioGroup с двумя вложенными RadioButton, подписанными как «Внесение документа» и «Просмотр документа».

Визуальные компоненты в Android называются представлениями (view), и их базовым классом является android.view.View. Роль данной операции заключается в предоставлении пользователю выбора между режимами работы: внесением нового документа и просмотром существующего. Возможность выбора может быть реализована при помощи переключателя, который в Android представлен компонентом RadioButton. Несколько переключателей, из которых может быть выбран один, должны быть помещены в представление RadioGroup. Таким образом, на макет необходимо добавить RadioGroup с двумя вложенными RadioButton, подписанными как «Внесение документа» и «Просмотр документа».

В случае выбора пункта «Внесение документа», пользователь также должен указать тип документа. Это может быть реализовано в рамках той же операции. Для этого на макет добавлен еще один RadioGroup с двумя опциями - «Паспорт» и «Страховое свидетельство». Изначально переключатель выбора типа документа должен быть скрыт и отображаться только при выборе режима «Внесение документа».

Последним представлением на данном макете будет кнопка «Продолжить». Она также должна быть скрыта по умолчанию и отображаться только при выбранной операции и при необходимости типа документа. Листинг макета представлен в приложении 3.

За обработку событий взаимодействия с операцией отвечает класс OperationActivity. Соответственно, в нем будет реализовано три метода: для события выбора опций из двух групп и для события нажатия на кнопку продолжения. Листинг операции представлен в приложении 9.

Метод обработки событий выбора режима управляет видимостью переключателей выбора типа документа и кнопки «Продолжить».

Метод обработки событий выбора типа документа управляет только видимостью кнопки «Продолжить».

Метод, вызываемый при нажатии кнопки продолжения вызывает одну из двух операций в зависимости от выбора пользователя. Запускаемая операция описывается при помощи намерения (intent), в котором указывается требуемая операция. Также в намерение могут быть помещены дополнительные данные (extras) для использования в вызываемой операции. В данном случае при выборе режима внесения нового документа будут добавлены дополнительные данные, содержащие тип документа. Операция будет запущена только в случае наличия разрешения на использование камеры. Для этого в файл манифеста AndroidManifest.xml необходимо добавить соответствующее разрешение (android.permission.CAMERA). Листинг файла AndroidManifest.xml представлен в приложении 1.

4.3 Операция распознавания

Большая часть логики приложения будет реализована в операции RecognitionActivity. Именно эта операция отвечает за получение изображения документа с камеры и распознавания данных. Прежде чем реализовать логику взаимодействия с камерой и с библиотеками OpenCV и Tesseract, необходимо подключить к проекту необходимые библиотеки в конфигурации Gradle (система автоматической сборки, используемая в проектах для Android). Для этого в секцию dependencies файла build.gradle в модуле app необходимо добавить следующие зависимости (листинг файла build.gradle приведен в приложении 23):

compile group: 'org.bytedeco', name: 'javacv', version: '1.3.2'

compile group: 'org.bytedeco.javacpp-presets', name: 'opencv', version: '3.2.0-1.3', classifier: 'android-arm'

compile group: 'org.bytedeco.javacpp-presets', name: 'ffmpeg', version: '3.2.1-1.3', classifier: 'android-arm'

compile group: 'org.bytedeco.javacpp-presets', name: 'tesseract', version: '3.04.01-1.3'

compile group: 'org.bytedeco.javacpp-presets', name: 'tesseract', version: '3.04.01-1.3', classifier: 'android-arm'

compile group: 'org.bytedeco.javacpp-presets', name: 'leptonica', version: '1.73-1.3', classifier: 'android-arm'

Библиотека org.bytedeco.javacv содержит утилитные классы, а также зависимости от org.bytedeco.javacpp, содержащей основные типы, применяемые при взаимодействии с нативным C++-кодом (например, класс BytePointer - представление указателя на тип char) и от предустановленных в JavaCPP библиотек, в том числе OpenCV.

Библиотека org.bytedeco.javacpp-presets.opencv и остальные в приведенном списке, имеющие классификатор android-arm содержат непосредственно C++-библиотеки, скомпилированные для процессоров с архитектурой ARM.

После подключения библиотек можно приступить к реализации операции распознавания данных документа. Для этого в первую очередь необходимо реализовать получение изображения с камеры. В репозитории примеров команды Bytedeco имеется проект javacv-android-camera-preview [12] с представлением CvCameraPreview - окном предпросмотра с возможностью обработки изображения, оперируя объектом класса opencv_core.Mat (Mat - центральный класс в библиотеке OpenCV. Он является контейнером для изображения и состоит из двух частей: заголовка матрицы и указателя на матрицу, содержащую значения пикселей [13]). Все что нужно - это реализовать интерфейс CvCameraPreview.CvCameraViewListener.

Таким образом, на макете операции RecognitionActivity необходимо расположить представление CvCameraPreview, и установить ему атрибуты app:camera_type="back" для выбора задней камеры и app:scale_type="fit" для того, чтобы изображение предпросмотра полностью вмещалось в окно. Листинг макета представлен в приложении 4, а операции - в приложении 12.

Всю логику обработки, обнаружения и распознавания можно вынести в отдельные сервисные классы. Общий для всех типов документов функционал будет расположен в базовом абстрактном классе BaseDocRecognitionService, в то время как подклассы будут реализовать функционал специфичный для документа. В базовом классе достаточно единственного публичного метода - processPreview(), который принимает параметром изображение с камеры и возвращает изображение для показа в окне предпросмотра. Стоит отметить, что разрешение исходного изображения ограничено 640 пикселями в обоих измерениях для сохранения приемлемой скорости отрисовки кадров в связи с высокой сложностью алгоритма. Как было сказано в разделе 3, операция получения изображения предпросмотра должна состоять из обнаружения полей документа и выделении их на изображении предпросмотра, следовательно, можно выделить два соответствующих метода - detect() и drawFields(). Листинг класса BaseDocRecognitionService представлен в приложении 13, реализаций PassportRecognitionService и SnilsRecognitionService - в приложениях 14 и 15 соответственно. Тип документа устанавливается перечислением DocumentType, листинг которого приведен в приложении 22.

4.3.1 Описание алгоритма метода обнаружения полей

Поскольку документы имеют разный размер и соотношение сторон, логично перед дальнейшей работой с изображением обрезать его до требуемого размера. Для этого объявим абстрактный метод getRatio(), который будет возвращать величину соотношения сторон для конкретного типа документа - например, 88/125 для паспорта [14]. Размер изображения документа в пикселях рассчитывается в конструкторе на основе этого соотношения и разрешения изображения предпросмотра. Затем исходное изображение обрезается под требуемый формат используя метод Mat.apply(). Метод apply() создает новый объект Mat с указателем на часть исходной матрицы. После этого над обрезанным изображением производятся следующие операции:

1. Конвертация изображения из цветового пространства RGBA в оттенки серого.

Для этой операции применяется метод opencv_imgproc.cvtColor, принимающий 3 параметра: исходное изображение, преобразованное изображение и код конвертации, определяющий цветовые пространства входного и выходного изображений. Второй параметр может принимать ссылку на тот же объект, что и передается в качестве входного изображения. В таком случае на уровне C++ все равно будет создана новая матрица и данные исходного изображения не будут затронуты. В качестве кода операции в данном случае используется CV_RGBA2GRAY.

2. Выделение границ

Эту задачу выполняют реализации абстрактного метода BaseDocRecognitionService.findEdges(). В реализациях для обоих типов документов вызывается единственный метод - opencv_imgproc.Canny() (оператор Кэнни). Он принимает в качестве параметров ссылки на исходное изображение, выходное бинарное изображение с выделенными границами, величину нижнего порога, величину верхнего порога, размер матрицы свертки для оператора Собеля и признак, указывающий на то, должна ли быть использована более точная формула расчета градиента вместо . Величины нижнего, верхнего порога и размера матрицы свертки зависят от цветов фона и шрифта документа. Они подобраны опытным путем, учитывая рекомендацию Кэнни по отношению величины верхнего порога к нижнему находящемуся в пределах (2; 3), и принимают следующие значения:

800, 2000, 5 - для паспорта;

100, 250, 3 - для страхового свидетельства.

Стоит отметить, что при увеличении размера матрицы свертки, величины порогов также должны быть увеличены.

3. Применение к изображению морфологических операций

Морфологические операции выполняются в методе BaseDocRecognitionService.applyMorphology(). Реализация этого метода в сервисе для паспорта следующая:

Изображение разбивается на левую и правую части, таким образом, чтобы в левой части находился текст, расположенный горизонтально, а в правой - вертикально, то есть серия и номер паспорта. К левой и правой частям изображения применяется операция замыкания с целью объединения символов и слов в единые блоки белого цвета (значения пикселей - 255). В левой части части матрица свертки имеет больший размер по горизонтали, в то время как в правой - по вертикали. Размер матрицы свертки, а также интервалы столбцов для частей изображения с горизонтальным и вертикальным текстом устанавливаются в конструкторе, чтобы снизить затраты процессорного времени. После операции замыкания, к изображению применяется операция размыкания. Ее роль заключается в том, чтобы убрать с изображения шумы и отсеять текст с мелким шрифтом.

Используемые в этом методе переменные рассчитываются в конструкторе следующим образом:

В сервисе для страхового свидетельства, SnilsRecognitionService, код метода applyMorphology() аналогичен описанному выше, за исключением того, что здесь нет необходимости в применении операции замыкания с разными матрицами свертки к разным частям изображения, поскольку весь текст в страховом свидетельстве расположен горизонтально.

4. Выделение полей документа

Этот метод, BaseDocRecognitionService.detectFields(), реализован в базовом классе. На вход он принимает бинарное изображение с выделенными белым цветом блоками текста.

В первую очередь находятся контуры блоков текста. Для этого применяется метод opencv_imgproc.findContours(input, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE), где input - входное бинарное изображение, contours - найденные контуры, RETR_EXTERNAL - режим поиска контуров, при котором находятся только внешние контуры, а внутренние, находящиеся во внешних, игнорируются, CHAIN_APPROX_NONE - аппроксимация контуров отключена, каждому пикселю соответствует одна точка контура.

Затем для каждого найденного контура выполняется: аппроксимация контура при помощи метода approxPolyDP(), в числе аргументов которого следует отметить epsilon, как величину характеризующую точность аппроксимации и равную максимальной дистанции между исходным и результирующим контуром, и closed, как признак того, нужно ли замыкать крайние точки контура. В нашем случае epsilon можно принять равным 3, а closed = true.

Следующим шагом полученные контуры вписываются в прямоугольники методом opencv_imgproc.boundingRect(). Полученные прямоугольники увеличиваются в размерах на 3 пикселя в каждом направлении, чтобы скомпенсировать возможную ошибку при выполнении предыдущих этапов. Далее этим прямоугольникам ставятся в соответствие поля документа. Эту функцию выполняет метод getFieldCorrespondingTo. Его описание будет приведено позднее.

Для поля документа необходимо создать интерфейс DocumentField с двумя методами: getName(), возвращающим название поля и getRelativeSearchingArea(), возвращающим область, в которой может находиться это поле в долях от ширины и высоты документа. Листинг интерфейса DocumentField приведен в приложении 16. Данный интерфейс будет реализован перечислениями PassportField и SnilsField. Их листинги приведены в приложениях 17 и 18 соответственно. В базовом классе имеется поле fieldsSearchingAreas() типа Map<DocumentField, Rect> - ассоциативный массив, ключом которого является поле документа, а значением - прямоугольник, в пределах которого это поле может располагаться на изображении. Этот массив инициализируется в конструкторе класса через вызов метода calculateSearchingAreas(), который преобразует относительные координаты областей поиска полей в абсолютные координаты, соответствующему конкретному разрешению изображения предпросмотра. Метод getFieldCorrespondingTo() принимает в качестве параметра прямоугольник с распознанным текстом и проходя по записям в ассоциативном массиве находит поле, которому принадлежит этот прямоугольник

Наконец, поле DocumentField и соответствующий ему прямоугольник Rect добавляются в Multimap - ассоциативный массив, допускающий соответствие одному ключу нескольких значений. Мультиотображение необходимо, потому что одно поле может содержать несколько строк текста, а при обнаружении одной строке текста соответствует один прямоугольник. Multimap и его реализации, такие как ArrayListMultimap, присутствуют в библиотеке Google Guava. Чтобы подключить эту библиотеку в файл build.gradle необходимо добавить зависимость:

compile 'com.google.guava:guava:22.0-android'

На этом обнаружение текста завершено. Но прежде чем отображать изображение предпросмотра с нанесенными на нем прямоугольниками, описывающими текст, необходимо проверить, не были ли обнаружены все поля, и, если это так, перейти к распознаванию текста. Проверка осуществляется в методе isAllFieldsFound следующим образом:

fields.containsAll(getAllFields());

Где getAllFields() - абстрактный метод, возвращающий список всех полей для данного типа документа.

4.3.2 Отрисовка прямоугольников для предпросмотра

В случае если не все необходимые поля были обнаружены, нужно визуализировать на исходном изображении прямоугольники с распознанными полями, а также прямоугольники, в которых производится поиск этих полей. Для этого создан метод visualizeRects(), выполняющий обрезку исходного изображения до размеров документа, рассчитанных в конструкторе класса, отрисовку на изображении найденных на прошлом шаге прямоугольников и прямоугольников, в которых должны располагаться соответствующие поля, и восстановление изображения до исходного размера с заполнением краев белым цветом. Эти действия вынесены в отдельные методы, из алгоритмов которых стоит отдельно выделить операции opencv_imgproc.rectangle(), служащую непосредственно для отрисовки на изображении прямоугольника определенного цвета и Mat.copyTo(), копирующую одну матрицу (изображение) в другую. В данном случае производится копирование обрезанного изображения в центральную часть полноразмерного изображения. Эта операция является заключительной в процессе обнаружения полей.

4.3.3 Интеграция операции RecognitionActivity с сервисом PassportRecognitionService

Как было упомянуто ранее, для осуществления взаимодействия с представление CvCameraPreview необходимо реализовать интерфейс слушателя CvCameraViewListener. Он содержит 3 метода: onCameraViewStarted(), вызываемый, при запуске предпросмотра, onCameraViewStopped() - при его остановке и onCameraFrame() - при получении очередного кадра. Наибольший интерес представляют методы onCameraViewStarted() и onCameraFrame().

В методе onCameraViewStarted() можно произвести инициализацию сервиса распознавания. Конструктор сервиса распознавания должен принимать следующие аргументы:

· ширину и высоту изображения предпросмотра - на их основе будут вычислены такие величины, как абсолютные координаты областей поиска полей, размеры обрезанного под документ изображения, размеры матриц сверток, используемых в морфологических и других операциях;

· контекст текущей операции (объект android.content.Context) - нужен для запуска следующей операции;

· объект android.hardware.Camera - он необходим для захвата фото в полном разрешении для последующего распознавания текста;

· объект tesseract.TessBaseAPI - API для распознавания текста, подробнее будет описано далее.

Контекст операции можно получить при помощи ключевого слова this, поскольку каждая операция (Activity) является наследником Context. Ширина и высота изображения поступают в метод onCameraViewStarted() в качестве параметров.

Для захвата полноразмерного снимка должен использоваться тот же объект Camera, который используется для получения изображений предпросмотра. Он инициализируется в классе CvCameraPreview, однако не передается в onCameraViewStarted в качестве аргумента, поэтому необходимо модифицировать CvCameraPreview и интерфейс CvCameraViewListener, добавив третий параметр - Camera.

Для работы Tesseract необходимы обученные данные для определенного шрифта и языка - файл с расширением traineddata. Обучение Tesseract используемым в документах шрифтам будет описано в пункте 4.7. Полученный после обучения файл (в данном случае rus.traineddata) необходимо встроить в приложение. ОС Android не предоставляет возможности обращения к файлам, встроенным в пакет приложения (APK), с использованием абсолютных путей, что необходимо для API библиотеки Tesseract. Поэтому файл с обученными данными можно скопировать из пакета приложения, например, в директорию кэша приложения. Копирование этого файла, если он отсутствует в директории кэша, а также инициализация API при помощи метода TessBaseAPI.Init() производятся при старте операции RecognitionActivity в методе initTesseract().

Таким образом, получены все необходимые для инстанцирования сервиса распознавания аргументы. В зависимости от типа документа, полученного ранее через дополнительные данные в намерении, в методе onCameraViewStarted() создается либо экземпляр класса PassportRecognitionService, либо SnilsRecognitionService. В методе onCameraFrame() достаточно вызывать processPreview() этого сервиса - обработанное этим методом изображение будет возвращено в CvCameraPreview для отрисовки на окне предпросмотра.

4.3.4 Распознавание

Распознавание текста полей также будет реализовано в BaseDocRecognitionService. Положительный результат проверки isAllFieldsFound() говорит о том, что можно приступить к распознаванию текста в полях. Эту роль выполняет метод takeFullSizePicture(). В нем происходит асинхронный захват полноразмерного изображения с камеры при помощи takePicture() того же экземпляра Camera, который используется для предпросмотра. Поскольку захват выполняется асинхронно, методу takePicture() в параметре jpeg необходимо сообщить реализацию интерфейса обратного вызова PictureCallback. Метод onPictureTaken() этого интерфейса будет вызван после полной обработки изображения и принимает на вход два параметра - массив байт, содержащий изображение и объект Camera, который был использован для захвата изображения.

1. Фильтрация

Прежде чем приступать к распознаванию, снятое изображение необходимо перевернуть и сконвертировать в цветовое пространство RGBA. Для этого могут быть применены фильтры FFmpeg, поскольку они также применяются в CvCameraPreview для фильтрации изображения предпросмотра. Алгоритм фильтрации можно вынести в метод filterFrame(), который примет на вход изображение в виде типа byte[], ширину и высоту исходного изображения.

Сперва нужно создать объект Frame - основной объект в FFmpeg, соответствующий одному кадру, и поместить в этот объект изображение (массив байт). После этого необходимо настроить фильтры. В данном случае - поворот изображения и конвертацию в цветовое пространство RGBA. Для этого предусмотрены фильтры transpose и format. Параметр dir фильтра transpose указывает направление поворота. Изображение необходимо повернуть на 90 градусов по часовой стрелке, и этому соответствует dir=1. Формат выходного изображения указывается в параметре pix_fmts фильтра format и для RGBA равен, соответственно, rgba. Фильтры указываются в строке через запятую.

Таким образом, строка фильтров будет выглядеть так:

transpose=1,format=pix_fmts=rgba

После настройки необходимо обработать изображение этими фильтрами. Для этого сначала фильтр запускается вызовом FFmpegFrameFilter.start, затем исходный кадр помещается в очередь обработки при помощи FFmpegFrameFilter.push, обработанный кадр вытаскивается из очереди методом FFmpegFrameFilter.pull и фильтр останавливается вызовом FFmpegFrameFilter.stop.

Обработанный фильтрами кадр должен быть преобразован к формату Mat для использования в OpenCV. Для конвертации между Frame и Mat в JavaCV существует утилитный класс OpenCVFrameConverter.ToMat, а именно - метод convert этого класса. Данному методу передается кадр и на выходе получается изображение в виде Mat.

2. Повторное обнаружение

Между получением очередного изображения предпросмотра и захватом полноразмерного изображения проходит некоторое время, за которое положение камеры относительно документа могло измениться, хоть и не на много. Этого смещения достаточно для того, чтобы обнаруженные прямоугольники с текстом не соответствовали реальному расположению текста на снятом изображении. В связи с этим, необходимо произвести повторное обнаружение полей. Для этого изображение сначала уменьшается до размеров изображения предпросмотра, чтобы снизить затраты процессорного времени на обнаружение, при помощи метода opencv_imgproc.resize(). Используемый алгоритм интерполяции - INTER_AREA. Он рекомендуется при уменьшении разрешения изображения, поскольку дает результат без муарового узора [15]. После изменения уменьшения, изображение вновь передается в метод detect() для обнаружения полей.

Распознавание

После обнаружения полей выполняется заключительная часть - непосредственно распознавание. Она выделена в абстрактный метод recognize(), принимающий на вход полноразмерное изображение и мультиотображение DocumentField -> Rect, то есть поля с соответствующими им прямоугольниками на изображении.

Реализации этого метода для PassportRecognitionService и SnilsRecognitionsService практически идентичны, за тем исключением, что часть изображения с серией и номером паспорта перед передачей в Tesseract необходимо повернуть на 90 градусов, поэтому достаточно рассмотреть пример реализации для паспорта.

Во-первых, изображение необходимо преобразовать в оттенки серого уже упоминавшейся операцией cvtColor(). После чего последовательно проходя записи в мультиотображении:

· Прямоугольник масштабируется под полноразмерное изображение. Это необходимо поскольку обнаружение полей производилось по уменьшенному изображению.

· Часть изображения, находящаяся в этом прямоугольнике, копируется в новый объект Mat, чтобы избежать повреждения полного изображения.

· В случае, если текущее поле - серия и номер паспорта, вырезанное изображение переворачивается на 90 градусов против часовой стрелки. Для этого последовательно выполняются операции транспонирования матрицы и отражения ее относительно оси X.

· Адаптивная пороговая бинаризация. В отличие от простой пороговой бинаризации этот алгоритм рассчитывает порог для небольшой области изображения, что дает разные пороги для разных частей изображения и лучшие результаты при непостоянном освещении [16]. Используемый алгоритм расчета порога - ADAPTIVE_THRESH_MEAN_C, порог рассчитывается как среднее значение из значений соседних пикселей. На выходе получается бинарное изображение с черным текстом на белом фоне.

· Операция замыкания отсеивает шумы.

· Полученное изображение передается для распознавания в Tesseract через метод TessBaseAPI.TesseractRect() и результат распознавания помещается в результирующее отображение DocumentField -> String. В случае если для этого поля уже была распознана некоторая строка (в случае многострочных полей), полученная на этом шаге строка добавляется к существующей.

На этом распознавание текста закончено и можно перейти к операции верификации распознанных данных. Ассоциативный массив полей документа с их значениями необходимо поместить в дополнительные данные намерения. Все поля с их значениями можно сгруппировать в объект Bundle и поместить его в намерение под ключом documentFields. Так же в намерение необходимо поместить тип документа - от него будут зависеть поля, отображаемые на форме верификации.

4.4 Корректировка и подтверждение распознанных данных

После распознавания данных запускается операция DocumentActivity. Ее макет activity_document.xml должен содержать список полей с их значениями и возможностью корректировки. Набор полей зависит от типа документа. Для возможности прокрутки формы с полями предназначено представление ScrollView. Соответственно на макете можно разместить два таких представления, из которых отображаться будет только одно, в зависимости от типа документа. Листинг операции DocumentActivity представлен в приложении 16, макета activity_document - в приложении 5.

ScrollView подразумевает, что в нем будет расположен единственный дочерний элемент, уже в котором будет находиться содержимое для прокрутки. Очевидно, для группировки нескольких произвольных элементов следует использовать макет, поэтому поместим в ScrollView макет типа ConstraintLayout как наиболее гибкий и удобный в использовании. На этом макете следует расположить представления EditText и дать им уникальные идентификаторы для последующего заполнения этих полей распознанным текстом. Кроме того, каждый EditText необходимо снабдить компонентом TextView с подписью для поля. Аналогичным образом создается второе представление ScrollView и обоим представлениям устанавливается атрибут android:visibility=”gone” для их скрытия по умолчанию.


Подобные документы

  • Основы безопасности персональных данных. Классификация угроз информационной безопасности персональных данных, характеристика их источников. Базы персональных данных. Контроль и управление доступом. Разработка мер защиты персональных данных в банке.

    дипломная работа [3,2 M], добавлен 23.03.2018

  • Законодательные основы защиты персональных данных. Классификация угроз информационной безопасности. База персональных данных. Устройство и угрозы ЛВС предприятия. Основные программные и аппаратные средства защиты ПЭВМ. Базовая политика безопасности.

    дипломная работа [2,5 M], добавлен 10.06.2011

  • Понятие информационной и автоматизированной системы. Жизненный цикл базы данных: этап начальной разработки, проектирование, реализация и загрузка, тестирование и оценка, функционирование. Структурный анализ и проектирование, средства моделирования.

    лекция [216,9 K], добавлен 07.12.2013

  • Сущности и функциональные зависимости базы данных. Атрибуты и связи. Таблицы базы данных. Построение ER-диаграммы. Организация ввода и корректировки данных. Реляционная схема базы данных. Реализация запросов, получение отчетов. Защита базы данных.

    курсовая работа [2,4 M], добавлен 06.02.2016

  • Реализация приложения "Книжный магазин" средствами систем управления базами данных. Проектирование структуры базы данных, определение сущности и атрибутов. Логическое проектирование базы данных и реализация базы данных в СУБД Microsoft Office Access.

    курсовая работа [7,8 M], добавлен 13.02.2023

  • Технологии защиты персональных данных и их применение. Юридический аспект защиты персональных данных в России. Описание результатов опроса среди рядовых российских пользователей. Прогноз развития технологий в связи с аспектом защиты персональных данных.

    дипломная работа [149,6 K], добавлен 03.07.2017

  • Проектирование базы данных для автоматизированной системы "Склад". Разработка концептуальной модели (ER-диаграмма). Преобразование в реляционную модель и ее нормализация. Разработка запросов к базе данных на языке SQL. Скрипт для создания базы данных.

    курсовая работа [161,8 K], добавлен 07.10.2013

  • Понятие базы данных, модели данных. Классификация баз данных. Системы управления базами данных. Этапы, подходы к проектированию базы данных. Разработка базы данных, которая позволит автоматизировать ведение документации, необходимой для деятельности ДЮСШ.

    курсовая работа [1,7 M], добавлен 04.06.2015

  • Концептуальное и инфологическое проектирование базы данных в системе управления базами данных Microsoft Access. Физическое проектирование базы данных "Магазин спорттоваров". Тестирование и отладка базы данных, составление руководства пользователя.

    курсовая работа [6,7 M], добавлен 22.11.2022

  • Характеристика основных этапов создания программной системы. Сведения, хранимые в базе данных информационной системы музея. Описание данных, их типов и ограничений. Проектирование базы данных методом нормальных форм. Технические и программные средства.

    курсовая работа [1,8 M], добавлен 23.01.2014

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.