Удаление / маскирование фона в Python с использованием обнаружения краев и scikit-изображения

Я хотел бы создать два изображения из исходного изображения RAW, в данном случае Canon CR2. Я отсортировал RAW-преобразование и кое-что обработал. Мои окончательные изображения должны быть в формате PNG с альфа-маской и в формате JPG 95% качества с альфа-областью, заполненной черным цветом. У меня есть тестовое изображение, показывающее, как далеко я продвинулся в обнаружении объекта:

http://imgur.com/a/Q8k3w/all

Итак, как вы можете видеть, я хочу изолировать объекты от серого фона. Я также хочу максимально и в идеале полностью замаскировать любые тени на сером фоне. Я использую сценарий Python2, который я написал, и до сих пор в основном scikit-image. При необходимости я бы переключился на другую библиотеку обработки изображений, совместимую с Python. Кроме того, мне нужно сделать все шаги в памяти, чтобы я сохранял только один раз в конце всей обработки изображений с PNG, а затем JPG. Так что нет подпроцесса. Открыть и т. Д.

Из примеров изображений вы увидите, что, по крайней мере, я думаю, что у меня уже есть какой-то способ решения. Я использовал scikit-image и его алгоритм Canny edge для изображений, которые вы видите в моих примерах.

Что мне теперь нужно сделать, так это выяснить, как заполнить объект на изображениях Canny белым цветом, чтобы я мог получить правильную сплошную белую маску. В большинстве моих примеров изображений с примененным фильтром Кэнни кажется, что есть хорошее обнаружение краев для самих предметов, обычно с большой непрерывной границей. Но я предполагаю, что в будущем я могу получить некоторые изображения, где этого не происходит, и могут быть небольшие разрывы в основной границе. Мне нужно обработать это происшествие, если похоже, что это будет проблемой для последующих этапов обработки.

Кроме того, мне интересно, нужно ли мне увеличить общую границу на один пиксель и установить для нее тот же цвет, что и мой 0,0-пиксель (т.е. первый пиксель вверху / слева в фоновом режиме), а затем запустить мой фильтр Canny и затем сжать мой граница снова на 1px? Это должно позволить обнаруживать нижний край и когда объекты ломают верхнюю или боковые стороны кадра?

Так что на самом деле я просто ищу совета и задаюсь вопросом, куда пойти дальше, чтобы получить красивую сплошную маску. Он должен оставаться двоичным как двоичная маска (т.е. все, что находится за пределами основного объекта, должно быть полностью замаскировано до 0). Это означает, что мне нужно будет запустить что-то, что в какой-то момент будет искать изолированные островки пикселей ниже определенного объема пикселей - возможно, последний шаг и добавить их в маску (например, 50 пикселей или около того).

Кроме того, в целом, практическое правило будет заключаться в том, что лучше, если будет замаскирована небольшая часть объекта, чем маскируется меньшая часть фона (т.е. я хочу, чтобы все или как можно больше областей фона / тени были замаскированы. )

Я пробовал несколько вещей, но не совсем понял. Я думаю, что что-то вроде find_contours в sci_kit может помочь. Но я не совсем понимаю из примеров scikit-image, как я бы выбрал, а затем превратил обнаруженный контур в маску. Я убил довольно много времени, экспериментируя сегодня безуспешно, и поэтому я подумал, что спрошу здесь и посмотрю, есть ли у кого-нибудь лучшие идеи.

Это многообещающий метод на основе OpenCV:

http://funcvis.org/blog/?p=44

Я хотел бы придерживаться scikit-image или какой-либо другой сменной библиотеки изображений numpty для python, если это возможно. Однако, если это проще и быстрее с OpenCV или другой библиотекой, тогда я открыт для идей, пока я могу придерживаться Python.

Также стоит иметь в виду, что для моего приложения у меня всегда будет изображение фона без объекта. Так что, может быть, мне стоит пойти по этому пути. Проблема в том, что я не думаю, что простой разностный подход хорошо работает с тенями. Мне кажется, что в какой-то момент требуется какое-то обнаружение краев для более качественного подхода к маскировке.

1"Источник 1"

2"Источник 2"

3"Источник 3"

1"Результат 1"

2"Результат 2"

3"Результат 3"


person robeastham    schedule 15.05.2016    source источник


Ответы (2)


Из ограниченного опыта предлагаю попробовать.

Результаты обнаружения Canny edge не позволяют отличить отверстия (в объекте Result 2) от сплошных областей (в Result 3). Это нормально для ваших целей? Будет ли соответствовать вашим потребностям обнаружение капель на этих краях и их заполнение, устраняя, таким образом, дыры из результата 2?

Предположим, что часть, которую вы хотите замаскировать, - это исходные серые области фона вместе с более темными серыми тенями на этом сером фоне. Кроме того, некоторая серая область минимального размера квалифицируется как «дыра», а не как серые пиксели или серый шум на объекте. (Есть ли способ различить части объекта, похожие на серый фон?)

Итак, рассмотрим этот план:

  1. Преобразуйте изображение в цветовое пространство HSV (или HSL).
  2. Вычислить 8-битное / пиксельное изображение «пороговой маски» серой шкалы, где каждый пиксель указывает, является ли соответствующий входной пиксель вероятным фоном или вероятным передним планом: если насыщенность входного пикселя ниже порогового значения ts (серый или почти серый) и его значение (или яркость) находится в пределах порогового диапазона [tv1 .. tv2] (темно-тень-фон-серый через фон-серый), тогда это скорее всего-фон, поэтому сделайте выходной пиксель 0 (черный), иначе он скорее всего-передний план, поэтому сделайте это 255 (белый).
  3. Расширьте белые пиксели, чтобы заполнить пробелы, затем Erode их обратно, чтобы восстановить исходный размер. . Эта пара операций также известна как Закрытие морфология. [Имейте в виду, что образец изображения на этой странице является запутывающим примером. Он расширяется, а затем размывает белые пиксели образца изображения, которые трудно не рассматривать как черно-белые штрихи!]

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

На шагах 2 и 3 создаются альфа-каналы (маски) типа "все или ничего". Возможно, на этих этапах лучше использовать несколько уровней серого (нечеткая логика), но не совсем понятно, как это сделать.

Примечание. Если вы используете JPEG 2000 в качестве окончательного формата выходного изображения, то один файл может содержать изображение со сжатием с потерями и его альфа-канал. Он также может поддерживать полную глубину цвета из исходного файла RAW.

person Jerry101    schedule 15.05.2016

Я собираюсь сделать снимок в этом.

Если вам нужны чистые маски объектов, есть что-то, называемое адаптивным пороговым значением (схема локального порогового значения), я думаю, это может быть жизнеспособным для вас, особенно потому, что оно может удалить эффекты теней, наряду с этим попробуйте пороговое значение Оцу (еще один автоматический но глобальная схема порога).

Посмотрите, какой из них дает лучшие результаты, и реализуйте тот, который вам нужен.

Я сказал это, потому что ваш запрос очень похож на классическую задачу определения порога (объекты на одном фоне).

Конечно, используйте морфологические операции для очистки вашей маски (как указал другой пользователь, было бы достаточно для удаления небольших спекл-шума).

person MyBushisaNeonJungle    schedule 15.05.2016