Файл: Министерство науки и высшего образования российской федерации федеральное государственное автономное.pdf

ВУЗ: Не указан

Категория: Реферат

Дисциплина: Не указана

Добавлен: 06.12.2023

Просмотров: 37

Скачиваний: 2

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

12 способ предусматривает ограничение яркости пикселей в обработанном изображении максимальным и минимальным пороговыми уровнями, и имеет более широкое применение. Присутствие в изображении самых светлых и самых темных тонов создает впечатление хорошей контрастности.
Инструментом для оценки уровней интенсивности пикселей является гистограмма.
Максимальному значению интенсивности пикселей присваивается уровень градации интенсивности 255 (белый цвет), самому темному – значение 0 (черный цвет). Интенсивности в диапазоне от 0 до 255 имеют линейную шкалу изменения, либо устанавливаемую в соответствии с принятой функцией изменения, например, усиливающей слабые сигналы
(градации серого) и ослабляющей сильные сигналы (в области белого цвета), чем повышается пространственное и контрастное разрешение изображения или определенной зоны интереса. Известен метод улучшения изображений, основанный на вычислении логарифма спектральных коэффициентов преобразования Фурье исходного изображения [27].
7. Выравнивание страницы. Получение изображения документа с помощью цифровой камеры или планшетного сканера часто приводит к искажениям страниц. Деформация не только снижает читабельность документа, но и снижает точность распознавания текста. Для исправления деформации изображения документа был предложен метод восстановления изображений на основе сегментации искаженных документов. Этот метод повышает качество документов путем обнаружения и вырезания шумных черных границ. Сначала изображение сглаживается, затем вычисляются начальные и конечные смещения границ и текстовых областей. Черные границы удаляются с помощью связанных компонентов изображения [13].
Следующий подход удаления искажений документа заключается в непрерывном представлении скелетного изображения для удаления деформаций. Цель выравнивания страниц состоит в том, чтобы выровнять

13 документ, снятый камерой, таким образом, чтобы он стал читаемым современными системами распознавания текста [20].

1.2. Использование нейронных сетей для верификации статической
подписи
Рукописные подписи занимают особое место в большом наборе биометрических признаков. В основном это связано с тем, что рукописные подписи уже давно зарекомендовали себя как наиболее распространенное средство личной верификации. Подписи, как правило, признаются в качестве юридического средства проверки личности человека административными и финансовыми учреждениями [14]. По сравнению с другими биометрическими, физическими признаками, рукописная подпись является результатом сложного процесса, зависящего от психофизического состояния подписавшего и условий, в которых происходит процесс подписания документа. Изображения подписи имеют различия в толщине пера, штрихах, стиле написания, повороте, масштабе даже в пределе подлинных подписей одного человека. По этой причине искусные подделки в значительной степени напоминают подлинные подписи. Верификация подписи по-прежнему остается открытым вопросом, поскольку подпись считается подлинной или поддельной только на основе нескольких эталонных образцов [14].
Для реализации статического метода верификации используют различные подходы, например искусственные нейронные сети, скрытые марковские модели, различные виды метрик, метод опорных векторов, вычисление локальных экстремумов или вычисление матриц расстояний [24].
В настоящее время предпочтение все чаще отдается нейросетевому подходу.
Это можно объяснить тем, что применение данного развивающего подхода помогает верифицировать подпись более точно, нежели при использовании других. Нейронные сети эффективно строят нелинейные зависимости,

14 которые точнее описывают данные, они более устойчивы к шумам во входных данных и более адаптированы к их изменениям.
При верификации с помощью нейронных сетей можно условно выделить две стадии: обучение и валидация (рис. 1).
Рисунок 1. Алгоритм оффлайн-верификации подписи с применением нейронной сети
Обучение включает в себя извлечение изображения подписи из обучающей выборки, первичную обработку изображения, которая состоит из конвертации изображения в бинарное, его обрезки, нормализации размера и скелетизации, извлечении признаков, обучение сети на обработанных изображениях. Валидация включает в себя такие шаги как: извлечение подписи, подлинность которой необходимо определить, обработка изображения, извлечение признаков, подачу на вход обученной нейросети признаков, получение результата. На эффективность распознавания влияет

15 выбор типа нейронной сети. В данной области используются в основном многослойные искусственные нейронные сети прямого распространения с обратным распространением ошибки и сети радиальных базисных функций
[2]. Выбор признаков также является фактором, который влияет на процент ошибок первого и второго рода. Следовательно, важной задачей, помимо выбора архитектуры нейронной сети, является выбор признаков, извлекаемых из изображения. Их можно разделить на две основные группы глобальные и локальные. Глобальные признаки отражают всю структуру подписи и извлекаются из всего изображения (например, центр масс, вертикальная и горизонтальная проекции, отношение ширины к высоте подписи, область изображения). Локальные признаки извлекаются из каждой части изображения путем его сегментирования, поэтому они сильно различаются даже для одного и того же человека.
При решении задач в области компьютерного зрения, распознавания речи, детектирования объектов на изображении, проверка документов, распознавание рукописных чеков, обнаружение лиц на фотографиях, которые включающих измерение сходства между двумя или более объектами, используют сиамскую нейронную сеть. Это один из простейших и наиболее популярных алгоритмов однократного обучения. Сиамская нейронная сеть – разновидность искусственной нейронной сети, состоящая из двух одинаковых нейронных подсетей с равными набором весов. Это тип архитектуры нейронной сети принимает два входа и выводит метрику расстояний для входных данных. Сиамские нейронные сети часто используется, когда число классов велико, а количество объектов в классах мало. Сиамская нейронная сеть представляет нелинейное отображение данных с целью приблизить к друг другу схожие объекты и отдалить различающиеся объекты на максимально возможное расстояние [18]. Сеть получила свое название из-за использования нескольких подсетей, разделяющих один набор весов. Подсети могут быть

16 представлены сверточными нейронными сетями, в которых выходы промежуточных слоев образуют матрицу либо набор матриц.
Сверточные сети используют операцию свертки вместо умножения матриц, хотя бы в одном из своих слоев. Основными видами слоев в сверточной нейронной сети являются сверточные слои, слои объединения и полносвязные слои. Сверточный слой нейронной сети представляет операцию свертки к выходам предыдущего слоя. Слой объединения, снижает размерность изображения. Исходное изображение делится на блоки и для каждого вычисляется функция максимума или взвешенного среднего. Слой объединения необходим для уменьшения изображения для последующей свертки, ускорения вычисления и увеличению инвариантности выхода сети по отношению к малому переносу входа [28]. Полносвязные слои соединяют каждый нейрон в одном слое с каждым нейроном в другом слое. Матрица проходит через полносвязный слой для классификации изображения.
Важной составляющей нейросети является функция активации, определяющая выходное значение нейрона в зависимости от результатов взвешенной суммы входов и порогового значения. Вид функции активации определяет возможности нейронной сети и метод обучения. Основными функциями активации считаются:
1) функция активации сигмоиды ????(????) =
1 1+????
−????
относится к классу непрерывных функций и принимает на входе произвольное вещественное число, а на выходе дает вещественное число в интервале от 0 до 1. Сигмоида одна из часто используемых активационных функций в нейронных сетях [8];
2) функция гиперболического тангенса
????(????) =
2 1+????
−2????
=
1 1+????
−????
− 1 является скорректированной сигмоидной функцией и поэтому имеет те же характеристики что и сигмоида. Она хорошо подходит для комбинации слоев, а диапазон значений функции лежит в интервале (-1,1) [8];

