
Детектор цвета кожи является одним из детекторов, при помощи которых мы классифицируем видео. Он не такой сложный, как детектор движения, или детектор фрагментов, можно даже сказать совсем простой. Вначале у нас была куча идей, связанных с цветом кожи в видео. Но попробовав самый простой подход к классификации, мы решили (возможно временно) на нем остановиться, поскольку полученные результаты нас вполне устроили. Итак.
Определение цвета кожи
Задачи перед нами стояло две:
- определить, какой цвет можно назвать «цветом кожи»,
- классифицировать порноролики по цвету кожи.
Итак, начнем с цвета кожи. Перво-наперво мы набрали несколько тысяч картинок. Как просто картинок, так и кадров из видео, в том числе и порнографического, поскольку нас в первую очередь интересовало именно такое видео.
Затем с помощью простой самодельной программки:

Мы отметили на картинках области с кожей и без. Таким образом мы получили координаты (в RGB) нескольких миллионов точек, классифицированных по принадлежности этих координат человеческой коже.
Затем стала проблема выбора цветовой модели, в которой мы будем рассматривать координаты точек. Выбирали между RGB, LAB, HSV и YСbCr. Провели несколько тестов и решили остановиться на YСbCr, не в последнюю очередь потому, что поскольку нам предстояло классифицировать именно по цвету, то можно было отбросить «серую» компоненту яркости Y.
Вот так выглядели точки с наших картинок на шкале Сb:

И на шкале Сr:

То есть, заметно, что этим двум координатам можно выделить пиксели кожи. Вот как выглядит вероятность (по нашим данным) того, что некоторая точка с координатами Cb и Cr является кожей:

Там, где синий цвет — вероятность равна 0%, там где красный — 100%. Эта горка говорит нам о том, что мы выбрав, например, 50% в качестве порога для классификации кожи, мы легко сможем отделить свет кожи (в координатах Cb и Cr), от всего другого цвета.
Мы решили не использовать для целей классификации SVM, а просто определить прямоугольную область, оптимально классифицирую пиксели кожи. То есть, такой псевдо-SVM с четырьмя опорными векторами. Вот такой получился прямоугольник:

Черная линия — наш прямоугольник. Зеленая линия — вероятность того, что точка на этой кривой относится к коже равна 50% (красная: 90%, синяя: 10%). То есть, все точки с координатами Cb и Cr, которые попадают внутрь черного прямоугольника являются пикселями кожи.
Вот пример определения кожи нашей системой:
На этом прямоугольнике мы приостановили свои изыскания, потому что это все конечно интересно, но нужно двигаться дальше — к классификации порнографии по цвету кожи.
Классификация по цвету кожи
Итак, мы определились с тем, что мы будем считать кожей. Поскольку мы работаем с видеоданными, то от цветового пространства YCbCr мы перешли к YUV (по сути, это одно и тоже, русская википедия даже редиректит со страницы YCbCr на страницу YUV). C YUV работать в данном случае исключительно удобно. Мы не только не перекодируем сырое видео, но и пар (U, V) у нас получается в два раза меньше, чем точек в кадре (если видео в формате yuv420p), в общем, сплошная экономия.
Но что же с классификацией? С классификацией все оказалось еще проще, чем с определением цвета кожи. Мы подумали: а что будет, если посчитать долю цвета кожи в порно и непорно роликах (то есть количество «кожных» пикселей разделить на общее количество пикселей в ролике). Получилась вот такая картинка:

Это гистограммы распределения роликов. По оси Y — количество роликов, по оси X — доля пикселей кожи в ролике. Пунктирными линиями показаны графики плотности распределения, если мы предположим, что распределение в обоих случаях нормальное, но это так, просто для иллюстрации.
Если измерять долю пикселей кожи не в целых роликах, а в порно и непорно фрагментах, а такие фрагменты у нас тоже есть — мы их вручную повырезали, когда делали детектор движения, то там результаты будут еще лучше.
Наш детектор цвета кожи возвращает вероятность (впрочем, как и остальные наши детекторы) того, что фрагмент является порнографическим. И эта вероятность просто является функцией от доли пикселей кожи во фрагменте. Функция приблизительно такая:

Итак, для того, чтобы классифицировать некоторый фрагмент некоторого ролика, мы:
- считаем количество пикселей кожи во всех кадрах фрагмента;
- делим на общее число пикселей кожи во всех кадрах фрагмента — получаем долю пикселей кожи;
- в зависимости от доли пикселей кожи получаем значение вероятности того, что фрагмент — порнографический;
- используем данную вероятность наравне с вероятностями, полученными от других детекторов для итоговой классификации фрагмента и целого ролика.