Ни для кого не секрет, что порно существует. Само явление старо как мир и из века в век развивается наравне с человечеством, становясь то более доступным, то уходя в подполье под запреты. В некоторых странах порнография узаконена, в некоторых за неё можно в лучшем случае угодить в тюрьму, а может, и вовсе проститься с жизнью. Учёные до хрипоты спорят, проводя исследования, чего больше приносит порнография — пользы или вреда.
Одно исследование может утверждать, что благодаря порнографии снижается количество изнасилований. Другое исследование иногда, даже на основе тех же самых данных, представляет совершенно противоположные выводы. Так что же такое порнография — благо или зло? Предоставим это решать философам, политикам, домохозяйкам... да кому угодно. Сегодня я хочу взглянуть не на проблему порно как явления, а на способы его автоматического определения и отлова.
Итак, сегодня у нас тема порно глазами программистов (что само по себе — то ещё порно)!
Посудите сами, порно не получится истребить. Оно было и будет. Но вряд ли найдётся хоть один родитель, который был бы рад увидеть своего малолетнего ребёнка за просмотром какого-нибудь очередного бестселлера от студии «Private». Поэтому, несомненно, важной задачей является именно отлов порноконтента ещё на периоде загрузки его на файлообменник. Если ребёнку не дать возможности просмотра, то мало кто полезет искать его самостоятельно.
Ну и стоит ли напоминать вам, что в нашей стране производство, хранение и распространение порнографии уголовно наказуемы? Так как же могут обезопасить себя владельцы файлообменных сервисов от недобросовестных пользователей, которые вопреки правилам грузят запрещённый контент?
Если взяться за описание его модели, то получится примерно следующее:
И если с работой SecurityOfficer всё понятно, то к софту есть вопросы. Как научить машину определять порно? Этому вопросу и посвятим нашу статью. В материале я буду опираться на существующий порнофильтр Licenzero.
При анализе порноматериалов существуют четыре подхода, которые позволяют с максимальной вероятностью определить принадлежность ролика к необходимому нам классу:
Секрет успеха кроется в обучении будущего порнофильтра. Для этого важно понимать, что по сути надо решить только две задачи:
Для решения первой задачи необходим начальный материал. Он отбирается вручную. Картинки, скриншоты из видео и т.д. Так сказать, проявите фантазию. Этот материал не обязательно должен быть порнографическим, ведь кожа в обоих случаях одинакова.
Затем нужно получить координаты точек, классифицированных как человеческая кожа. Вот один из вариантов решения:
Процесс выделения границ кожи
С помощью самодельной программы человек вручную закрашивает все места, где кожи нет. Для большей точности выделения можно сделать различный размер кисти, которой производится выделение. Также можно подойти с другой стороны и выделять области с кожей. Выбор за вами.
Тем временем координаты миллионов точек (в RGB) получены и встаёт новая проблема: проблема выбора цветовой модели, в которой будут рассматриваться полученные точки. Что выбрать: RGB, LAB, HSV, YСbCr...?
В рассматриваемом порнофильтре выбор пал на YСbCr. Не в последнюю очередь потому, что поскольку предстояло классифицировать именно по цвету, то можно было отбросить «серую» компоненту яркости Y.
Так выглядят точки картинок на шкале Сb:
Значения Сb
И на шкале Сr:
Значения Сr
Заметно, что по этим двум координатам можно выделить пиксели кожи. Вот как выглядит вероятность (по нашим данным) того, что некоторая точка с координатами Cb и Cr является кожей:
Оценка вероятностей попаданий Cb и Cr
Там, где синий цвет — вероятность равна 0%, там, где красный — 100%. Эта горка говорит о том, что, выбрав, например, 50% в качестве порога для классификации кожи, легко можно отделить цвет кожи (в координатах Cb и Cr) от всего другого цвета.
Для целей классификации можно использовать не SVM, а просто определить прямоугольную область, оптимально классифицирующую пикселы кожи. То есть, такой псевдо-SVM с четырьмя опорными векторами.
псевдо-SVM
Черная линия — и есть этот псевдоSVM. Зеленая линия — вероятность в 50% того, что точка на этой кривой относится к коже (красная: 90%, синяя: 10%). То есть, все точки с координатами Cb и Cr, которые попадают внутрь черного прямоугольника, являются пикселами кожи.
Думаю, хватит теоретических выкладок. Пора взглянуть, как такая система работает на практике:
Систему можно и дальше улучшать, но зачем? Такого анализа достаточно, чтобы перейти к решению более интересной задачи: к классификации по цвету кожи.
Теперь программа знает, что именно считать кожей. Пора научить её отличать «порно» от «не порно». Поскольку, в основном, нужно обрабатывать видеоданные, то от цветового пространства YCbCr лучше перейти к YUV (по сути, это одно и то же). C YUV работать в данном случае удобно, так как не нужно не только перекодировать сырое видео, но и пар (U, V) получается в два раза меньше, чем точек в кадре (если видео в формате yuv420p).
Выгода, как говорится, налицо.
А с самой классификацией всё обстоит гораздо проще, чем вы думаете. Если объяснять «на пальцах», то в порно люди голые, а в остальных видео одетые (конечно, многие из читателей тут же могут опровергнуть меня и сказать, что в категорию «порно» запросто попадёт и Hustler, и семейное видео с отдыха в Турции. Всё так. И именно поэтому классификация по цвету кожи — лишь один четырёх методов, по которым будет выноситься окончательный вердикт).
Таким образом, нужно посчитать долю цвета кожи в порно и непорно роликах (то есть количество «кожаных» пикселов разделить на общее количество пикселов в ролике).
Результат представлен ниже:
Уровень кожаных пикселов
Это гистограммы распределения роликов. По оси Y — количество роликов, по оси X — доля пикселов кожи в ролике. Пунктирными линиями показаны графики плотности распределения.
Если измерять долю пикселов кожи не в целых роликах, а в порно и непорно фрагментах, а такие фрагменты стоит предварительно нарезать вручную, то результаты будут еще лучше.
В итоге, детектор цвета кожи возвращает вероятность того, что фрагмент является порнографическим. И эта вероятность просто является функцией от доли пикселов кожи во фрагменте. Функция приблизительно такая:
Уровень кожаных пикселов
Итак, подводя черту под первым подходом в определении порно, резюмируем его основные принципы:
При поиске порнографии нельзя оставить без внимания и отдельные кадры. Нужно поискать что-нибудь и там. Для извлечения полезной информации непосредственно из кадров в рассматриваемом фильтре используют Bag of Visual Words. То есть сначала определяются «визуальные слова» — фрагменты или сэмплы, которые лучше всего характеризуют кадры с порно и без. Получается такой набор визуальных слов. А затем при классификации детектор по наличию тех или иных слов в картинке дает оценку порнографичности данного кадра.
Для извлечения полезной информации непосредственно из кадров в рассматриваемом фильтре используют Bag of Visual Words.
Но этот подход не единственный. В кадре можно искать определённые формы и объекты, которые могут содержаться только в порно. Приведу пример с женской грудью. В самом общем понимании её можно охарактеризовать как группу пикселов с «цветом кожи» овальной или круглой формы, внутри которой есть ещё одна группа пикселов более тёмного цвета. По идее, такой алгоритм сможет задетектить фронтальный план обнажённой груди без особых трудностей.
В кадре можно искать определённые формы и объекты, которые могут содержаться только в порно.
На самом деле этот подход едва ли не один из самых сложных в реализации. При обработке видео есть ряд нюансов, которых нет при обработке простых изображений: сложнее с определением цветов, низкое качество роликов (далеко не всё порно в HD, согласитесь), артефакты после сжатия различными кодеками, пикселизация и т.д. Да и определить форму объекта для программы порой весьма затруднительно. Смешно, но правда: детекторы формы часто путают то, что некоторые студенты кладут на учёбу, и большой палец.
Двигаемся дальше. И не просто двигаемся, а двигаемся ритмично :)
Поиск ритмичного движения в кадре можно назвать основой основ при определении порноконтента. В теории всё выглядит довольно просто. Сущность классификации заключается в том, чтобы разделить некоторое множество объектов на два класса. Для этого:
Вот так всё просто. Но за этой мнимой простотой, как обычно, скрывается интересное техническое решение.
Принцип работы большинства систем машинного обучения достаточно прост. Для классификации объектов на классы А и Б описывается совокупность их некоторых признаков (features), которые можно каким-либо образом измерить. Далее, статистически выводится формула или выражение, которая, если в нее подставить конкретные значения признаков для конкретного объекта, выдает значение >0 для объектов класса А, и значение <0 для объектов класса Б.
Например, мы хотим автоматически отличить, скажем, красную икру от черной. Признаки — цвет и размер икринки. Выберем несколько икринок черной и красной икры, измерим их и отразим ситуацию на графике.
Икринки
Пунктирная линия хорошо разделяет два имеющихся класса объектов. Видно, что красная икра крупнее и светлее черной. Построим формулу для этой линии, например:
z = размер * c1 - цвет * c2 + c0,
где:
c1 и c2 — некоторые коэффициенты, статистически подобранные по результатам наблюдений;
c0 - константа.
В итоге, имея какую-то неизвестную икринку, мы подставим ее размер и цвет в нашу формулу, и при z>0 скажем, что икра красная, а при z<=0 — что она черная.
Это все, конечно, широко известно в узких кругах. Существует достаточно большое количество алгоритмов классификации. Например, при создании детекторов в рассматриваемом фильтре были использованы методы AdaBoost и Support Vector Machines.
Но вернёмся к теме — анализ ритмичности движения. Пожалуй, это один из самых важных признаков при классификации видеоконтента. Редко какой порноролик обходится без характерных ритмичных движений. Да, «татушки» знали, о чём пели. Что ж, приступим.
Одним из известных и часто применяемых методов анализа движения является optical flow. Например, реализация optical flow отсутствует в широко известной библиотеке OpenCV. Принцип работы напоминает поиск векторов движения при кодировании видео в формате mpeg — в одном кадре выбираются некоторые фрагменты изображения, которые ищутся в следующем кадре (например, методом SAD). Движение объектов соответствует смещению фрагментов изображения между кадрами.
Однако при реализации optical flow в детекторе порноконтента появляются нюансы:
Для определения направления движений используются пространственно-временные фильтры (spatiotemporal filters), основанные на применении операции свертки сигнала (convolution) и суммирования. Такой метод только начинает получать широкое распространение.
Давайте разберём применение свертки на простом, двухмерном примере. Допустим, вы применяете операцию «выделение края» (detect edges) к изображению в графическом редакторе.
Графический редактор создает маску размером 3×3, накладывает ее на изображение, начиная с каждого пиксела, перемножает соответствующие числа и суммирует результаты умножения. Результатом является одно число — можно сказать, что оно тем больше, чем сигнал под маской похож на саму маску.
Аналогичным образом, но в трехмерном пространстве (двумерные координаты пиксела в кадре + время или номер кадра в качестве третьего измерения), работают и использованные нами фильтры.
Оценка движения
На рисунке ниже показан результат работы такого фильтра движения на небольшом отрывке порноролика.
Работа порнофильтра
Само видео можно увидеть на сайте авторов фильтра. Картинка в центре — текущий кадр из ролика. Картинки вокруг него — результат фильтрации последовательности кадров фильтрами. Каждый результат соответствует одному из двенадцати выбранных направлений движения. Зеленые кривые — это график количества движения в каждом направлении на протяжении нескольких десятков кадров.
Заметно, что характерные для порнографических роликов движения выражаются характерной, легко узнаваемой кривой. Также по этой кривой можно оценить количество персонажей в видеоролике и направления и скорость их движений.
В приведенном выше примере видео — два участника, двигающиеся в противоположных направлениях. Большие периодичные всплески на зеленой кривой соответствуют сильным движениям мужчины влево. Маленькие всплески соответствуют ответным движениям женщины и более слабым, возвратным движениям мужчины.
В случае присутствия лишь одного участника в видео (такое часто встречается в видеочатах), кривая не имеет вторых всплесков, чем-то напоминает синусоиду и легко поддается анализу. В случае трех или более участников ситуация значительно осложняется. Согласитесь, некоторые из редко встречающихся действий партнеров не могут быть смоделированы ни математически, ни даже описаны словесно.
Скорость движения также может быть использована для оценки времени акта. Если вы внимательно смотрели на данные ролика (а не на размытое изображение), то заметили, что, приближаясь к окончанию ролика, амплитуда движений увеличивается, а период — сокращается. К сожалению, данная оценка, скорее, представляет академический интерес, так как на практике является не слишком надёжным показателем.
После того, как необходимые кривые были получены, осталось сделать последний шаг — научить компьютер отличать кривые, соответствующие порнографическим материалам, от других кривых. Тут тоже есть выбор методов, например:
Для оценки кривых можно использовать существующие системы фильтрации словесного спама, основанные на методе Баейса. Каждая кривая может быть превращена в последовательность «слов» следующим образом:
Таким образом, ролик превращается в набор «слов». Скажем, слова, похожие на 0110011, зачастую наблюдаются в порнороликах.
После превращения видеоролика в описание в виде набора таких «слов», тренировка обычного спам-фильтра для фильтрации порнографии — это уже просто дело техники.
Вот мы практически и добрались к финишной кривой. На мой взгляд, классификация звука по уровню сложности в реализации уступает детектору движений. Остановимся лишь на примерном описании подхода.
Вначале вручную отбирается тренировочное множество объектов, которое вырезается из порнороликов. Затем создаётся модель, обучается система, возвращается вероятность принадлежности ролика к порно.
Сам детектор звука основывается на двух основных параметрах:
Таким образом, можно судить о наличии стонов (понятно, с некоторой вероятностью) в звуковом фрагменте. То есть, по этим двум параметрам детектор классифицирует фрагмент. Хотя, в реальной жизни женщины стонут по разным причинам, но для первого приближения сойдет.
В современном мире количество информации увеличивается даже не экспоненциально, и не в геометрической прогрессии. Всё происходит крайне быстро. Вместе с технологией изменяются и представления людей о хранении информации. Если ещё пару лет назад каждый считал своим долгом хранить любимую музыку на жёстком диске (а может на всякий случай ещё и на CD\DVD бэкап держать), то сейчас такие люди вызывают, скорее, удивление, чем понимание. Last.fm, prostopleer, googlemusic, appstore и прочие сервисы прочно укореняются на новых серверах, количество которых по последним данным выросло аж на 51%. Облачные технологии приходят на смену старым методам. Всё меняется и мы меняемся следом.
На разросшихся видеохостингах и файлообменных сервисах человек не в силах модерировать все входящие файлы. Только ведь статьи за «создание, хранение и распространение» не отменяли. В свете такой ситуации в процессе модерации человек отходит на «руководящую» должность, предоставляя делать «грязную» работу по отбору подозрительного контента машине.
Конечно, ни одна из систем не может дать 100% точности отбора. Представленные в статье подходы, к примеру, плохо сработают, если в порноролике будут участвовать темнокожие люди.