17 3) вышеописанные функции активации приводят к проблемам с затуханием или увеличением градиентов поэтому более простой вариант использовать выпрямленную линейную функцию активации ReLu, которая выражается формулой ????(????) = max (0, ????) [8]. Преимущество использования функции в том, что ее производная равна 1 или 0, поэтому произойти разрастания или затухания градиентов не может. Так же ReLu менее требовательна к вычислительным ресурсам, чем сигмоида или гиперболический тангенс из-за того, что производит простые математические операции.
Использование нормализация локального ответа в архитектуре сети позволяет ограничить рост функции активации выходного слоя и делает более крупными пары ответов локальных нейронов, подавляя нейроны с меньшей обратной связью [1]. Для предотвращения переобучения нейронной сети, используется исключающий слой. Во время обучения он случайным образом обнуляет некоторые элементы входных данных.
Преимущество использования сверточных нейросетей в том, что это один из лучших алгоритмов для решения задач распознавания и классификации изображений, нейросеть обладает относительной устойчивостью к повороту или сдвигу распознаваемого изображения, обучение происходит при помощи классического метода обратного распространения ошибки.
Особые проблемы, с которыми сталкиваются системы проверки подписи заключается в небольшом количестве подлинных образцов, которые могут быть использованы для процесса обучения. CEDAR, GPDS300, GPDS
Synthetic, BHSig260 – свободые и широкоиспользуемые базы данных, содержащие наборы эталонных подписей [7]. База данных CEDAR содержит подписи 55 человек, каждый из которых оставил 24 подлинные подписи с интервалом 20 минут. Также каждый подделал 8 подписей для троих человек.

18
Набор данных включает в себя 1320 подлинных подписей и 1320 поддельных.
База данных GPDS300 состоит из 24 подлинных подписей и 30 поддельных для трехсот человек. База данных GPDS Synthetic синтетических сигнатур содержит 4000 человек, где каждый имеет 24 подлинные и 30 поддельных подписей.
База данных BHSig260 содержит подписи 260 человек из них 100 человек подписаны на бенгальском языке, а 160 на хинди. Здесь для каждого человека имеется 24 подлинные и 30 поддельных.

19
2. Реализация приложения для верификации статической
подписи
2.1. Реализация предварительной обработки изображения
Python высокоуровневый объектно-ореинтированный язык программирования, который помимо своей синтаксической простоты и лаконичности обеспечивает высокую производительность при обработке данных, а также имеет большое количество библиотек, упрощающих написание кода. В особенности это относится к использованию в сферах машинного обучения, обработки данных и веб-разработки. Предварительная обработка реализована на языке Python 3.8.1 с использованием следующих библиотек:
1) OpenCV, предназначенная для анализа, классификации и обработки изображения. Модуль CV обработки изображения и компьютерного зрения, включает базовые операции над изображением такие как фильтрация, преобразование цветовых пространств и многое другое;
2) Scikit-image библиотека, включающая в себя алгоритмы сегментации, геометрических преобразований, управления цветовым пространством, обнаружение признаков и т.п.;
3) NumPy и SciPy библиотеки, используемые для математического и численного анализа.
Алгоритм предварительной обработки состоит из пяти этапов. Он представлен в приложении А, файл
Sigex
.py. Целью алгоритма является повышение качества изображения и выделение подписи, рассмотрим его подробнее. Входное изображение представляет собой отсканированный или сфотографированный документ (рис. 2).

20
Рисунок 2. Исходное изображение
На первом этапе предварительной обработки необходимо выпрямить входное изображение (рис. 2) для улучшения чтения, удалив области изображения, не принадлежащие к документу. Для этого переводим входное цветное изображение в оттенки серого, используя функцию cv2.cvtColor(), после выделяем границы методом Канни, для этого сглаживаем изображение используя фильтр Гаусса, чтобы удалить высокочастотные шумы. Метод cv2.GaussianBlur(), сглаживает и устраняет найденные разрывы, применяя перемещаемую по изображению маску размером 5 на 5 и возвращает размытое изображение. Значения ядра должны быть нечетными, чем больше значение ядра, тем сильнее размытие.
Далее применяем морфологический фильтр, находим и сортируем контуры изображения и выпрямляем изображение функцией

21 for_point_transform(). После применяем метод выделения границ cv2.Canny().
Алгоритм Канни использует двойную пороговую фильтрацию, только пиксели, попавшие в средний диапазон, относятся к границе. Используя метод np.median() медианной интенсивности пикселей после выделения границ методом cv2.dilate, расширяем область белого цвета на изображении.
Полученный результат продемонстрирован на рисунке 3.
Рисунок 3. Исходное изображение с выделенными границами
Далее, методом cv2.findContours находим контуры на изображении и сортируем их по убыванию площадей, оставляя только самые большие контуры (первые 5) cnts = sorted(cnts, key=cv2.contourArea, reverse=True)[:5].
После, в цикле для каждого контура вычисляем длину замкнутого контура,

22 используя метод cv2.arcLength и методом cv2.approxPolyDP аппроксимируем кривую. Найдя контур с 4 точками аппроксимации, применяем функцию four_point_transform(). Результат первого этапа предварительной обработки документа изображен на рисунке 4.
Рисунок 4. Выпрямленное изображение
Вторым этапом предобработки изображения служит удаление фона.
Техника выделения подписи из документа берет за основу алгоритм маркировки подключенных компонентов, который сканирует изображение и группирует его пиксели, то есть все пиксели связанных компонентов имеют одинаковые значения интенсивности пикселей и каким-то образом связаны с друг другом. После определения всех групп каждая группа помечается цветом в соответствии с компонентом, которому он был назначен [11]. Извлечение и

23 маркировка различных компонентов в изображении занимает центральное место в приложениях автоматизированного анализа изображений и соответственно поставленной задаче.
Маркировка подключенных компонентов работает на бинарных изображениях или на изображениях в оттенках серого. Подключенные компоненты в изображении представляют собой набор пикселей с одинаковым значением, подключенных через четырехпиксельную или восьмипиксельную связь
(рис. 5).
Четырехпиксельная связь подключает все компоненты имеющие одинаковые значения по краям, восьмипиксельная же подключает компоненты, имеющие одно значение по краям и углам [11].
Рисунок 5. Четырехпиксельная или восьмипиксельная связь
В первую очередь бинаризируем изображение, используя метод cv2.threshold(). Для удаления фона используем два пороговых значения, первое для удаления слишком малых компонентов изображения, которое рассчитывается следующим образом: small_size_outliar_constant = (( average / const_param_1) * const_param_2)
+ const_param_3.
И для удаления больших подключенных компонентов используя формулу определения второго порогового значения:

