Программные средства для заполнения базы персональных данных
Исследование возможностей ускорения процессов заполнения базы персональных данных за счет сокращения ручного ввода данных путем применения технологий оптического распознавания символов. Проектирование, реализация и тестирование автоматизированной системы.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | дипломная работа |
Язык | русский |
Дата добавления | 10.07.2017 |
Размер файла | 2,6 M |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Так же в нижней части основного макета нужно разместить кнопку с подписью «Сохранить», выполняющую сохранение данных документа в БД приложения. Механизм сохранения будет описан позднее.
4.4.1 Заполнение полей формы данными
Заполнение текстовых полей выполняется при запуске Activity в методе onCreate(). Из дополнительных данных намерения получается тип документа и Bundle, содержащий значения полей этого документа. Затем в зависимости от типа документа атрибут android:visibility того или иного представления ScrollView устанавливается в значение VISIBLE.
В классе операции определены отображения полей документов (то есть элементов перечислений PassportField или SnilsField) на идентификаторы представлений EditText, который соответствуют этим полям. Это отображение используется при заполнении текстовых полей на форме конкретными значениями из Bundle-а, полученного в намерении. Так же для последующего сохранения в БД данные из объекта Bundle копируются в поле класса типа Map<DocumentField, String>.
4.4.2 Сохранение в БД
1. Создание БД
В ОС Android присутствует встроенный механизм хранения данных приложения в СУБД SQLite и API для работы с БД в пакете android.database.sqlite.
Сперва необходимо написать так называемый контрактный класс, который явно определит схему БД [17]. В контрактном классе следует разместить константы, определяющие URI, таблицы и столбцы. Для схемы БД данного проекта этот класс представлен в приложении 19.
После определения контрактного класса нужно реализовать методы создания и управления базой данных и таблицами. Android дает возможность удобного управления БД при помощи класса SQLiteOpenHelper. Чтобы его использовать, необходимо создать класс-наследник, в котором реализовать по крайней мере методы onCreate() и onUpgrade(). В методе onCreate() должны выполняться SQL-скрипты для инициализации БД, такие как создание таблиц и при необходимости их заполнение. В методе onUpgrade() должны быть описаны действия, выполняемые при увеличении версии схемы БД. Реализация данного класса DbHelper представлена в приложении 20.
Итак, при создании БД нужно создать 3 таблицы: DOCUMENT, DOCUMENT_TYPE и USER. Скрипты для создания этих таблиц разместятся в статичных final-полях класса. Метод onCreate() принимает параметром объект SQLiteDatabase - именно этому обеспечивает взаимодействие с БД. Таблицы можно создать, вызывая метод execSQL() этого объекта, передавая ему в качестве параметра SQL-скрипт.
Затем необходимо заполнить таблицу DOCUMENT_TYPE. Вставка строки в таблицу осуществляется путем передачи объекта ContentValues методу insert(). Сначала создается объект ContentValues, затем в него при помощи метода put() помещаются значения для отдельных полей. Например, для паспорта:
ContentValues docTypeValues = new ContentValues();
docTypeValues.put(COLUMN_NAME_CODE, VALUE_CODE_PASSPORT);
docTypeValues.put(COLUMN_NAME_NAME, VALUE_NAME_PASSPORT);
db.insert(DocRecognizerContract.DocumentType.TABLE_NAME, null, docTypeValues);
После этого вызывается метод SQLiteDatabase.insert(), которому первым аргументом передается имя таблицы, третьим - ContentValues, созданный ранее. Во втором параметре в данном случае нет необходимости и вместо него передается null.
Схема БД будет редактироваться только во время разработки приложения, поэтому в методе onUpgrade() нет необходимости делать миграцию данных. Все что выполняет этот метод - удаляет существующие таблицы и повторно вызывает метод onCreate().
2. Сохранение в БД
После нажатия кнопки сохранения используя экземпляр написанного ранее класса DbHelper создается подключение к БД с доступом на запись, используя метод DbHelper.getWritableDatabase(). Затем в зависимости от типа документа, необходимо прочитать из таблицы DOCUMENT_TYPE соответствующий типу документа ID. Этот идентификатор впоследствии будет вставлен в столбец DOCUMENT.DOCUMENT_TYPE_ID. Работа с записями производится через курсор, получаемый вызовом метода SQLiteDatabase.query(). В первом аргументе метода указывается название таблицы, во втором массив названий полей, которые должны быть выбраны, в третьем - условие выборки с символом “?” в местах, куда должны быть подставлены параметры, переданные в четвертом параметре.
Изначально курсор находится на позиции -1, для получения результата выборки, его необходимо передвинуть на первую запись с помощью метода Cursor.moveToFirst(). Теперь можно прочитать искомый ID - для этого вызывается метод Cursor.getLong(), который принимает в качестве параметра номер столбца. Поскольку в выборку попадает единственное поле _ID, методу getLong() необходимо передать аргумент 0. После того как работа с курсором закончена, его нужно закрыть методом Cursor.close().
Для преобразования Java-объектов в JSON-текст существует целый ряд библиотек. Из них можно выделить Google Gson, так как она свободно распространяемая, нашла широкое применение и, что немаловажно, поддерживает сериализацию отображений (Map). Чтобы подключить библиотеку Gson к проекту необходимо добавить в конфигурацию Gradle следующую зависимость:
compile 'com.google.code.gson:gson:2.8.0'
Чтобы использовать Gson, сначала нужно создать экземпляр класса Gson вызвав метод GsonBuilder.create(). Все что нужно для сериализации в строку отображения названий полей на их значения - вызвать метод Gson.toJson(), передав ему это отображение. Таким образом, отображение
“NUMBER” -> “19 08 000000”,
“ISSUED_BY” -> “Отделом УФМС России”,
“LAST_NAME” -> “Иванов”
преобразуется в:
{"NUMBER":"19 08 000000","ISSUED_BY":"Отделом УФМС России",
"LAST_NAME":"Иванов"}
Теперь необходимо сохранить этот документ в БД. Создается новый экземпляр класса ContentValues, в него помещаются значения столбцов DOC_TYPE_ID (был найден ранее), DATA (JSON-строка) и USER_ID (ID пользователя, механизм аутентификации будет реализован позднее) и новая запись вставляется в таблицу DOCUMENT. На этом сохранение в БД завершено и снова производится переход к операции выбора режима OperationActivity.
4.5 Механизм аутентификации
Каждому пользователю приложения соответствует уникальный идентификатор, хранящийся в таблице USER. Идентификатор, который принадлежит аутентифицированному в данный момент пользователю должен быть доступен в любой операции приложения, в частности - в операции верификации/просмотра данных документа и в операции отображения списка документов. Для этого необходимо каким-либо способом передать ID пользователя в эти операции. Одним из вариантов является проброс ID при помощи дополнительных данных намерений. Однако этот способ сильно запутывает код, поскольку перед каждым запуском другой операции идентификатор нужно поместить в намерение, а при старте каждой операции - брать его оттуда. Существует еще два подхода - использование паттерна «Синглтон» для хранения переменной или расширение класса Application и хранение переменной в нем [18]. Предпочтительным из этих подходов является второй, поскольку он естественен для приложения Android.
Таким образом, необходимо создать класс, наследующий Application - DocRecogApplication. Этот класс должен содержать поле userId типа Long, а также геттер и сеттер для этого поля. Чтобы приложение использовало этот класс, необходимо в файле AndroidManifest.xml элементу application добавить атрибут android:name=”.DocRecogApplication”. Листинг класс DocRecogApplication приведен в приложении 21.
Теперь нужно создать операцию аутентификации. Android Studio предлагает набор шаблонных операций, в числе которых операция аутентификации - LoginActivity. По умолчанию она просто проверяет введенные логин пароль на равенство жестко закодированным в операции строкам. Необходимо модифицировать этот класс таким образом, чтобы аутентификация производилась с использованием базы данных. Листинги макета и операции представлены в приложениях 2 и 8 соответственно.
Пароль должен храниться в виде хеш-суммы. Хеширование пароля будет осуществляться алгоритмом SHA-256. Реализация этого алгоритма есть в библиотеке Google Guava, которая уже подключена к проекту. Хеширование производится следующим образом:
String passwordHash = Hashing.sha256().hashUnencodedChars(password).toString();
После этого необходимо открыть подключение к базе данных и проверить наличие пользователя с соответствующим именем пользователя. В случае если пользователь найден, проверяется соответствие хеш-сумм паролей, и, если результат положительный, ID пользователя сохраняется в поле класса. В случае же, если пользователь не найден, необходимо его зарегистрировать - в таблицу USER вставляется запись с именем пользователя и хеш-суммой пароля и ID пользователя соответственно становится равным значению столбца _ID только что добавленной записи.
Взаимодействие с БД осуществляется асинхронно в отдельном потоке. По его завершении в основном UI-потоке выполняется метод onPostExecute(), в котором идентификатор пользователя устанавливается в DocRecogApplication и становится доступен остальным частям приложения, и запускается операция OperationActivity. В случае если пользователь был найден, но хеш-суммы паролей не совпали, рядом с текстовым полем ввода пароля выводится текст ошибки.
Теперь для получения в приложении идентификатора пользователя необходимо вызвать ((DocRecogApplication) getApplication()).getUserId().
4.6 Просмотр документов
В случае, если выбран режим «Просмотр существующего документа», должен быть отображен список внесенных пользователем документов, для чего необходимо создать новую операцию - DocListActivity. Список элементов может быть создан при помощи представления ListView. Список автоматически заполняется элементами при помощи адаптера (класс Adapter), который конвертирует данные из таких источников данных, как массивы или БД, в элементы списка. Листинг макета данной операции представлен в приложении 6. Листинг операции представлен в приложении 11.
Для данных, получаемых из курсора, существует реализация адаптера SimpleCursorAdapter. Для его использования необходимо указать макет, который будет использован для отображения каждой строки, и значения каких столбцов должны быть вставлены в какие представления этого макета. Поэтому, сперва необходимо создать макет строки - list_item.xml. Стоить заметить, что SimpleCursorAdapter может заполнять данными только компоненты TextView. На макете list_item.xml будет расположен единственное представление - TextView, в котором будет выводиться тип документа и его порядковый номер. Листинг list_item.xml находится в приложении 7.
В методе onCreate операции нужно открыть подключение к базе данных и создать курсор запроса на выборку доступных текущему пользователю документов. Для того, чтобы получить название типа документа, необходимо соединить таблицы DOCUMENT и DOCUMENT_TYPE оператором JOIN, однако стандартный метод SQLiteDatabase.query() не предоставляет такой возможности. Для построения произвольных запросов существует метод SQLiteDatabase.rawQuery(). В первом аргументе методу передается текст запроса с символами “?” на местах, куда должны быть подставлены значения, переданные в массиве во втором аргументе. Для применения в адаптере запрос также должен возвращать обязательный столбец _ID. Он же будет использован для нумерации документов. Запрос на выборку будет выглядеть следующим образом:
SELECT DOCUMENT._ID, DOCUMENT_TYPE.NAME || “ ” || DOCUMENT._ID AS DOC_NAME
FROM DOCUMENT
JOIN DOCUMENT_TYPE ON DOCUMENT.DOC_TYPE_ID = DOCUMENT_TYPE._ID
WHERE DOCUMENT.USER_ID = ?
На место “?” будет подставлен ID текущего пользователя. Далее необходимо создать адаптер, передав ему этот курсор, идентификатор макета строки list_item, наименование столбца, из которого будет получено значение для отображения на TextView (в данном случае DOC_NAME) и идентификатор TextView, в который данное значение будет установлено. После чего необходимо назначить этот адаптер списку методом ListView.setAdapter.
При нажатии на элемент списка, нужно открывать на чтение соответствующий документ. Для этого необходимо запустить операцию DocumentActivity, предварительно поместив в намерение идентификатор документа. Также необходимо модифицировать DocumentActivity таким образом, чтобы в случае если в намерении установлен ID документа, поля документа загружались из БД, TextView, в которых отображаются эти поля становились недоступными для редактирования, а кнопка сохранения - невидимой.
Загрузка документа из БД вынесена в метод loadDocument(). В нем сначала производится выборка столбцов DOCUMENT.DATA и DOCUMENT_TYPE.CODE для документа с требуемым ID. Затем производится десериализация JSON-объекта при помощи той же библиотеки Gson, а именно метода Gson.fromJson(). Кроме JSON-строки методу необходимо передать объект типа Type, определяющий тип десериализованного объекта. Чтобы получить объект Type, необходимо воспользоваться методом getType() класса TypeToken. Например, для того, чтобы на выходе получить отображение PassportField -> String, нужно создать тип следующим образом:
new TypeToken<Map<PassportField, String>>(){}.getType();
Удаление документов
Удаление существующего документа осуществляется после долгого нажатия на элемент списка ListView. Чтобы обработать событие долгого нажатия, при запуске операции просмотра списка документов необходимо реализовать интерфейс OnItemLongClickListener. В методе onItemLongClick этого интерфейса нужно вызвать метод SQLiteDatabase.delete(), передав ему в качестве аргументов название таблицы, из которой производится удаление, - DOCUMENT и условие, по которому будет произведено удаление (_ID = id). Список ListView после удаления элемента самостоятельно не обновится - для удаления необходимо обновить курсор адаптера списка.
На этом разработка приложения в части кодирования завершена.
4.7 Обучение Tesseract
Tesseract предлагает пакет инструментов для обучения. Первым действием при обучении должно быть генерирование изображений для обучения (в формате TIFF) и файлов с координатами прямоугольников (в формате BOX), в которых заключены символы на изображениях [19]. При наличии требуемого шрифта в формате TrueType, генерация TIFF и BOX-файлов может быть автоматизирована при помощи утилиты text2image, однако для печати текста в паспортах и страховых свидетельствах используются встроенные в принтеры Epson «матричные» шрифты, для которых не существует шрифтов в требуемом формате. Создание изображений и BOX-файлов в таком случае осуществляется вручную.
Подготовка TIFF и BOX-файлов
В качестве обучающих изображений могут быть использованы сканы или фотографии документов. Цветные изображения необходимо перевести в оттенки серого и затем в черно-белые, например, при помощи пороговой бинаризации, так, чтобы текст был черным на белом фоне. Полученное изображение желательно сохранить в формате TIFF. После этого должен быть создан BOX-файл с координатами символов. Для этого будет использована программа jTessBoxEditor. После запуска программы нужно переключиться на вкладку Box Editor и открыть изображение документа. Интерфейс программы изображен на рисунке 22.
Рисунок 22 - Интерфейс программы jTessBoxEditor
Далее необходимо каждый символ поместить в отдельный прямоугольник, добавив его кнопкой Insert на панели инструментов, и сопоставить с прямоугольником символ Юникода. После повторения этой операции для каждого символа необходимого шрифта на изображении, BOX-файл сохраняется нажатием кнопки Save.
Собрав достаточное количество обучающих данных (Tesseract рекомендует не менее 20 образцов для часто встречающихся символов и 5-10 - для редких) можно приступить к непосредственно обучению. Обучение также может быть выполнено в jTessBoxEditor - для этого следует переключиться на вкладку Trainer, в поле Training Data указать источник изображений с BOX-файлами, в поле Language ввести “rus” в поле выбора режима установить Train with Existing Box и запустить обучение нажатием кнопки Run. После обучения в указанной папке появится директория tessdata с файлом rus.traineddata - эту директорию необходимо поместить в папку assets проекта Android Studio. При запуске приложения на смартфоне этот файл будет скопирован из APK в папку кэша приложения.
4.8 Сборка приложения
Приложение готово к сборке. В связи с большим количеством библиотечных методов байт-код приложения должен располагаться в нескольких DEX-файлах. Для этого в конфигурации Gradle необходимо разрешить создание нескольких DEX-файлов, добавив строку “multiDexEnabled true” в секцию defaultConfig.
Затем нужно переключить вариант сборки с debug на release и собрать пакет, нажав “Build APK”. Перед тем как пакет сможет быть установлен на устройство, его необходимо подписать. Для этого сначала следует создать хранилище ключей и ключ, после чего подписать пакет приложения выбрав подписание целого пакета (V2). После этого в папке проекта будет создан пакет приложения app-release.apk, готовый к установке на устройство.
5. ТЕСТИРОВАНИЕ
5.1 Обоснование методики тестирования
С целью проверки соответствия системы исходным требованиям будет проведено ее системное тестирование. На основе вариантов использования приложения будут определены тестовые случаи.
Тест-кейс №1. Регистрация пользователя: имя пользователя короче 4-х симолов.
Шаги
1. Запустить приложение
2. Ввести имя пользователя «usr».
3. Ввести пароль «pswd»
4. Нажать на кнопку войти/зарегистрироваться
Ожидаемый результат
Появляется сообщение об ошибке «Имя пользователя слишком короткое»
Тест-кейс №2. Регистрация пользователя: пароль короче 4-х симолов.
Шаги
1. Запустить приложение
2. Ввести имя пользователя «user».
3. Ввести пароль «pwd»
4. Нажать на кнопку войти/зарегистрироваться
Ожидаемый результат
Появляется сообщение об ошибке «Пароль слишком короткий»
Тест-кейс №3. Регистрация пользователя: имя пользователя и пароль не менее 4-х символов.
Шаги
1. Запустить приложение
2. Ввести имя пользователя «user».
3. Ввести пароль «pswd»
4. Нажать на кнопку войти/зарегистрироваться
Ожидаемый результат
Регистрация успешна - происходит переход в операции выбора режима
Тест-кейс №4. Аутентификация пользователя с некорректным паролем.
Предварительные условия
Зарегистрирован пользователь «user» с паролем «pswd»
Шаги
1. Запустить приложение
2. Ввести имя пользователя «user».
3. Ввести пароль «password»
4. Нажать на кнопку войти/зарегистрироваться
Ожидаемый результат
Появляется сообщение об ошибке «Неверный пароль»
Тест-кейс №5. Аутентификация пользователя с корректным паролем.
Предварительные условия
Зарегистрирован пользователь «user» с паролем «pswd»
Шаги
1. Запустить приложение
2. Ввести имя пользователя «user».
3. Ввести пароль «pswd»
4. Нажать на кнопку войти/зарегистрироваться
Ожидаемый результат
Аутентификация успешна - происходит переход в операции выбора режима
Тест-кейс №6. Внесение документа типа паспорт при различных условиях освещенности и используемых устройствах.
Шаги
1. Запустить приложение
2. Ввести имя пользователя «user».
3. Ввести пароль «pswd»
4. Нажать на кнопку войти/зарегистрироваться
5. Выбрать опцию «Внесение документа», затем «Паспорт» и нажать на кнопку «Продолжить
6. Навести камеру устройства на документ, так чтобы поля документа совпали с прямоугольниками и дождаться распознавания
7. Сравнить результат распознавания с истинным текстом на документе при помощи инструмента String similarity test [20].
Ожидаемый результат
Требования к точности распознавания не определены.
Тест-кейс №7. Внесение документа типа страховое свидетельство при различных условиях освещенности и используемых устройствах.
Шаги
1. Запустить приложение
2. Ввести имя пользователя «user».
3. Ввести пароль «pswd»
4. Нажать на кнопку войти/зарегистрироваться
5. Выбрать опцию «Внесение документа», затем «Страховое свидетельство» и нажать на кнопку «Продолжить
6. Навести камеру устройства на документ, так чтобы поля документа совпали с прямоугольниками и дождаться распознавания
7. Сравнить результат распознавания с истинным текстом на документе при помощи инструмента String similarity test.
Ожидаемый результат
Требования к точности распознавания не определены.
Тест-кейс №8. Просмотр документа типа паспорт.
Предварительные условия
Для пользователя «user» с паролем «pswd» создан документ типа паспорт
Шаги
1. Запустить приложение
2. Ввести имя пользователя «user».
3. Ввести пароль «pswd»
4. Нажать на кнопку войти/зарегистрироваться
5. Выбрать опцию «Просмотр документа» и на кнопку «Продолжить»
6. Выбрать из списка документ
Ожидаемый результат
Отображается форма просмотра документа с заполненными полями «Серия и номер», «Кем выдан», «Дата выдачи», «Код подразделения», «Фамилия», «Имя», «Отчество», «Пол», «Дата рождения», «Место рождения». Поля заполнены такими же данными, какие были при сохранении.
Тест-кейс №9. Просмотр документа типа страховое свидетельство.
Предварительные условия
Для пользователя «user» с паролем «pswd» создан документ типа страховое свидетельство
Шаги
1. Запустить приложение
2. Ввести имя пользователя «user».
3. Ввести пароль «pswd»
4. Нажать на кнопку войти/зарегистрироваться
5. Выбрать опцию «Просмотр документа» и на кнопку «Продолжить»
6. Выбрать из списка документ
Ожидаемый результат
Отображается форма просмотра документа с заполненными полями «СНИЛС», «Фамилия», «Имя», «Отчество», «Дата рождения», «Место рождения», «Пол», «Дата выдачи». Поля заполнены такими же данными, какие были при сохранении.
Тест-кейс №10. Удаление документа.
Предварительные условия
Для пользователя «user» с паролем «pswd» создан документ любого типа
Шаги
1. Запустить приложение
2. Ввести имя пользователя «user».
3. Ввести пароль «pswd»
4. Нажать на кнопку войти/зарегистрироваться
5. Выбрать опцию «Просмотр документа» и на кнопку «Продолжить»
6. Осуществить долгое нажатие на документ в списке
Ожидаемый результат
Документ удален из списка
Также необходимо произвести тестирование производительности операции распознавания текста полей документа. Для этого необходимо программно замерить время между началом и окончанием операции распознавания. Текущее время в миллисекундах может быть получено при помощи метода System. currentTimeMillis().
Будет проведен эксперимент по сравнению среднего времени внесения данных документа при помощи разработанной системы и ручного ввод. Внесение документа кроме непосредственно ввода данных, включает в себя их верификацию и коррекцию.
5.2 Результаты тестирования
Результаты тестирования отражены в таблице 1.
Таблица 1 - результаты тестирования
№ п/п |
№ тест-кейса |
Дополнительные условия |
Результат |
|
1 |
1 |
пройден |
||
2 |
2 |
пройден |
||
3 |
3 |
пройден |
||
4 |
4 |
пройден |
||
5 |
5 |
пройден |
||
6 |
6 |
Естественное боковое освещение, Oneplus One |
точность - 92,97 % |
|
7 |
6 |
Естественное боковое освещение, Xiaomi Redmi 4X |
точность - 91,61 % |
|
8 |
6 |
Естественное боковое освещение, Xiaomi Mi4c |
точность - 90,95 % |
|
9 |
6 |
Искусственное локализованное освещение, Oneplus One |
точность - 97,83 % |
|
10 |
6 |
Искусственное локализованное освещение, Xiaomi Redmi 4X |
точность - 94,47 % |
|
11 |
6 |
Искусственное локализованное освещение, Xiaomi Mi4c |
точность - 93,22 % |
|
12 |
7 |
Естественное боковое освещение, Oneplus One |
точность - 92,31 % |
|
13 |
7 |
Естественное боковое освещение, Xiaomi Redmi 4X |
точность - 90,66 % |
|
14 |
7 |
Естественное боковое освещение, Xiaomi Mi4c |
точность - 90,44 % |
|
15 |
7 |
Искусственное локализованное освещение, Oneplus One |
точность - 97,98 % |
|
16 |
7 |
Искусственное локализованное освещение, Xiaomi Redmi 4X |
точность - 97,23 % |
|
17 |
7 |
Искусственное локализованное освещение, Xiaomi Mi4c |
точность - 94,21 % |
|
18 |
8 |
пройден |
||
19 |
9 |
пройден |
||
20 |
10 |
пройден |
Тестирование производительности показало, что среднее время распознавания данных паспорта составляет 832 мс, а среднее время распознавания данных страхового свидетельства - 581 мс, что удовлетворяет требованию к максимальному времени распознавания в 1 с.
Среднее время внесения данных при помощи оптического распознавания составило для паспорта 39,8 с, для страхового свидетельства - 23,4 с. Замер времени производился между запуском операции распознавания (RecognitionActivity) и нажатием на кнопку сохранения документа в БД.
Для оценки скорости внесения данных документов вручную была использована операция DocumentActivity с пустыми текстовыми полями. Время замерялось между началом ввода и нажатием кнопки «Сохранить» и в среднем составило: для паспорта - 1 мин 23,9 с, для страхового свидетельства - 1 мин 1 с.
Таким образом, для паспорта время автоматического ввода оказалось меньше, чем ручного, в раза, а для страхового свидетельства - в раза.
ЗАКЛЮЧЕНИЕ
В ходе выполнение выпускной квалификационной работы был проведен анализ существующих решений по распознаванию данных документов, удостоверяющих личность, изучены теоретические основы в области компьютерного зрения и алгоритмы обработки изображений и оптического распознавания символов.
Была спроектирована база данных для использования в приложении. Разработаны алгоритмы обнаружения и распознавания текста в документе, использующие преимущественно возможности библиотеки OpenCV. Спроектирован пользовательский интерфейс приложения на ОС Android.
Было разработано приложение в интегрированной среде разработки Android Studio. К приложению подключена локальная БД SQLite для сохранения данных распознанных документов. Реализован простой механизм аутентификации пользователя в системе. Также была обучена библиотека Tesseract для шрифтов, используемых в паспортах РФ и страховых свидетельствах.
В результате тестирования приложения ошибок в его работе не обнаружено. Точность распознавания зависит от условий освещенности и камеры устройства и в среднем составляет не менее 90%. Также стоит отметить, что интересующий текст на документах может быть плохо пропечатан или, например, сливаться с другими объектами, что тоже оказывает отрицательное влияние на точность распознавания. Время, затрачиваемое на распознавание, удовлетворяет техническому заданию. Использование технологий оптического распознавания дало прирост к скорости внесения данных документов более чем в 2 раза по сравнению с ручным вводом.
Приложение может использоваться на смартфонах с ОС Android 4.0 и выше, имеющих камеру с разрешением не менее 2 Мп с автофокусом, и не требует доступ к интернету.
СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ
1. Технологии перевода бумажных документов в электронные [Электронный ресурс] - Режим доступа: http://compress.ru/article.aspx?id=11802
2. Comparison of optical character recognition software [Электронный ресурс] - https://en.wikipedia.org/wiki/Comparison_of_optical_character_recognition_software
3. Improving the quality of the output [Электронный ресурс] - https://github.com/tesseract-ocr/tesseract/wiki/ImproveQuality
4. Компьютерное зрение [Электронный ресурс] - Режим доступа: ru.wikipedia.org/wiki/Компьютерное_зрение
5. Выделение границ [Электронный ресурс] - Режим доступа: ru.wikipedia.org/wiki/Выделение_границ
6. Оператор Кэнни [Электронный ресурс] - Режим доступа: ru.wikipedia.org/wiki/Оператор_Кэнни
7. Математическая морфология [Электронный ресурс] - Режим доступа: ru.wikipedia.org/wiki/Математическая_морфология
8. Операции [Электронный ресурс] - Режим доступа: https://developer.android.com/guide/components/activities.html?hl=ru
9. Макеты [Электронный ресурс] - Режим доступа: https://developer.android.com/guide/topics/ui/declaring-layout.html?hl=ru
10. jTessBoxEditor [Электронный ресурс] - Режим доступа: http://vietocr.sourceforge.net/training.html
11. Dashboards [Электронный ресурс] - Режим доступа: https://developer.android.com/about/dashboards/index.html
12. Bytedeco javacv-android-camera-preview [Электронный ресурс] - Режим доступа: https://github.com/bytedeco/sample-projects/tree/master/javacv-android-camera-preview
13. Mat - The Basic Image Container [Электронный ресурс] - Режим доступа: http://docs.opencv.org/3.2.0/d6/d6d/tutorial_mat_the_basic_image_container.html
14. Паспорт гражданина Российской Федерации [Электронный ресурс] - Режим доступа: https://ru.wikipedia.org/wiki/Паспорт_гражданина_Российской_Федерации
15. Geometric Image Transformations [Электронный ресурс] - Режим доступа: http://docs.opencv.org/3.2.0/da/d54/group__imgproc__transform.html#gga5bb5a1fea74ea38e1a5445ca803ff121acf959dca2480cc694ca016b81b442ceb
16. Image Thresholding [Электронный ресурс] - Режим доступа: http://docs.opencv.org/trunk/d7/d4d/tutorial_py_thresholding.html
17. Saving Data in SQL Databases [Электронный ресурс] - Режим доступа: https://developer.android.com/training/basics/data-storage/databases.html
18. Defining Global Variables in Android [Электронный ресурс] - Режим доступа: https://androidresearch.wordpress.com/2012/03/22/defining-global-variables-in-android/
19. Training Tesseract [Электронный ресурс] - Режим доступа: https://github.com/tesseract-ocr/tesseract/wiki/Training-Tesseract
20. String similarity test [Электронный ресурс] - Режим доступа: https://www.tools4noobs.com/online_tools/string_similarity
ПРИЛОЖЕНИЕ 1
(обязательное)
Листинг файла манифеста AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="demidov.docrecognition">
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<application
android:name=".DocRecogApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".RecognitionActivity"
android:screenOrientation="portrait"></activity>
<activity
android:name=".LoginActivity"
android:label="@string/title_activity_login">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".OperationActivity"
android:label="@string/title_activity_operation" />
<activity
android:name=".DocumentActivity"
android:label="@string/title_activity_document" />
<activity
android:name=".DocListActivity"
android:label="@string/title_activity_doclist" />
</application>
</manifest>
ПРИЛОЖЕНИЕ 2
(обязательное)
Листинг макета activity_login.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="demidov.docrecognition.LoginActivity">
<!-- Login progress -->
<ProgressBar
android:id="@+id/login_progress"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:visibility="gone" />
<ScrollView
android:id="@+id/login_form"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/username_login_form"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<AutoCompleteTextView
android:id="@+id/username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/prompt_username"
android:maxLines="1"
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/prompt_password"
android:imeActionId="@+id/login"
android:imeActionLabel="@string/action_sign_in_short"
android:imeOptions="actionUnspecified"
android:inputType="textPassword"
android:maxLines="1"
android:singleLine="true" />
</android.support.design.widget.TextInputLayout>
<Button
android:id="@+id/sign_in_button"
style="?android:textAppearanceSmall"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/action_sign_in"
android:textStyle="bold" />
</LinearLayout>
</ScrollView>
</LinearLayout>
ПРИЛОЖЕНИЕ 3
(обязательное)
Листинг макета activity_operation.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="demidov.docrecognition.OperationActivity">
<RadioGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="8dp"
android:id="@+id/operations">
<RadioButton
android:id="@+id/createDoc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/create_document"
android:onClick="selectOperation" />
<RadioButton
android:id="@+id/existingDoc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/view_existing_document"
android:onClick="selectOperation" />
</RadioGroup>
<RadioGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginTop="8dp"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@+id/operations"
app:layout_constraintLeft_toLeftOf="@+id/operations"
android:id="@+id/docTypes">
<RadioButton
android:id="@+id/passport"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="selectDocType"
android:text="@string/passport" />
<RadioButton
android:id="@+id/socialSecurity"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="selectDocType"
android:text="@string/social_security" />
</RadioGroup>
<Button
android:id="@+id/continueButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/continue_button"
android:visibility="invisible"
android:layout_marginTop="8dp"
app:layout_constraintTop_toBottomOf="@+id/docTypes"
android:layout_marginLeft="0dp"
app:layout_constraintLeft_toLeftOf="@+id/docTypes"
android:onClick="next" />
</android.support.constraint.ConstraintLayout>
ПРИЛОЖЕНИЕ 4
(обязательное)
Листинг макета activity_recognition.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black">
<Button
android:id="@+id/recorder_control"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_gravity="bottom"
android:layout_marginBottom="16dp"
android:text="record" />
<demidov.docrecognition.CvCameraPreview
android:id="@+id/camera_view"
android:layout_width="match_parent"
android:layout_height="417dp"
app:camera_type="back"
app:scale_type="fit" />
</FrameLayout>
ПРИЛОЖЕНИЕ 5
(обязательное)
Листинг макета activity_document.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="demidov.docrecognition.DocumentActivity">
<Button
android:id="@+id/saveButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:onClick="saveData"
android:text="@string/saveDocData"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" />
<ScrollView
android:id="@+id/passportVerification"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toTopOf="@+id/saveButton"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0">
<android.support.constraint.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="-163dp">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="@string/pass_number"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/passNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:ems="10"
android:inputType="text"
android:text=""
android:textSize="18sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<TextView
android:id="@+id/textView5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="@string/pass_issuer_name"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/passNumber" />
<EditText
android:id="@+id/passIssuerName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:ems="10"
android:inputType="text"
android:text=""
android:textSize="18sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView5" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="@string/pass_issuing_date"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/passIssuerName" />
<EditText
android:id="@+id/passIssuingDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:ems="10"
android:inputType="text"
android:text=""
android:textSize="18sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView3" />
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="@string/pass_issuer_code"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/passIssuingDate" />
<EditText
android:id="@+id/passIssuerCode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:ems="10"
android:inputType="text"
android:text=""
android:textSize="18sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView4" />
<TextView
android:id="@+id/textView6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="@string/last_name"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/passIssuerCode" />
<EditText
android:id="@+id/lastName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:ems="10"
android:inputType="text"
android:text=""
android:textSize="18sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView6" />
<TextView
android:id="@+id/textView7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="@string/first_name"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/lastName" />
<EditText
android:id="@+id/firstName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:ems="10"
android:inputType="text"
android:text=""
android:textSize="18sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView7" />
<TextView
android:id="@+id/textView8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="@string/middle_name"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/firstName" />
<EditText
android:id="@+id/middleName"
android:layout_width="216dp"
android:layout_height="43dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:ems="10"
android:inputType="text"
android:text=""
android:textSize="18sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView8"
tools:layout_editor_absoluteX="7dp" />
<TextView
android:id="@+id/textView9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="@string/gender"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/middleName" />
<EditText
android:id="@+id/gender"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:ems="10"
android:inputType="text"
android:text=""
android:textSize="18sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView9" />
<TextView
android:id="@+id/textView10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="@string/birth_date"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/gender" />
<EditText
android:id="@+id/birthDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:ems="10"
android:inputType="text"
android:text=""
android:textSize="18sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView10" />
<TextView
android:id="@+id/textView11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="@string/birth_place"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/birthDate" />
<EditText
android:id="@+id/birthPlace"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:ems="10"
android:inputType="text"
android:text=""
android:textSize="18sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView11" />
</android.support.constraint.ConstraintLayout>
</ScrollView>
<ScrollView
android:id="@+id/snilsVerification"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@+id/saveButton"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0">
<android.support.constraint.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="-163dp">
<TextView
android:id="@+id/textView12"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="@string/snils_number"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/snilsNumber"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:ems="10"
android:inputType="text"
android:text=""
android:textSize="18sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView12" />
<TextView
android:id="@+id/textView13"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="@string/last_name"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/snilsNumber" />
<EditText
android:id="@+id/snilsLastName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:ems="10"
android:inputType="text"
android:text=""
android:textSize="18sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView13" />
<TextView
android:id="@+id/textView14"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="@string/first_name"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/snilsLastName" />
<EditText
android:id="@+id/snilsFirstName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:ems="10"
android:inputType="text"
android:text=""
android:textSize="18sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView14" />
<TextView
android:id="@+id/textView15"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="@string/middle_name"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/snilsFirstName" />
<EditText
android:id="@+id/snilsMiddleName"
android:layout_width="216dp"
android:layout_height="43dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:ems="10"
android:inputType="text"
android:text=""
android:textSize="18sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView15"
tools:layout_editor_absoluteX="7dp" />
<TextView
android:id="@+id/textView16"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="@string/birth_date"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/snilsMiddleName" />
<EditText
android:id="@+id/snilsBirthDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:ems="10"
android:inputType="text"
android:text=""
android:textSize="18sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView16" />
<TextView
android:id="@+id/textView17"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="@string/birth_place"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/snilsBirthDate" />
<EditText
android:id="@+id/snilsBirthPlace"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:ems="10"
android:inputType="text"
android:text=""
android:textSize="18sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView17" />
<TextView
android:id="@+id/textView18"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="@string/gender"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/snilsBirthPlace" />
<EditText
android:id="@+id/snilsGender"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:ems="10"
android:inputType="text"
android:text=""
android:textSize="18sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView18" />
<TextView
android:id="@+id/textView19"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:text="@string/pass_issuing_date"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/snilsGender" />
<EditText
android:id="@+id/snilsIssuingDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:ems="10"
android:inputType="text"
android:text=""
android:textSize="18sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView19" />
</android.support.constraint.ConstraintLayout>
</ScrollView>
</android.support.constraint.ConstraintLayout>
ПРИЛОЖЕНИЕ 6
(обязательное)
Подобные документы
Основы безопасности персональных данных. Классификация угроз информационной безопасности персональных данных, характеристика их источников. Базы персональных данных. Контроль и управление доступом. Разработка мер защиты персональных данных в банке.
дипломная работа [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