Какие методы обработки изображений можно использовать для реализации приложения, которое обнаруживает рождественские елки, отображаемые на следующих изображениях?
Я ищу решения, которые будут работать на всех этих изображениях. Поэтому подходы, которые требуют обучения каскадных классификаторов Хаара или сопоставления с шаблоном , не очень интересны.
Я ищу что-нибудь, что можно написать на любом языке программирования, если в нем используются только технологии с открытым исходным кодом . Решение должно быть протестировано с изображениями, которые передаются по этому вопросу. Есть 6 входных изображений и в ответе должны отображаться результаты обработки каждого из них. Наконец, для каждого выходного изображения должны быть нарисованы красные линии, чтобы окружить обнаруженное дерево.
Как бы вы могли программно обнаружить деревья на этих изображениях?
источник
Ответы:
У меня есть подход, который я считаю интересным и немного отличным от остальных. Основное отличие моего подхода по сравнению с некоторыми другими заключается в том, как выполняется этап сегментации изображения - я использовал DBSCAN алгоритм кластеризации из Python's scikit-learn; он оптимизирован для поиска несколько аморфных форм, которые могут не обязательно иметь единый четкий центроид.
На верхнем уровне мой подход довольно прост и может быть разбит на 3 этапа. Сначала я применяю порог (или фактически, логическое «или» двух отдельных и разных порогов). Как и во многих других ответах, я предположил, что рождественская елка будет одним из самых ярких объектов в сцене, поэтому первый порог - это просто простой монохромный тест яркости; любые пиксели со значениями выше 220 по шкале 0-255 (где черный равен 0, а белый - 255) сохраняются в двоичном черно-белом изображении. Второй порог пытается найти красные и желтые огни, которые особенно заметны на деревьях в верхнем левом и нижнем правом углу шести изображений и хорошо выделяются на сине-зеленом фоне, который преобладает на большинстве фотографий. Я конвертирую изображение RGB в пространство HSV, и требуют, чтобы оттенок был меньше 0,2 по шкале 0,0-1,0 (примерно соответствует границе между желтым и зеленым) или больше 0,95 (соответствует границе между фиолетовым и красным), и дополнительно мне требуются яркие насыщенные цвета: насыщенность и значение должны быть выше 0,7. Результаты двух пороговых процедур логически «или» объединены, и результирующая матрица черно-белых двоичных изображений показана ниже:
Вы можете четко видеть, что каждое изображение имеет один большой кластер пикселей, приблизительно соответствующий местоположению каждого дерева, плюс несколько изображений также имеют некоторые другие небольшие кластеры, соответствующие либо огням в окнах некоторых зданий, либо фоновая сцена на горизонте. Следующий шаг - заставить компьютер распознать, что это отдельные кластеры, и правильно пометить каждый пиксель идентификатором членства в кластере.
Для этой задачи я выбрал DBSCAN . Существует довольно хорошее визуальное сравнение того, как DBSCAN обычно ведет себя по сравнению с другими алгоритмами кластеризации, доступными здесь . Как я уже говорил ранее, это хорошо с аморфными формами. Выходные данные DBSCAN, где каждый кластер представлен в другом цвете, показаны здесь:
Есть несколько вещей, о которых следует помнить, глядя на этот результат. Во-первых, DBSCAN требует, чтобы пользователь установил параметр «близости», чтобы регулировать его поведение, которое эффективно контролирует, как должна быть разделена пара точек, чтобы алгоритм объявлял новый отдельный кластер, а не агломерировал контрольную точку на уже существующий кластер. Я установил это значение в 0,04 раза больше размера по диагонали каждого изображения. Поскольку размер изображения варьируется от примерно VGA до примерно HD 1080, этот тип определения относительного масштаба имеет решающее значение.
Еще один момент, который стоит отметить, заключается в том, что алгоритм DBSCAN, реализованный в scikit-learn, имеет ограничения памяти, которые довольно сложны для некоторых больших изображений в этом примере. Поэтому для нескольких больших изображений мне пришлось «прореживать» (то есть сохранять только каждый 3-й или 4-й пиксель и отбрасывать остальные) каждый кластер, чтобы оставаться в пределах этого предела. В результате этого процесса отбраковки оставшиеся отдельные разреженные пиксели трудно увидеть на некоторых больших изображениях. Поэтому, только для целей отображения, пиксели с цветовой кодировкой в приведенных выше изображениях были эффективно "немного расширены", чтобы они лучше выделялись. Это чисто косметическая операция ради повествования; хотя есть комментарии, упоминающие это расширение в моем коде,
Как только кластеры идентифицированы и помечены, третий и последний шаг становится легким: я просто беру самый большой кластер в каждом изображении (в этом случае я решил измерить «размер» с точки зрения общего количества пикселей-членов, хотя можно было бы так же легко вместо этого использовал некоторый тип метрики, который измеряет физическую протяженность) и вычислил выпуклую оболочку для этого кластера. Затем выпуклая оболочка становится границей дерева. Шесть выпуклых оболочек, рассчитанных с помощью этого метода, показаны ниже красным цветом:
Исходный код написан для Python 2.7.6 и зависит от numpy , scipy , matplotlib и scikit-learn . Я разделил это на две части. Первая часть отвечает за фактическую обработку изображения:
а вторая часть представляет собой скрипт уровня пользователя, который вызывает первый файл и генерирует все графики, приведенные выше:
источник
scipy.ndimage.filters.maximum_filter()
в том же месте, где я использовал порог.ПРИМЕЧАНИЕ ПО РЕДАКТИРОВАНИЮ: я отредактировал этот пост, чтобы (i) обрабатывать каждое древовидное изображение отдельно, как того требуют требования, (ii) учитывать яркость и форму объекта, чтобы улучшить качество результата.
Ниже представлен подход, который учитывает яркость и форму объекта. Другими словами, он ищет объекты треугольной формы и со значительной яркостью. Это было реализовано на Java с использованием Marvin фреймворка обработки изображений .
Первым шагом является пороговое значение цвета. Цель здесь - сфокусировать анализ на объектах со значительной яркостью.
выходные изображения:
исходный код:
На втором этапе самые яркие точки на изображении расширяются, чтобы сформировать фигуры. Результатом этого процесса является вероятная форма объектов со значительной яркостью. Применяя сегментацию заливки, обнаруживаются несвязанные формы.
выходные изображения:
исходный код:
Как показано на выходном изображении, было обнаружено несколько фигур. В этой задаче есть всего несколько ярких точек на изображениях. Однако этот подход был реализован для решения более сложных сценариев.
На следующем шаге анализируется каждая фигура. Простой алгоритм обнаруживает фигуры с рисунком, похожим на треугольник. Алгоритм анализирует форму объекта построчно. Если центр масс каждой линии формы почти одинаков (при заданном пороговом значении) и масса увеличивается с увеличением y, объект имеет форму треугольника. Масса линии формы - это количество пикселей в этой линии, которое принадлежит форме. Представьте, что вы разрезаете объект по горизонтали и анализируете каждый горизонтальный сегмент. Если они расположены по центру друг от друга, и длина увеличивается от первого сегмента до последнего в линейном порядке, у вас, вероятно, есть объект, напоминающий треугольник.
исходный код:
Наконец, положение каждой фигуры, похожее на треугольник и со значительной яркостью, в данном случае рождественской елки, выделяется на исходном изображении, как показано ниже.
окончательный вывод изображений:
окончательный исходный код:
Преимущество этого подхода в том, что он, вероятно, будет работать с изображениями, содержащими другие светящиеся объекты, так как он анализирует форму объекта.
Счастливого Рождества!
РЕДАКТИРОВАТЬ ПРИМЕЧАНИЕ 2
Существует дискуссия о сходстве выходных изображений этого решения и некоторых других. На самом деле они очень похожи. Но этот подход не просто сегментирует объекты. Он также анализирует формы объекта в некотором смысле. Он может обрабатывать несколько светящихся объектов в одной сцене. На самом деле, рождественская елка не обязательно должна быть самой яркой. Я просто записываю это, чтобы обогатить дискуссию. Существует смещение в образцах, что просто ища самый яркий объект, вы найдете деревья. Но действительно ли мы хотим прекратить обсуждение на этом этапе? На данный момент, насколько далеко компьютер действительно распознает объект, напоминающий елку? Попробуем закрыть этот пробел.
Ниже представлен результат, чтобы прояснить этот момент:
входное изображение
вывод
источник
Вот мое простое и глупое решение. Он основан на предположении, что дерево будет самой яркой и большой вещью на картинке.
Первым шагом является обнаружение самых ярких пикселей на картинке, но мы должны различать само дерево и снег, отражающий его свет. Здесь мы пытаемся исключить снег, применяя действительно простой фильтр к цветовым кодам:
Затем мы находим каждый «яркий» пиксель:
Наконец мы объединяем два результата:
Теперь мы ищем самый большой яркий объект:
Сейчас мы почти закончили, но есть еще некоторые недостатки из-за снега. Чтобы обрезать их, мы создадим маску, используя круг и прямоугольник, чтобы приблизить форму дерева для удаления ненужных фрагментов:
Последний шаг - найти контур нашего дерева и нарисовать его на исходной картинке.
Извините, но сейчас у меня плохое соединение, поэтому я не могу загрузить фотографии. Я постараюсь сделать это позже.
Счастливого Рождества.
РЕДАКТИРОВАТЬ:
Вот несколько картинок с окончательным выводом:
источник
./christmas_tree ./*.png
. Их может быть сколько угодно, результаты будут показываться один за другим нажатием любой клавиши. Это неправильно?<img src="http://i.stack.imgur.com/nmzwj.png" width="210" height="150">
просто измените ссылку на картинку;)Я написал код в Matlab R2007a. Я использовал k-средства, чтобы примерно извлечь елку. Я покажу свой промежуточный результат только с одним изображением, а окончательные результаты со всеми шестью.
Во-первых, я сопоставил пространство RGB с пространством Lab, что может повысить контраст красного в его b-канале:
Помимо функции в цветовом пространстве, я также использовал функцию текстуры, которая связана с соседством, а не с самим пикселем. Здесь я линейно объединил интенсивность от 3 исходных каналов (R, G, B). Причина, по которой я отформатировал этот способ, заключается в том, что у всех рождественских елок на изображении есть красные огни, а иногда и зеленая / иногда синяя подсветка.
Я применил локальный двоичный шаблон 3X3
I0
, использовал центральный пиксель в качестве порога и получил контраст, рассчитав разницу между средним значением интенсивности пикселя над порогом и средним значением под ним.Так как у меня всего 4 функции, я бы выбрал K = 5 в своем методе кластеризации. Код для k-средних показан ниже (он взят из курса машинного обучения доктора Эндрю Нга. Я проходил этот курс раньше и сам написал код в его задании по программированию).
Поскольку на моем компьютере программа работает очень медленно, я выполнил 3 итерации. Обычно критерием остановки является (i) время итерации не менее 10 или (ii) больше никаких изменений на центроидах. В моем тесте увеличение итерации может более точно дифференцировать фон (небо и дерево, небо и здание, ...), но не показало резких изменений в извлечении рождественской елки. Также обратите внимание, что k-means не защищен от случайной инициализации центроида, поэтому рекомендуется запускать программу несколько раз для сравнения.
После k-средних
I0
была выбрана область с максимальной интенсивностью . И для отслеживания границ использовалась трассировка границ. Для меня последняя рождественская елка - самая трудная для извлечения, поскольку контраст на этой картинке недостаточно высок, как в первых пяти. Другой проблемой в моем методе является то, что я использовалbwboundaries
функцию в Matlab для трассировки границы, но иногда внутренние границы также включаются, как вы можете наблюдать в 3-м, 5-м, 6-м результатах. Темная сторона в рождественских елках не только не может быть сгруппирована с освещенной стороной, но они также приводят к такому количеству прослеживания крошечных внутренних границ (imfill
не очень улучшается). Во всем моем алгоритме еще много места для улучшения.В некоторых публикациях указывается, что среднее смещение может быть более устойчивым, чем k-среднее, и многие алгоритмы, основанные на срезе графа , также очень конкурентоспособны при сложной сегментации границ. Я сам написал алгоритм среднего смещения, кажется, что лучше выделять области без достаточного количества света. Но среднее смещение немного чрезмерно сегментировано, и необходима некоторая стратегия слияния. Он работал даже намного медленнее, чем k-means на моем компьютере, боюсь, мне придется отказаться от него. Я с нетерпением жду возможности увидеть, что другие представят здесь отличные результаты с этими современными алгоритмами, упомянутыми выше.
Тем не менее, я всегда считаю, что выбор функции является ключевым компонентом в сегментации изображения. При правильном выборе функции, которая может максимизировать разницу между объектом и фоном, многие алгоритмы сегментации определенно будут работать. Различные алгоритмы могут улучшить результат с 1 до 10, но выбор функции может улучшить его с 0 до 1.
Счастливого Рождества !
источник
Это мой последний пост с использованием традиционных подходов к обработке изображений ...
Здесь я как-то объединяю два других моих предложения, добиваясь даже лучших результатов . На самом деле я не могу понять, как эти результаты могут быть лучше (особенно когда вы смотрите на маскированные изображения, которые создает метод).
В основе подхода лежит комбинация трех ключевых допущений :
С учетом этих допущений метод работает следующим образом:
Вот код в MATLAB (опять же, скрипт загружает все изображения jpg в текущей папке и, опять же, это далеко не оптимизированный кусок кода):
Результаты
Результаты высокого разрешения все еще доступны здесь!
Еще больше экспериментов с дополнительными изображениями можно найти здесь.
источник
Мои шаги решения:
Получить канал R (из RGB) - все операции, которые мы выполняем на этом канале:
Создать область интересов (ROI)
Порог R канала с минимальным значением 149 (верхнее правое изображение)
Расширить область результата (в центре слева изображение)
Обнаружение возраста в компьютерных роях. Дерево имеет много краев (среднее правое изображение)
Расширить результат
Эрозия с большим радиусом (нижнее левое изображение)
Выберите самый большой (по площади) объект - это область результата
ConvexHull (дерево является выпуклым многоугольником) (нижнее правое изображение)
Ограничительная рамка (нижнее правое изображение - grren box)
Шаг за шагом:
Первый результат - самый простой, но не в программном обеспечении с открытым исходным кодом - «Adaptive Vision Studio + Adaptive Vision Library»: это не открытый исходный код, а действительно быстрое создание прототипа:
Весь алгоритм обнаружения елки (11 блоков):
Следующий шаг. Мы хотим, чтобы решение с открытым исходным кодом. Измените фильтры AVL на фильтры OpenCV: здесь я сделал небольшие изменения, например, Edge Detection использует фильтр cvCanny, чтобы уважать то, как я умножил изображение области с изображением ребер, чтобы выбрать самый большой элемент, который я использовал findContours + contourArea, но идея та же.
https://www.youtube.com/watch?v=sfjB3MigLH0&index=1&list=UUpSRrkMHNHiLDXgylwhWNQQ
Я не могу показать изображения с промежуточными шагами сейчас, потому что я могу поставить только 2 ссылки.
Хорошо, теперь мы используем фильтры openSource, но это еще не весь открытый исходный код. Последний шаг - портирование на c ++ код. Я использовал OpenCV в версии 2.4.4
Результат окончательного кода C ++:
C ++ код также довольно короткий:
источник
std::max_element()
звонок? Я хотел бы также вознаграждать ваш ответ. Я думаю, что у меня есть GCC 4.2.... еще одно старомодное решение, основанное исключительно на обработке HSV :
Несколько слов об эвристике при обработке HSV:
Конечно, можно поэкспериментировать с множеством других возможностей для точной настройки этого подхода ...
Вот код MATLAB, который нужно сделать (предупреждение: код далеко не оптимизирован !!! Я использовал методы, не рекомендуемые для программирования на MATLAB, просто чтобы иметь возможность отслеживать что-либо в процессе - это может быть значительно оптимизировано):
Результаты:
В результатах я показываю замаскированное изображение и ограничивающий прямоугольник.
источник
Какой-то старомодный подход к обработке изображений ...
Идея основана на предположении, что изображения изображают освещенные деревья, как правило, на более темном и более гладком фоне (или в некоторых случаях на переднем плане). Освещенная область дерева является более «энергичной» и имеет более высокую интенсивность .
Процесс выглядит следующим образом:
То, что вы получаете, это бинарная маска и ограничивающая рамка для каждого изображения.
Вот результаты с использованием этой наивной техники:
Код на MATLAB выглядит следующим образом: Код запускается в папке с изображениями JPG. Загружает все изображения и возвращает обнаруженные результаты.
источник
Используя совершенно иной подход, чем я видел, я создал PHPскрипт, который обнаруживает рождественские елки по их огням. Результатом является всегда симметричный треугольник и, при необходимости, числовые значения, такие как угол ("упитанность") дерева.
Самой большой угрозой для этого алгоритма, очевидно, являются огни рядом (в большом количестве) или перед деревом (большая проблема до дальнейшей оптимизации). Редактировать (добавлено): Что он не может сделать: выяснить, есть ли рождественская елка или нет, найти несколько рождественских елок на одном изображении, правильно обнаружить рождественскую елку в центре Лас-Вегаса, обнаружить рождественские елки, которые сильно согнуты, перевернутый или срубленный ...;)
Различные этапы:
Объяснение маркировки:
Исходный код:
Картинки:
Бонус: немецкий Weihnachtsbaum, из Википедии http://commons.wikimedia.org/wiki/File:Weihnachtsbaum_R%C3%B6merberg.jpg
источник
Я использовал Python с OpenCV.
Мой алгоритм выглядит так:
Код:
Если я изменю ядро с (25,5) на (10,5), я получу более хорошие результаты на всех деревьях, кроме нижнего левого,
Мой алгоритм предполагает, что на дереве есть источники света, а в нижнем левом дереве верхняя часть имеет меньше света, чем остальные.
источник