24 big_size_outliar_constant = small_size_outliar_constant * const_param_4.
Константные значения (const_param_1, const_param_2, const_param_3 и const_param_4) рассчитывались экспериментально [11], а остальные индивидуальны для каждого изображения – average является отношением количества пикселей в контурах и числа этих контуров.
После удаления компонентов, которые не относятся к подписи получаем изображение, которое содержит только рукописную подпись (рис. 6). Как видно на рисунке 6, незначительные элементы подписи были удалены на этом этапе предварительной обработки.
Рисунок 6. Исходное изображение после удаления фона
На третьем этапе, выделяем подпись из документа. Основные элементы текста с документа были удалены на предыдущем этапе предварительной обработки, поэтому здесь подпись занимает самый большой сегмент изображения. Используя метод cv2.findContours и функцией sorted сортируем контуры. С помощью функции boundingRect() преобразуем

25 полученный контур в прямоугольник с координатами x, y верхнего левого угла, шириной w и высотой h, содержащего подпись. Обрежем входное изображение по найденным координатам crop_img = img[y:y+h, x:x+w].
Результат выделения подписи из документа представлен на рисунке 7.
Рисунок 7. Результат выделения подписи из исходного
На четвертом этапе, применяя фильтр Гаусса, улучшаем изображение за счет усиления контраста мелких деталей при неизменном общем контрасте.
Улучшаем изображение повышением четкости исходного изображения, используя нерезкое маскирование. техника использует размытое изображение для создания маски [22]. Для размытия используем метод cv2.GaussianBlur() с ядром 9 на 9. Затем применяем метод cv2.addWeighted – размытое изображение объединяется с исходным, создавая более четкое изображение, т. к. четкое изображение — это разница между исходным и размытым.
На пятом этапе повышаем яркость и контрастность изображения для улучшения последующей верификации.
Используем функцию apply_brightness_contrast(), описанную в приложении
А, файл color_correlation.py.
Рисунок 8. Результат улучшения четкости и контрастности вырезанного изображения
Подведем итоги предварительной обработки изображений, содержащих рукописные подписи. В ходе работы изучены и реализованы следующие

26 методы обработки изображений: фильтрация зашумленных изображений медианным фильтром, сегментация, выделение границ методом Канни, бинаризация изображения, удаление фона, нерезкое маскирование, коррекция яркости и контрастности изображения. Обработка зашумленных изображений медианным фильтром применяется для сглаживания, восстановления изображений и подавлении случайных шумов при наименьшем размывании.
Бинаризация изображения заключается в преобразовании изображения в двухцветное (черно-белое), что повышает эффективность методов сегментации, а также сокращает объем обрабатываемой информации.
Дифференциальные методы обработки изображений с текстом позволяют эффективно выделять объекты и границы подписей на черно-белых изображениях. После сегментации методом Канни над изображением производится операция выделение объекта из фона. Применение порогового значения для данной задачи является простым и эффективным методом. После удаления фона происходит выделение подписи из документа. Для повышения резкости изображения используется нерезкое маскирование. Коррекция яркости и контрастности изображения является заключительным этапом в подготовке изображения перед верификацией.
2.2. Реализация верификации статической подписи
Для реализации задачи верификации рукописной подписи была обучена сверточная сиамская нейронная сеть с использованием библиотеки глубокого обучения PyTorch с открытым исходным кодом для языка Python. PyTorch используется в основном, чтобы обучать модели быстро и эффективно, благодаря архитектуре фреймворка, процесс создания модели достаточно прост и прозрачен. Рассмотрим этот процесс реализации верификации рукописной подписи подробнее. В модуле torch.nn реализован основной функционал для работы с нейросетью. Использовалась библиотека OpenCV, которая предназначена для анализа, классификации и обработки изображений.

27
Архитектура сиамской нейронной сети, предложенная Александром
Крижевским [17], содержит в качестве базовой подсети сверточную нейронную сеть, она представлена на рисунке 9. Данный вариант разрабатывался автором для схожего вида задач [17].
Рисунок 9. Архитектура сверточной нейронной сети (Convolutional – сверточный слой, pooling – слой объединения, linear – полносвязный слой, dropout – исключающий слой, LRN-функция нормализации)
Модель нейронной сети представлена в приложении Б, файл Model.py.
По всей сети применяется функция активации ReLu. Первые сверточные слои фильтруют входное изображение подписи размером 155 × 220 с 96 ядрами размером 11 × 11 с шагом 1 пиксель. Второй сверточный слой принимает в качестве входных данных вывод первого сверточного слоя и фильтрует его 256 ядрами размером 5×5. Третий и четвертый сверточные слои соединены друг с другом без какого-либо вмешательства объединения или нормализации слоев.
Третий слой имеет 384 ядра размером 3 × 3, соединен со вторым сверточным слоем. Четвертый сверточный слой имеет 256 ядер размером 3×3. Это приводит к тому, что нейронная сеть обучается быстрее. Первый

28 полносвязный слой имеет 1024 нейрона, в то время как второй полносвязный слой имеет 128 нейронов.
В сиамской нейронной сети, в качестве функции потерь использовалась функция контрастных потерь [3]. Чтобы минимизировать расстояние между элементами двух одинаковых изображений и заставить элементы разнородного изображения отделяться друг от друга.
????(????
1
, ????
2
, ????) = ????(1 − ????)????
????
2
+ ???????? max(0, ???? − ????
????
)
2
, где ????
1
, ????
2
– изображения подписи,
???? – двоичная индикаторная функция, обозначающая принадлежат ли два изображения одному классу или нет, D
w
– евклидово расстояние, ???? – функция встраивания, которая отображает изображение подписи в реальное векторное пространство через сверточную нейронную сеть, а ????
1
, ????
2
– веса для определенного слоя базовой сети, определяются оптимизатором Adam, который описывается ниже.
Также для проверки работы алгоритма была рассмотрена база данных
CEDAR, которая содержит подписи 55 человек, каждый из которых оставил
24 подлинные подписи с интервалом 20 минут. Также каждый подделал 8 подписей для троих человек. Набор данных включает в себя 1320 подлинных подписей и 1320 поддельных. В файле Dataloaders.py приложения Б разделим датасет CEDAR на тренировочную и тестовую выборки в соотношении 5 к 1, используя функцию train_test_split из библиотеки sklearn. Определим число экземпляров для каждого класса. Сгруппируем и пометим 1 пары с двумя подлинными подписями и 0 пары с подлинной и поддельной подписями.
Создадим классы TrainDataset и TestDataset (файл Dataloaders.py приложения
Б), открывающие сохраненные в файлы вышеописанные сгруппированные наборы изображений. Эти классы наследуются от torch.utils.data.Dataset и в них переопределены методы получения количества образцов в наборе __len__ и получения изображения в тензорном виде по заданному индексу
__getitem__.

