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

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

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

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

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

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

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

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

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

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

Это метод на основе OpenCV, который выглядит многообещающе:

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

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

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

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

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

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

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

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

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

2 ответа

Из ограниченного опыта, я предложу несколько идей, чтобы попробовать.

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

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

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

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам