Scipy метка эрозии - PullRequest
       6

Scipy метка эрозии

4 голосов
/ 20 декабря 2011

Как сохранить кольцо пикселей вокруг помеченных областей в массиве пустышек?

В простом случае я бы вычел эрозию.Такой подход не работает, когда ярлыки соприкасаются.Как я могу получить B от A?

A = array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
           [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
           [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
           [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
           [0, 0, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0],
           [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
           [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
           [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
           [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

B = array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
           [0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0],
           [0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0],
           [0, 0, 2, 0, 0, 2, 2, 2, 2, 0, 0, 0],
           [0, 0, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0],
           [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0],
           [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0],
           [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0],
           [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

Я работаю с большими массивами с множеством меток, поэтому раздельные эрозии на каждой метке не вариант.

1 Ответ

2 голосов
/ 21 декабря 2011

Новый ответ

На самом деле, я просто подумал о лучшем способе:

B = A * (np.abs(scipy.ndimage.laplace(A)) > 0)

В качестве полного примера:

import numpy as np
import scipy.ndimage

A = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
              [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
              [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
              [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
              [0, 0, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0],
              [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
              [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
              [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
              [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
              [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

B = A * (np.abs(scipy.ndimage.laplace(A)) > 0)

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

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

B = scipy.ndimage.laplace(A)
B = np.abs(B, B) # Preform abs in-place
B /= B  # This will produce a divide by zero warning that you can safely ignore
B *= A  

Эта версия намного более многословна, но должна использовать намного меньше памяти.

Старый ответ

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

Однако, как вы упомянули, можно сделать несколько отдельных эрозий.

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

Например:

import numpy as np
import scipy.ndimage

A = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
              [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
              [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
              [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
              [0, 0, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0],
              [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
              [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
              [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
              [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
              [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

regions = scipy.ndimage.find_objects(A)

mask = np.zeros_like(A).astype(np.bool)

for val, region in enumerate(regions, start=1):
    if region is not None:
        subregion = A[region]
        mask[region] = scipy.ndimage.binary_erosion(subregion == val)

B = A.copy()
B[mask] = 0

Это дает:

array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0],
       [0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0],
       [0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0],
       [0, 0, 2, 0, 0, 2, 2, 2, 2, 0, 0, 0],
       [0, 0, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0],
       [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0],
       [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0],
       [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...