29
Процесс обучения нейронной сети требует изображений одинакового размера, поэтому изменим размер изображений до фиксированного размера
155 на 220. После инвертируем изображения так, чтобы пиксели фона имели значение равное 0, и нормализуем изображение, изменяя значение пикселей на стандартное отклонение значений пикселей изображений в наборе данных, показано на рисунках 10 и 11.
Рисунок 10. Исходное изображение
Рисунок 11. Инвертированное изображение
В файле Train.py приложения Б реализуется обучение нейронной сети, архитектура которой описана выше. Для этого подключаем необходимые модули – torch, Model, Dataloaders
Пакет torch.optim реализует различные алгоритмы оптимизации, используем оптимизатор Adam, заменяющий процесс традиционного стохастического градиентного спуска, итеративно обновляя веса нейронной сети на основе обучающих данных. Модуль torch.save используется для сохранения обученной модели. С помощью

30 torch.utils.data, подаем подготовленные данные для обучения модели партиями размером 16 (batch_size = 16 количество данных на вход модели за один проход). train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True).
Класс DataLoader служит для упрощения и ускорения загрузки данных и экономии памяти.
Подготовив данные, внутри цикла перебираем сеты изображений, которые отдает итератор train_loader. Обнуляем градиент у оптимизатора, поскольку в PyTorch по умолчанию происходит накапливание градиента после каждой итерации. После этого совершаем проход по нейронной сети, считаем значение для функции потерь и делаем градиентный шаг оптимизатора.
Определяем среднее значение функции потерь на тренировочной выборке, оно составило 0.323829. Сохраняем обученную модель, продолжительность обучения составила 20 эпох.
В файле Test.py, представленного в приложении Б, рассчитывается пороговое значение для проверки подлинности подписи. Также с помощью torch.utils.data.DataLoader, подаем подготовленные данные для валидации модели с количеством данных на один проход (batch_size) 8. После этого переводим модель в режим оценки методом eval(), далее делаем все то же, что и при обучении, но без расчета градиента. Пороговое значение d составило
0.369907. Средняя точность верификации составила 80,2%.
Таким образом, сиамская нейронная сеть была обучена на 4/5 части набора CEDAR, содержащий как эталонные подписи, так и поддельные.
Точность верификации нейронной сетью, на этапе валидации составила 80,2%.
Так же в результате валидации получено пороговое значение, используемое для определения поддельных подписей, оно равняется 0.369907.

31
1   2   3   4   5


2.3. Реализация конечного приложения верификации
В разделах выше была описана реализация предварительной обработки изображений и выделения подписи из них (раздел 2.1), а также реализация верификации рукописной подписи, использующая нейросетевую модель
(раздел 2.2). Данные реализации представляют собой отдельные программные решения.
Текущий раздел посвящен объединению подмодулей предварительной обработки с выделением подписи и верификации подписей в единое приложение для удобного использования.
Определимся с видом конечного решения, оно будет представлять собой веб-приложение, на котором будет возможность добавлять пользователя, предоставив подлинные изображения, содержащие подпись, и уникальный идентификатор – имя, а также осуществлять верификацию, указав идентификатор (имя) и изображение, содержащее подпись для проверки.
Для интерфейса пользователя приложения достаточно реализовать одностраничный фронтенд, используя HTML, CSS и React JS. Для части, обрабатывающей запросы пользователя и обеспечивающей необходимый функционал приложения, необходимо реализовать бэкенд часть. Разработка подмодулей выделения и верификации подписи велась на python, поэтому лучше всего, с точки зрения простоты процесса взаимодействия, выбрать один из веб-фреймворков, поддерживающих этот же язык. Для небольшого веб- приложения наиболее используемым фреймворком является Flask, он относится к категории микрофреймворков, т. е. минималистичных каркасов веб-приложений, сознательно предоставляющих лишь самые базовые возможности, тем самым обеспечивающим быструю разработку. Основная логика будет представлена разработанными подмодулями выделения и верификации подписи. Необходимо создать классы, обертывающие эти подмодули и обеспечивающие взаимодействие с бэкенд модулем. Для возможности добавления данных пользователя и их последующего

32 использования при верификации необходимо обеспечить хранение этих самых данных. Для этого в приложении необходима база данных, для небольшого приложения достаточно модуля с SQlite3. В этом модуле создается база данных, которая включает в себя таблицу, где хранятся образцы изображений с подлинной подписью, соответствующие уникальному идентификатору – имени записи личности, определенному как первичный ключ.
Вышеописанные модули являются основополагающими для разрабатываемого приложения. Они взаимодействуют между собой, как показано на блок-схеме, представленной на рисунке 12.
Рисунок 12. Блок-схема конечного приложения
Определившись как должно выглядеть приложение, какие технологии использовать и какие модули иметь, перейдем непосредственно к процессу создания. В данном случае разработка началась с реализации фронтенда.
Фреймворк React JS определяет каркас пользовательского интерфейса. В

33 основной функции, формирующей главную и единственную страницу, определим основные компоненты как показано ниже:
<
div
className
="App">
<
h1
> Верификация статической рукописной подписи <
/h1
>
<
UploadImageContainer
imgLimit
="3"
submitButtonText
="Загрузить"
headingText
="Добавьте 3
новые подписи клиента "
allowMultiple
={true}/>
<
VerifyImageContainer
imgLimit
="1"
submitButtonText
="Проверить"
headingText
="Для
проверки добавьте изображение подписи клиента"
allowMultiple
={false}/>

div
>
Как видно в листинге, основными компонентами являются два объекта
– UploadImageContainer и VerifyImageContainer. Приведем содержимое
VerifyImageContainer:
<
div
className
="VerifyImageContainer">
<
p
>{props.
headingText
}

<
TextField
hint
="Customer ID"
customerID
={customerID}
setCustomerID
={setCustomerID} />
<
ActionButton
text
={props.
submitButtonText
}
handleClick
={postData} />
<
BrowseImages
imgLimit
={props.
imgLimit
}
allowMultiple
={props.
allowMultiple
}
fileUrl
={fileUrl}
setFileUrl
={setFileUrl}
filesValid
={filesValid}
setFilesValid
={setFilesValid}
file
={file}
setFile
={setFile} />
<
label
style
={{
color
: errorColor }}>{errorText}<
/label
>
<
Result
style
={{
display
: (errorText == "") ? "inline" : "none" }}
threshold
={threshold}
setThreshold
={setThreshold}
distance
={distance}
setDistance
={setDistance} />

