Привет, коллеги! В прошлом году защитил диплом и выложил исходники —
github.com/maxbogus/fltrVd. В прошлом посте я писал о проекте, но без деталей. Сегодня — разбор по косточкам: как устроен конвейер, на чём написано, с какими граблями столкнулся и что из этого вышло.
В открытых каналах (RTSP, веб-камеры, YouTube) можно спрятать данные прямо в пикселях. Классика — LSB (младшие биты) или маскировка под высокочастотный шум. Глаз не отличит артефакт сжатия от внедрённого файла. Моя задача — научить алгоритм находить эти «закладки» и помечать подозрительные кадры, не путая их с обычным шумом или сменой сцены.
Система fltrVd — это не один скрипт, а целый пайплайн из пяти этапов:
1. Захват
2. Предобработка
3. Извлечение признаков
4. Классификация
5. Постобработка
Я сравниваю гистограммы соседних кадров четырьмя методами из OpenCV. Но одного критерия недостаточно — резкая смена сцены тоже меняет гистограмму. Поэтому все метрики идут в общий пул признаков.
LSB-проверка
Для синего канала извлекается младший бит. Считается доля единиц, бинарная энтропия и отклонение от 0.5. При случайном заполнении контейнера распределение стремится к равномерному. Есть упрощённый chi-square-тест на парах соседних значений — порог пока эвристический (15.0), дальше буду калибровать на реальных данных.
Нейросеть — не SVM, не RandomForest, а CNN на PyTorch
Да, я попробовал и классические ML-алгоритмы, но они проигрывали по точности. В итоге остановился на двух моделях:
1. TinyVGG — лёгкая CNN для быстрых экспериментов.
2. SteganalysisNet — первый слой с фиксированными SRM-фильтрами (30 штук), дальше обучаемые свёртки, BatchNorm и Global Average Pooling. Именно SRM помогает вытащить слабый стегосигнал, который обычно «тонет» в шуме.
Датасет и обучение
Сгенерировал синтетический набор:
1. 2500 изображений на класс для обучения, 725 — для теста.
2. Шумы: гауссовское, экспоненциальное, гамма-, равномерное, рэлеевское.
3. Встраивание LSB с заполнением 25%, 50%, 75%.
Обучение: 30 эпох, batch_size=32, Adam (lr=0.001), CrossEntropyLoss. Без аугментации точность на тесте ~0.614, с аугментацией на некоторых эпохах доходила до 0.839. Для синтетики — неплохо, но до промышленного применения ещё далеко.
Временные аномалии
Последовательность размеров кадров после PNG-кодирования разбивается на окна по 10 кадров. Автоэнкодер сжимает окно до двух латентных значений и пытается восстановить. Ошибка восстановления, превышающая mean + 2*std, помечается как аномалия. Так я ловлю не только одиночные «закладки», но и их влияние на поток.
Что в коде и как всё организовано
Какие были сложности (и как я их победил)
1. Не перепутать шум с контейнером — главная боль. Чистый шум, сжатие, смена сцены — всё даёт выбросы. Решение: комбинировать гистограммы, LSB-статистику, размер кадра, CNN и временную модель. Ни один признак не доминирует.
2. Скорость обработки — на первых версиях всё тормозило. Перешёл на пакетную обработку: собираю батч кадров и прогоняю через модель один раз. Добавил mixed precision, cosine scheduler, gradient clipping, early stopping — ускорило обучение и инференс.
3. Эвристические пороги — для LSB и автоэнкодера они пока ручные. В планах — подбирать их по ROC/PR-кривым на валидации, но это уже за рамками диплома.
Что получилось и куда двигаться дальше
Система обнаруживает LSB-контейнеры, которые визуально неотличимы от шума. График временного ряда чётко показывает, где заканчивается «чистый» шум и начинается подозрительная активность. Мне удалось убедиться, что совместное использование статистических критериев и нейросетей действительно работает.
Диплом дал мне бесценный опыт: я вплотную столкнулся с CV, ML, стеганографией и понял, что это не магия, а математика, которая видит то, что скрыто от глаза. Код местами сыроват — прошу прощения у будущих форкеров, но для первого погружения в тему он вполне рабочий.
Буду рад звёздочкам, вопросам в Issues и конструктивной критике. Заходите, обсуждаем!
Ссылка на проект:
github.com/maxbogus/fltrVd