Привет, Хабр.


Хочу представить вам небольшой проект, который я написал вместо во время сессии.


Суть такова: это классификатор, определяющий наличие стеганографии в изображении. Сразу стоит отметить, что классификатор получился довольно простым: он работает с методом LSB, где заменяется один последний бит 8-битного RGB изображения, и проверялся только на полностью заполненных стегоконтейнерах.
Поиграть с тем, что получилось, можно тут. Примеры картинок (кстати, принимаются только png) есть здесь.


Реализация стегоанализа:


Дело в том, что стегоанализ можно рассматривать как задачу двухклассовой классификации машинного обучения. Каждый объект (картинку) необходимо описать набором признаков для дальнейшей обработки. Для этого будет использоваться алгоритм SPAM (Subtractive Pixel Adjacency Model of covers). Суть этого алгоритма состоит в том, что по различным направлениям считается разность цветов соседних пикселей $D$, а затем вычисляются условные вероятности:


$M_{u,v} = P(D_{i,j+1}=u|D_{i,j}=v)$


где $u,v$ принадлежат множеству чисел $T = [-4,-3,-2,-1,0,1,2,3,4]$.


Таким образом получается вектор признаков для каждого изображения. Эти данные подаются на вход алгоритму машинного обучения.


Чтобы обучить классификатор, я использовал около 1000 картинок, скрытое сообщение содержалось примерно в 200 из них. Сами сообщения — случайные наборы символов (предполагается, что сообщение было зашифровано перед помещением в стегоконтейнер).


В качестве классификатора используется Catboostclassifier. Это библиотека для градиентного бустинга на основе деревьев решений.


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


Реализация всего остального:


Сначала я хотел описать всё только на словах, но быстро понял, что без схемы во всем известном графическом редакторе не обойтись:


Alt text


Пройдемся по её элементам:


  • Главная страница, которая действительно ничего не имеет, кроме кнопки “Загрузить”. На случай, если не верите, а ссылка уже не работает, вот скриншот:

  • Дальше пользователя перенаправит по ссылке, равной значению хэша файла. Это сделано для того, чтобы разные отправленные файлы гарантированно перенаправляли на разные страницы с результатом, но в то же время повторная отправка файла вела к странице с уже известным результатом, которого не придётся ждать. Там находится страница с «Подождите, пожалуйста», которая обновляется каждые 5 секунд, пока файл обрабатывается алгоритмом.
  • Для того, чтобы все файлы гарантированно шли на обработку, используется брокер сообщений RabbitMQ. Сообщением является сама картинка в бинарном формате.
  • Далее сообщения принимаются алгоритмом, который переводит их обратно в изображения и проводит стегоанализ так, как это описано выше, с той разницей, что теперь вектор извлечённых признаков подаётся классификатору не для обучения, а для предсказания.
  • Redis – это хранилище ключ-значение, куда отправляется результат. Ключом является все тот же хэш файла. В Redis можно легко настроить время жизни записи, поэтому здесь не понадобятся сборщики мусора.

Заключение


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


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


Весь код реализован на языке Python 3 версии. Полный код проекта выложен на github. Ну и ещё раз, ссылка на результат работы.


Также хочу выразить благодарность пользователю PavelMSTU за советы при разработке проекта и рекомендации по оформлению статьи.