div
>
По своему содержанию UploadImageContainer и VerifyImageContainer практически идентичны, за исключением того, что VerifyImageContainer дополнительно включает в себя поле результат. Оба контейнера обрабатывают нажатие по кнопке
загружая изображения с соответствующими параметрами и затем производят HTTP
POST запрос, содержащий JSON данные, которые включают в себя загруженные изображения и идентификатор из
.
UploadImageContainer выполняет запрос на адрес
“/upload”, а
VerifyImageContainer – на “/verify”. В обоих вариантах также реализована обработка возвращаемого результата и оповещение пользователя в случае ошибок или при успешном выполнении.

34
UploadImageContainer и VerifyImageContainer, как видно из листинга приведенного выше содержат компоненты TextField, ActionButton,
BrowseImages, Result, которые также были реализованы. Получившийся интерфейс представлен на рисунке 13.
Рисунок 13. Интерфейс пользователя в браузере
Следующим шагом было создание бекэнд части, реализация велась на основе фреймворка Flask. В первую очередь реализована обработка обращения к корню веб-приложения, в данном случае производится возврат главной сформированной страницы index.html. Затем была реализована обработка POST запросов по пути “/upload” и “/verify”.
В первом случае полученные изображения и идентификатор пользователя передавался модели, где производилась предварительная обработка изображений с выделением подписи и их сохранение в базу данных.
До добавления в базу данных реализовано удаление уже существующей записи с тем же идентификатором, тем самым обеспечивается уникальность

35 идентификаторов в системе. Также реализована обработка ошибок при работе с базой данных, они возвращаются пользователю в виде оповещения.
Во втором случае (“/verify”) изображение для проверки и идентификатор аналогично передаются модели, но уже выполняется верификация. Для этого в первую очередь производится предварительная обработка изображения с выделением подписи. Затем получение эталонных изображений из базы данных по идентификатору. В цикле изображение на проверку подается с каждым эталонным изображением на вход подмодуля верификации, по результатам выполнения операции сравнения которого определяется расстояние. Затем определяется минимальное вычисленное расстояние из результатов сравнения со всеми эталонными изображениями, и оно сравнивается с пороговым значением. Сравнивая значения, делается вывод о подлинности подписи, что является результатом процесса верификации. Он возвращается пользователю. Также реализована обработка ошибок.
Модель включает в себя подмодули предварительной обработки, выделения и верификации подписи. В ней при запуске приложения производится загрузка сохраненной нейросетевой модели и подключение к базе данных. В модели определены описанные выше сценарии добавления эталонных подписей и верификации в виде методов использования подмодулей.
Таким образом, используя CSS, React JS, Flask, SQlite3 и другие реализовано конечное веб-приложение, содержащее модули, представленные на рисунке 12 и реализующее автоматическую верификацию статической подписи удобным для пользователя способом.

36
3. Результаты тестирования приложения
Основной целью при реализации процедуры проверки подписи является сведение ошибок при распознавании к минимуму. Данные ошибки можно разделить на два типа: первого, когда система выдает отрицательный результат верификации при проверке эталонной подписи, и второго рода, когда система выдает положительный результат при проверке поддельной подписи. Оба типа ошибок связаны между собой и зависят от принятого порогового значения для определения подписи. При увеличении этого значения процент ошибки первого рода уменьшается, а процент ошибки второго рода увеличивается и наоборот.
Точность (accuracy) – это самая простая метрика оценки, которую можно себе представить, и она определяется как количество правильных прогнозов, деленное на общее количество прогнозов, умноженное на 100. Эту метрику можно назвать базовой. Она измеряет количество верно классифицированных объектов относительно общего количества всех объектов.
???????????????????????????????? =
???????? + ????????
???????? + ???????? + ???????? + ????????
,
где FP, FN – количества ошибок первого и второго рода; TP, TN – количество верно классифицированных объектов в положительном и отрицательном случаях. Более точно TP, TN и FP, FN представлены на рисунке 14. Таким образом, ошибки классификации бывают двух видов: False Negative (FN) первого рода и False Positive (FP) второго рода.
Тем не менее, у метрики accuracy есть одна особенность, которую необходимо учитывать. Она присваивает всем документам одинаковый вес, что может быть не корректно в случае, если распределение документов в обучающей выборке сильно смещено в сторону какого-то одного или нескольких классов.

37
Рисунок 14. Матрица ошибок
Тестирование разработанного программного обеспечения проходило с использованием подписей 13 людей. Каждый оставил четыре личные подлинные подписи и подделал две подписи других. Было составлено два набора:

в первом наборе содержатся 52 образца, распределенные по группам из четырех подлинных подписей одного человека;

во втором наборе содержатся 104 образца, распределенные по группам из трех подлинных и одной поддельной подписи.
Используя первый набор образцов подписей для вычисления ошибок первого рода, а второй набор для вычисления ошибок второго рода.
В ходе экспериментов на первом наборе получено, что 41 образец определён верно (из 52), а оставшиеся 11 определены неверно. Процент ошибок первого рода – 21.15%. На втором наборе 81 образец (из 104) определен верно и 23 ошибочно. Процент ошибок второго рода 22.11%.
Подставив полученные значения в формулу метрики точности, получим:
???????????????????????????????? =
41+81 41+11+23+81
= 0.78205128.

38
Таким образом, 78,21 % – точность верификации рукописной подписи, с использованием обученной модели нейронной сети (раздел 2.2).
На рисунке 15 приведен пример корректной работы – определено, что подпись подлинная, при подаче изображения с подлинной подписью на проверку. На рисунке 16 приведен пример ошибочной верификации первого рода – определено, что подпись подлинная при подаче изображения с поддельной подписью.
На рисунке 17 приведен пример корректной работы – определено, что подпись поддельная, при подаче изображения с поддельной подписью на проверку. На рисунке 18 приведен пример ошибочной верификации второго рода – определено, что подпись поддельная при подаче изображения с подлинной подписью.
Исходя из результатов тестирования приложения, точность верификации подписи с использованием обученной нейронной сети на датасете CEDAR при проверке на собственном наборе образцов составляет
78.21%. Возможной причиной низкой точности может быть недостаточное количество и разнообразие образцов для обучения.

39
Рисунок 15. Пример корректной верификации типа TP

40
Рисунок 16. Пример ошибочной верификации типа FN

41
Рисунок 17. Пример корректной верификации типа TN

42
Рисунок 18. Пример корректной верификации типа FP

