Определить фотографии против изображений
Я пытаюсь, учитывая случайное изображение и используя NumPy, определить, является ли это фотография "отрендеренным" изображением (например, картой). Изображения могут быть цветными или черно-белыми, а градиенты на визуализированных изображениях могут легко использовать 0-255, поэтому подсчет цветов не поможет для оттенков серого. Я не могу использовать метаданные EXIF /etc.
Подходы, которые я до сих пор быстро испробовал, ничего не выпрыгивая:
- Преобразование в оттенки серого, затем просмотр гистограммы
- 2D БПФ затем смотрит на гистограммы частот на полосу (как RGB и YUV)
- Рассматривая средства и стандартное отклонение яркости
- Обнаружение края с использованием фильтров Canny и Sobel
- Сравнение свойств GLCM для случайных патчей 21x21 от каждого изображения
- Сжатие изображений в формате JPEG (хорошо для фотографий) или Deflate (иначе PNG) (хорошо для карт) и сравнение битов на пиксель
(не стесняйтесь предложить мне вернуться и посмотреть еще раз)
Я обычно анализирую случайные образцы больших площадей, а не мелких культур, как примеры, показанные ниже, поэтому подходы, которые игнорируют случайные крайние случаи, должны работать.
Текущие многообещающие предложения описаны ниже, идеи, которые я еще не рассмотрел:
- Ни одного не осталось
Есть ли алгоритмы / подходы, на которые я должен обратить внимание?
HSV
Все еще в стадии разработки для черно-белых изображений:) - но оттенок и насыщенность всех визуализированных изображений гораздо более резкие, чем на фотографиях, и, как правило, также имеют максимумы в 2-5 раз выше.
image_hsv = skimage.color.rgb2hsv(image_rgb)
hue_band, sat_band, val_band = np.squeeze(np.dsplit(image_hsv, 3))
band_hist, _ = np.histogram(hue_band.ravel(), bins=256)
peak_idx = np.signal.argrelmax(band_hist, order=20)[0]
peaks = band_hist[peak_idx]
контрастировать
Изучение контраста кажется немного лучше, рассчитывается с помощью кода ниже. Фотографии, как правило, кажутся <= 130, а карты обычно>= 150. Хотя черно-белые карты имеют очень низкий контраст (например, 11 для изображения ниже):
# image_rgb is a 3D numpy array: [
# [ [r,g,b], [r,g,b], ... ],
# [ [r,g,b], [r,g,b], ... ],
# ...
# ]
# these constants from http://en.wikipedia.org/wiki/Relative_luminance
rgb2lum = numpy.array([0.2126, 0.7152, 0.0722])
luminance = numpy.dot(image_rgb, rgb2lum)
# for B&W images, luminance == image_bw already
rms_contrast = numpy.sqrt(numpy.mean(numpy.square(luminance)))
Текущий подход
То, что я в настоящее время пошел с:
- Анализирует до 8x 512x512px случайных патчей из изображений, которые все голосуют за результат:
- Для изображений RGB конвертируйте патч в цвет HSV
- Создание гистограммы (256 бинов) из черно-белых данных или полосы Хюэ (
np.histogram()
) - Подсчитайте непустые ячейки в гистограмме, если менее 100 голосов - это "карта".
- Получите пики гистограммы (
signal.argrelmax(hist, order=20)
) - Если максимальный пик составляет>9% от общего количества пикселей в полосе, а максимальный пик> = в 2 раза больше среднего значения пиков, тогда голосование принимается за "карту".
- В противном случае голосование будет "фото"
- Если 50% голосов от патчей "карта", то результат "карта"
Это очень хорошо, когда вы работаете с цветными изображениями, и результаты снова улучшаются, если у вас есть несколько изображений в наборе данных и вы можете повторно голосовать на уровне каждого изображения.
Черно-белые изображения все еще немного попали или пропустили.
Примеры изображений
Высококонтрастное цветное фото. Некоторые могут быть довольно передержаны:
Низкоконтрастное цветное фото:
Высококонтрастное черно-белое фото. Опять же, некоторые могут быть довольно передержаны:
Низкоконтрастное черно-белое фото:
Низкоконтрастная цветовая карта:
Высококонтрастная карта:
Черно-белая карта:
1 ответ
Я согласен, что это может быть немного за рамками SO. Возможно, отправьте его в Cross Validated?
Чтобы начать, я бы посоветовал рассмотреть особенности текстуры каждого изображения, а не цвета или контрастность. Идея обнаружения краев - это шаг в правильном направлении.
Как только вы преобразуете каждое изображение в набор числовых текстурных объектов, вы можете использовать двоичный классификатор, чтобы отделить фотографии от синтетических изображений.