2016-08-10 5 views
2

У меня есть изображение (или несколько сотен), которое необходимо проанализировать. Цель состоит в том, чтобы найти все черные пятна близко друг к другу.Как найти соседей в бинарном изображении с заданным горизонтальным и вертикальным расстоянием (Python)

Например, все черные пятна с горизонтальным расстоянием 160 пикселей и вертикальным 40 пикселем.

Just a small part of an image

Сейчас я просто смотрю на каждый пиксель, и если есть черный пиксель я называю рекурсивный метод, чтобы найти своих соседей (я могу отправить код тоже, если вы хотите)

It работает, но очень медленно. В настоящий момент скрипт работает примерно 3-4 минуты в зависимости от размера изображения.

Есть ли какой-нибудь простой/быстрый способ выполнить это (лучше всего будет использовать метод scikit-image, чтобы помочь здесь) Я использую Python.

Редактировать: Я пытался использовать scikit.measure.find_contours, теперь у меня есть массив с массивами, содержащими контуры черных пятен. Теперь мне нужно найти контуры в окрестности этих контуров.

ответ

1

Отказ от ответственности: Я не специалист с библиотекой изображений scikit на всех, но я решать подобные проблемы с помощью MATLAB, так что я искал эквивалентных методов в scikit, и я надеюсь, что мои результаты ниже помогут вам ,

Сначала вы можете использовать skimage.measure.label, который возвращает label_image, то есть изображение, где все связанные области обозначены одинаковым числом. Я считаю, что вы должны вызвать эту функцию с помощью background=255, потому что из вашего описания кажется, что фон в ваших изображениях является областью while (отсюда значение 255).

Это изображение, в котором background пикселям присваивается значение 0, а пикселям, составляющим каждое (подключенное) пятно, присваивается значение целочисленной метки, поэтому все пиксели одного пятна будут помечены значком значение 1, пиксели другого пятна будут помечены значком 2 и т. д. Ниже я буду ссылаться на «пятна» и «помеченные области» взаимозаменяемо.

После этого вы можете позвонить по номеру skimage.measure.regionprops, который берет на вход label_image, полученный на предыдущем шаге. Эта функция возвращает список RegionProperties (по одному для каждой помеченной области), который представляет собой сводку свойств помеченной области.

В зависимости от определения

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

существуют различные поля в RegionProperties, которые вы можете использовать, чтобы помочь решить вашу проблему:

  • bbox дает набор координат прямоугольника, который содержит, что меченый область,
  • centroid дает координаты центроидного пикселя этой помеченной области,
  • local_centroid дает вам центроид относительно ограничивающей рамки bbox

(Примечание есть также area и bbox_area свойства, которые вы можете использовать, чтобы решить, стоит ли выбрасывать очень маленькие пятна, которые Вы не могли бы быть заинтересованы в том, что сокращает время вычислений, когда дело доходит до сравнения близости от каждой пары пятна)

Если вы ищете грубое сравнение, то сопоставления centroid или local_centroid между каждой парой отмеченных областей может быть достаточно.

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

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

+0

Спасибо за ваш ответ. Собственность коордов точно соответствует мне. Теперь мне просто нужно получить вертикальное/горизонтальное расстояние между каждым пикселем. Но я думаю, что это не проблема. – Kuchen

2

Когда вы получаете координаты различных черных пятен, а не вычисляете все расстояния между всеми парами черных пикселей, вы можете использовать cKDTree (в scipy.spatial, http://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.cKDTree.html#scipy.spatial.cKDTree). Точный метод использования cKDTree зависит от вашего точного критерия (вы можете, например, использовать cKDTree.query_ball_tree, чтобы узнать, существует ли пара точек, принадлежащих двум различным меткам, с максимальным расстоянием, которое вы даете).

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

+0

Это довольно приятно получить расстояние от разных регионов, а также очень быстро по сравнению с моим собственным методом. Единственная проблема: я получаю только расстояние в радиусе. но расстояние нужно разным горизонтально и вертикально. Для примера 100px в x-оси и 40 px в оси y. Знаете ли вы способ быстро найти расстояние в одном направлении? – Kuchen

1

Если входное изображение бинарное, можно отделить интерес областей следующим образом:

  1. «растут» все регионы ожидаемым расстояния (на самом деле половина его, как вы растете с «обеих сторон пробела ") с binary_dilation, где structure является ядром (например, прямоугольником: http://scikit-image.org/docs/dev/api/skimage.morphology.html#skimage.morphology.rectangle), скажем, 20x80 пикселей;
  2. использовать полученную маску в качестве входного сигнала для skimage.measure.label для назначения различных значений для пикселей разных регионов;
  3. умножьте свое входное изображение на маску, созданную выше, до нулевых расширенных пикселей.

Вот результаты предлагаемого способа по вашему образу и kernel = rectange(5,5):

дилатационная бинарное изображение (выход из стадии 1):

enter image description here

Маркированный версия выше (выход шаг 2):

enter image description here

Умножение результаты (выход из шага 3):

enter image description here

+0

Большое спасибо. Это самый простой способ решить эту проблему. – Kuchen

Смежные вопросы