43
Заключение
Рукописные подписи имеют большое значение как наиболее распространенное средство личной верификации. Подписи признаются в качестве юридического средства проверки личности человека административными и финансовыми учреждениями. Необходимость верификации рукописной подписи объясняется активным процессом автоматизации деятельности, связанной с документооборотом, а также необходимостью распознавания, визуализации для различного рода задач.
Автономные системы верификации статической подписи используются, когда доступны только печатные копии подписей.
Для реализации статического метода верификации подписи используют различные подходы, например, искусственные нейронные сети, скрытые марковские модели, различные виды метрик, метод опорных векторов, вычисление локальных экстремумов или вычисление матриц расстояний.
Нейросетевой подход имеет ряд преимуществ. Можно заключить, что нейронные сети более эффективно строят нелинейные зависимости, которые точнее описывают данные подписей, также они более устойчивы к шумам во входных данных и более адаптированы к их изменениям, что является важным условием при работе с типичными примерами документов, содержащих рукописную подпись [10, 12, 14, 15].
Перед выполнением алгоритмов нейросетевой модели необходимо подготовить изображения. Во-первых, с целью подготовки пригодных для верификации изображений, это связанно с тем, что как правило, подписанную копию документа, подлежащего обработке, сканируют или фотографируют, это в свою очередь определяет задачу выделения подписи из изображения. Во- вторых, с целью повышения точности верификации, так как качество предполагаемых материалов может быть низким. В ходе работы изучены и реализованы следующие методы обработки изображений: фильтрация

44 зашумленных изображений медианным фильтром, сегментация, выделение границ методом Канни, бинаризация изображения, удаление фона, нерезкое маскирование, коррекция яркости и контрастности изображения.
Для реализации верификации рукописной статической подписи, использовались библиотеки OpenCV и
PyTorch.
Были изучены принципы работы сиамских нейросетей, а именно, принципы построения архитектуры, функции активации и принципы обучения. Поскольку нейросети данного вида наиболее подходящие для решения задачи, в которой проводится измерение сходства между двумя или более объектами. В качестве базовой сети была выбрана сверточная нейронная сеть, архитектура которой представлена на рисунке 9, она состоит из 11 слоев, из них 4 – сверточных и 3 – полносвязных, подробнее они описываются в разделе 2.2. Использовалась функция активации
ReLu, она менее требовательна к вычислительным ресурсам и в ней не может произойти разрастания или затухания градиентов. В качестве функции потерь использовалась функция контрастных потерь, чтобы минимизировать расстояние между элементами двух одинаковых изображений и заставить элементы разнородного изображения отделяться друг от друга [3]. Сиамская нейронная сеть была обучена на 4/5 части набора CEDAR и протестирована на оставшейся части. Точность верификации нейронной сетью, на этапе валидации составила 80.2%. Так же в результате валидации получено пороговое значение, используемое для определения поддельных подписей, оно равняется 0.369907.
Используя CSS, React JS, Flask, SQlite3 и реализованные подмодули предварительной обработки, выделения подписи и верификации, реализовано конечное веб-приложение, реализующее автоматическую верификацию статической подписи удобным для пользователя способом. В приложении есть возможность добавлять пользователя, предоставив подлинные изображения, содержащие подпись, и уникальный идентификатор – имя личности, а также

45 осуществлять верификацию, указав идентификатор (имя) и изображение, содержащее подпись для проверки.
На завершающем этапе работы было проведено тестирование на собранном личном наборе подписей, который состоит из 78 подписей от 13 человек (каждый по 4 собственные подписи и 2 поддельные других). Точность верификации составила 78.2%.
Подводя итог, отметим, что все поставленные задачи выполнены и цель работы достигнута – разработано и реализовано программного обеспечения автоматической верификации статической подписи с использованием нейронных сетей. Полученный процент точности верификации мал для работы достоверных систем верификации, это обусловлено тем, что даже для одного человека образцы подписи могут отличаться, также со временем подпись может измениться, на это влияет множество внешних и внутренних факторов, таких как психоэмоциональное состоянием человека, срочность подписания, поверхность на которой подписывался документ и многое другое.
Достигнутой точности достаточно для множества задач, где требуется проверка соответствия или определения наличия подписи на документах, например, поиска в архивах подписанных документов одним человеком.

46
Список использованной литературы
1.
Aqeel A. Difference between local response normalization and batch normalization,
06.
2019.

[Электронный ресурс] https://towardsdatascience.com/difference-between-local-response-normalization- and-batch-normalization-272308c034ac
(Дата обращения 23.05.2021).
2.
Azzopardi G. How effective are radial basis function neural networks for offline handwritten signature verification. // Thesis, B. Sc. University of London. ―
2006. ― p. 123.
3.
Buglione J., Sethu H. K., Digging deeper into metric learning with loss function,
12.2019.

[Электронный ресурс]
(
https://towardsdatascience.com/metric-learning-loss-functions-5b67b3da99a5
)
(Дата обращения 09.05.2021).
4.
Canny John. A computational approach to edge detection // IEEE
Transactions on pattern analysis and machine intelligence, vol. 8, № 6. ―1986. ― pp. 679-698.
5.
Cemil OZ, Ercal F., Demir Z. Signature recognition and verification with
ANN, using moment invariant method // International symposium on neural networks
― 2005. ― pp. 643-649.
6.
Cuceloglu I., Ogul H. Detecting handwritten signatures in scanned documents
// Proceedings of the 19th Computer Vision Winter Workshop ― 04.2014. ― pp.
89–94.
7.
Diaz M., Ferrer M., Impedovo D., Malik M. I., Pirlo G., Plamondon R. A
Perspective analysis of handwritten signature technology // ACM Comput. Surv. 51,
6, Article 117. ― 2019. ― p. 39.
8.
Fuchang G., Boyu Z. A use of even activation functions in neural networks //
Arxiv journals. ― 23.11.2020.
9.
Gonzalez R., Woods R. Digital image processing // the University of
Michigan. ― 2011. ― pp. 261-267.

47 10.
Hafemann Luiz G., Sabourin R., Oliveira Luiz S. Offline handwritten signature verification // Seventh international conference on image processing theory, tools and applications (IPTA). ― 2017.
11.
Horn B. Robot vision // MIT Press chap. 4. ― 1986.
12.
Impedovo D., Pirlo G. Automatic signature verification: the state of the art //
IEEE transaction on system, man and cybernetics, vol 38 no. 5. ― 09. 2008. ― pp.
609-635.
13.
Ioannis P., Basilis G., Konstantinos N., Basilios G. Segmentation based recovery of arbitrarily warped document images // Ninth international conference on document analysis and recognition (ICDAR 2007), vol 2. ― 2007.
14.
Jae Duk Seo. Understanding 2D dilated convolution operation with examples in numpy and Tensorflow with Interactive code, 03.2018 ― [Электронный ресурс] https://towardsdatascience.com/understanding-2d-dilated-convolution-operation- with-examples-in-numpy-and-tensorflow-with-d376b3972b25
(Дата обращения
23.04.2021).
15.
Koch G., Zemen R., Salakhutdinov R., Siamese neural networks for one-shot image recognition // Department of Computer Science, University of Toronto. ―
2015.
16.
Kolhe S. T. Offline signature verification using neural network // International journal of modern engineering research, vol.2. ― 2012. ― pp. 1171-1175.
17.
Krizhevsky A. One weird trick for parallelizing convolutional neural networks // Arxiv journals. ― 2014.
18.
Leal-Taixe L., Canton-Ferrer C., Schindler K., Learning by tracking: siamese
CNN for robust target association // IEEE Conf. on computer vision and pattern recognition Workshops (CVPRW). ― 2016. ― pp. 418-425.
19.
Otsu N. A. Threshold selection method from gray-level histograms // IEEE
Transaction on system, man and cybernetics, vol. SMC-9. ― 1979. ― pp. 62-66.

48 20.
Shafait F., Breuel T. M. Document image dewarping contest // In 2nd Int.
Workshop on camera-based document analysis and recognition, Brazil. ― 2007. ― pp. 181- 188.
21.
Shi J., Malik J. Normalized cuts and image segmentation // IEEE Conf.
Computer vision and pattern recognition. ―1997. ― pp. 731-737.
22.
Unsharp masking ― [Электронный ресурс]
(
https://scikit- image.org/docs/dev/auto_examples/filters/plot_unsharp_mask.html
)
(Дата обращения 18.02.2021).
23.
Власов А. В., Цапко И. В. Модификация алгоритмов Канни применительно к обработке рентгенографических изображений // Вестник наук Сибири, № 4 (10). ― 2013. ― C. 120–127.
24.
Глущенко Н.А., Коннова Н.С. Нейросетевой подход к верификации рукописной подписи // МГТУ им. Баумана. Политехнический молодежный журнал, № 5 ― 2018.
25.
Макфузова А.И., Якименко А.А. Анализ метода сегментации изображения для картин волнового поля // Сборник научных трудов НГТУ, № 3-4 (93). ―2018. ― C. 70-82.
26.
Федоров А. Бинаризация черно-белых изображений: состояние и перспективы развития

[Электронный ресурс] http://it- claim.ru/Library/Books/ITS/wwwbook/ist4b/its4/fyodorov.htm
(Дата обращения
23.01.2021).
27.
Предварительная обработка изображений // Национальной библиотеки им.
Н. Э. Баумана,
5.12.2016

[Электронный ресурс] https://ru.bmstu.wiki/Предварительная_обработка_изображений
(Дата обращения 23.01.2021).
28.
Сверточные нейронные сети // Конспекты кафедры компьютерных технологий Университета ИТМО, 28.03.2021. ― [Электронный ресурс] https://neerc.ifmo.ru/wiki/index.php?title=Сверточные_нейронные_сети#ResNet
(Дата обращения 03.04.2021).

49
1   2   3   4   5


Приложение А. Код модуля предварительной обработки
изображения
SigEx.py
import sigex.signature_extractor.sample_project.color_correlation as color_correlation import cv2 import sigex.signature_extractor.sample_project.dewapper as dewapper import sigex.signature_extractor.sample_project.signature_extractor as signature_extractor import sigex.signature_extractor.sample_project.unsharpen as unsharpen import sigex.signature_extractor.sample_project.captch as captch def SignatureExtraction(image): img = 0 try: img = dewapper.dewarp_book(image) cv2.imwrite("step 1 -page_dewarped.jpg", img) print("- step1 (cropping with the argins + book dewarpping): OK") except Exception as e: print("type error: " + str(e)) print("ERROR IN CROPPING & BOOK DEWARPING! PLEASE CHECK
LIGTHNING,"
" SHADOW, ZOOM LEVEL AND ETC. OF YOUR INPUT BOOK IMAGE!") try img = signature_extractor.extract_signature(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)) cv2.imwrite("step 2 - signature_extracted.jpg", img) print("- step2 (signature extractor): OK") except Exception as e: print("type error: " + str(e)) print("ERROR IN SIGNATURE EXTRACTION! PLEASE CHECK LIGTHNING,
SHADOW,"
" ZOOM LEVEL AND ETC. OF YOUR INPUT BOOK IMAGE!") try: img = unsharpen.unsharpen_mask(img) cv2.imwrite("step 3 - unsharpen_mask.jpg", img) print("- step3 (unsharpening mask): OK") except Exception as e: print("type error: " + str(e)) print("ERROR IN BOOK UNSHARPING MASK! PLEASE CHECK LIGTHNING,
SHADOW,"
" ZOOM LEVEL AND ETC. OF YOUR INPUT BOOK IMAGE!") try: img = color_correlation.funcBrightContrast(img) cv2.imwrite("step 4 - color_correlated.jpg", img) print("- step4 (color correlation): OK") except Exception as e: print("type error: " + str(e)) print("ERROR IN BOOK COLOR CORRELATION! PLEASE CHECK LIGTHNING,
SHADOW,"
" ZOOM LEVEL AND ETC. OF YOUR INPUT BOOK IMAGE!")

50 try: file_name = "step 4 - color_correlated.jpg" crop_img = captch.captch_ex(file_name) cv2.imwrite("step 5 - crop image.jpg", crop_img) print("- step5 (crop image): OK") except Exception as e: print("type error: " + str(e)) print("ERROR! COULD NOT CUT THE CAPTION, PLEASE CHECK THE INPUT
IMAGE OF THE BOOK!") return crop_img
dewapper.py
import cv2 import imutils import numpy as np from utils.transform import four_point_transform def dewarp_book(image):
# get input image ration to keep best output resolution quality ratio = image.shape[0]/500.0
# copy source image for filter operations orig = image.copy()
# resize the input image image = imutils.resize(image, height=500)
# convert rgb input image to grayscale gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) #image gray = cv2.GaussianBlur(gray, (5, 5), 0) #5.5.0
# sigma parameter is used for automatic Canny edge detection sigma = 0.33
# compute the median of the single channel pixel intensities v = np.median(gray) #image
# apply automatic Canny edge detection using the computed median lower = int(max(0, (1.0 - sigma) * v)) #нижняя граница upper = int(min(255, (1.0 + sigma) * v)) #верхняя граница edged = cv2.Canny(gray, lower, upper)#image cv2.imwrite("edged0.jpg", edged)
# perform dilate morphological filter to connect teh image pixel points kernel = np.ones((5, 5), np.uint8) edged = cv2.dilate(edged, kernel, iterations=1) #расширенеие изображения cv2.imwrite("edged.jpg", edged)
# найдите контуры на обрезанном изображении, сохраняя только
# # большие камни и инициализация контура экрана cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
#поиск контуров cnts = imutils.grab_contours(cnts) cnts = sorted(cnts, key=cv2.contourArea, reverse=True)[:5]#сортировка контуров по убыванию площадей
# loop over the contours отрисовка контура for c in cnts: peri = cv2.arcLength(c, True)#замкнутый контур, периметр approx = cv2.approxPolyDP(c, 0.02 * peri, True)

51
# если наш аппроксимированный контур имеет четыре точки, то мы
# можно предположить, что мы нашли наш экран if len(approx) == 4: screenCnt = approx break
# apply the four point transform for book dewarping warped = four_point_transform(orig, screenCnt.reshape(4, 2) * ratio) return warped
Signature_extractor.py
import cv2 import matplotlib.pyplot as plt from skimage import measure, morphology from skimage.measure import regionprops import numpy as np
# значения используются для удаления подключенных компонентов малого размера constant_parameter_1 = 84 constant_parameter_2 = 250 constant_parameter_3 = 100
# значение для удаления подключенных компонентов большого размера constant_parameter_4 = 16.7 def extract_signature(source_image): img = source_image img = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)[1] # перевод в бинароное
# анализ подключенных компонентов используя scikit-learn blobs = img > img.mean() blobs_labels = measure.label(blobs, background=1) fig, ax = plt.subplots(figsize=(5, 8)) the_biggest_component = 0 total_area = 0 counter = 0 average = 0.0 for region in regionprops(blobs_labels): if (region.area > 10): #количество пикселей в области total_area = total_area + region.area counter = counter + 1 if (region.area >= 250): if (region.area > the_biggest_component): the_biggest_component = region.area print("total_area: " + str(total_area)) print("counter: " + str(counter)) average = (total_area/counter) print("the_biggest_component: " + str(the_biggest_component)) print("average: " + str(average))
# расчет порогового значения для удаления выделенных пикселей, меньших чем a4_small_size_outliar_constant =
((average/constant_parameter_1)*constant_parameter_2)+constant_parameter_3 print("a4_small_size_outliar_constant: " + str(a4_small_size_outliar_constant))
# расчет порогового значения для удаления выделенных пикселей больших чем a4_big_size_outliar_constant = a4_small_size_outliar_constant*constant_parameter_4


52 print("a4_big_size_outliar_constant: " + str(a4_big_size_outliar_constant))
# удаление pre_version = morphology.remove_small_objects(blobs_labels, a4_small_size_outliar_constant) component_sizes = np.bincount(pre_version.ravel()) too_small = component_sizes > (a4_big_size_outliar_constant) too_small_mask = too_small[pre_version] pre_version[too_small_mask] = 0
# предварительная версия, помеченная цветами plt.imsave('pre_version.png', pre_version) img = cv2.imread('pre_version.png', 0)
# перевод в бинароное img = cv2.threshold(img, 0, 255,cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1] return img
unsharpen.py
import cv2 def unsharpen_mask(image):
# применяем фильтр Гаусса gaussian_3 = cv2.GaussianBlur(image, (9, 9), 10.0)
# вычисляем взвешенную сумму unsharp_image = cv2.addWeighted(image, 1.5, gaussian_3, -0.5, 0, image) return unsharp_image
color_correlation.py
import cv2 contrast = 0 brightness = 0 def funcBrightContrast(img, bright=0): effect = apply_brightness_contrast(img, bright, contrast) return effect def apply_brightness_contrast(input_img, brightness=255, contrast=127): brightness = 80 contrast = 60
# яркость отлична от нуля if (brightness != 0): if (brightness > 0): shadow = brightness highlight = 255 else: shadow = 0 highlight = 255 + brightness alpha_b = (highlight - shadow) / 255 gamma_b = shadow
# меняем яркость buf = cv2.addWeighted(input_img, alpha_b, input_img, 0, gamma_b) else: buf = input_img.copy()
# контрастность отлична от нуля

53 if contrast != 0: f = float(131 * (contrast + 127)) / (127 * (131 - contrast)) alpha_c = f gamma_c = 127*(1-f) buf = cv2.addWeighted(buf, alpha_c, buf, 0, gamma_c) return buf
captch.py
import cv2 def captch_ex(file_name): img = cv2.imread(file_name) img2gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, mask = cv2.threshold(img2gray, 180, 255, cv2.THRESH_BINARY) image_final = cv2.bitwise_and(img2gray, img2gray, mask=mask) ret, new_img = cv2.threshold(image_final, 180, 255, cv2.THRESH_BINARY_INV) kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (3,3)) dilated = cv2.dilate(new_img, kernel, iterations=9) contours, hierarchy = cv2.findContours(dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) # поиск контура height, width = img.shape[:2] contours = sorted(contours, key=cv2.contourArea) contours = contours[::-1] for contour in contours:
# контур ограничивающего прямоугольника
[x, y, w, h] = cv2.boundingRect(contour)
# исключаем ложные ссрабатывания if w < 35 and h < 35: continue if w >= 0.9 * width or h >= 0.9 * height: continue
# отрисовка контура cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 255),2) break crop_img = img[y:y+h, x:x+w] return crop_img

54
Приложение Б. Код модуля верификации подписи
Model.py import torch
#скелет архитектуры class SiameseConvNet(Module): def __init__(self): super().__init__() self.conv1 = Conv2d(1, 48, kernel_size=(11, 11), stride=1) self.lrn1 = LocalResponseNorm(48, alpha=1e-4, beta=0.75, k=2) self.pool1 = MaxPool2d(kernel_size=(3, 3), stride=2) self.conv2 = Conv2d(48, 128, kernel_size=(5, 5), stride=1, padding=2) self.lrn2 = LocalResponseNorm(128, alpha=1e-4, beta=0.75, k=2) self.pool2 = MaxPool2d(kernel_size=(3, 3), stride=2) self.dropout1 = Dropout(0.3) self.conv3 = Conv2d(128, 256, kernel_size=(3, 3), stride=1, padding=1) self.conv4 = Conv2d(256, 96, kernel_size=(3, 3), stride=1, padding=1) self.pool3 = MaxPool2d(kernel_size=(3, 3), stride=2) self.dropout2 = Dropout(0.3) self.fc1 = Linear(25 * 17 * 96, 1024) self.dropout3 = Dropout(0.5) self.fc2 = Linear(1024, 128)
#принцип перемещенияданных def forward_once(self, x): x = relu(self.conv1(x)) x = self.lrn1(x) x = self.pool1(x) x = relu(self.conv2(x)) x = self.lrn2(x) x = self.pool2(x) x = self.dropout1(x) x = relu(self.conv3(x)) x = relu(self.conv4(x)) x = self.pool3(x) x = self.dropout2(x) x = x.view(-1, 17 * 25 * 96) x = relu(self.fc1(x)) x = self.dropout3(x) x = relu(self.fc2(x)) return x def forward(self, x, y): f_x = self.forward_once(x) f_y = self.forward_once(y) return f_x, f_y def distance_metric(features_a, features_b): batch_losses = F.pairwise_distance(features_a, features_b) return batch_losses class ContrastiveLoss(torch.nn.Module): def __init__(self, margin=2): super(ContrastiveLoss, self).__init__()