2015-03-25 7 views
5

Mam tablicy numpy które chcesz segmentu w odrębnych obszarach o unikalnych identyfikatorów, który wygląda mniej więcej tak:Segmentowanie tablicy Pythona w unikalne regiony połączone przez pojedynczą komórkę lub mniej?

Example array

Zazwyczaj na coś takiego użyłbym scipy.ndimage.label generować unikalne identyfikatory dla dyskretnych obiektów typu blob, ale w tym przypadku mam kilka bardzo dużych obszarów ciągłych, które również chcę podzielić na mniejsze, unikalne regiony, najlepiej gdy są one połączone tylko z sąsiadami przez połączenie o szerokości 1 komórki. Aby zilustrować, oto tablica próbki, wynik uzyskać podczas uruchamiania scipy.ndimage.label i mój pożądany rezultat:

import numpy as np 
import scipy.ndimage as ndimage 
import matplotlib.pyplot as plt 

# Sample study area array 
example_array = np.array([[0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0], 
          [0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1], 
          [0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1], 
          [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0], 
          [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1], 
          [1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1], 
          [1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1], 
          [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0], 
          [1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0], 
          [1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0], 
          [1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0], 
          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]) 

# Identify discrete regions and assign unique IDs 
current_output, num_ids = ndimage.label(example_array, structure=np.ones((3,3))) 

# Plot outputs 
plt.imshow(example_array, cmap="spectral", interpolation='nearest') 
plt.imshow(current_output, cmap="spectral", interpolation='nearest') 

Outputs and expected outputs

Szczególną numerację i podział komórek nie jest wtórne ; wszystko, co przypomina ostatni wykres powyżej, zrobi. Moja najlepsza próba dotąd w użyciu morfologicznego przetwarzania obrazu do pierwszego obniżają moją tablicę, uruchom scipy.ndimage.label a następnie rozszerzają się, ale nie ma to niefortunny efekt uboczny eliminując wszystkie regiony pojedynczej komórki lub cienkich obiektów liniowych (z których jest wiele).

Bardzo doceniam wszelkie myśli!

+1

możliwe jest najpierw określić obszary jednokomórkowe i cienkie elementy liniowe i erozji i rozszerzają? –

+0

Dzięki za przypomnienie mi tom10. Poprzednia odpowiedź została odpowiednio zaktualizowana! Julien: które mogą działać, ale można zobaczyć problemy z długich, cienkich obszarów wystających z krawędzi dużych obszarów, które powinny mieć ten sam niepowtarzalny identyfikator, ale jest oddzielona, ​​gdy usuwa się przed dylatacji-erozji. Zdecydowanie warte zobaczenia! –

Odpowiedz

4

Najprostszym rozwiązaniem może być zastosowanie następujące jądra ujmujący przed etykietowania scipy („?” 2,2, co do pochodzenia i może być 0 lub 1):

IF |? 1 ?| OR |? 0 ?| THEN origin(x,y) == 0 
    |0 1 0| |1 1 1| 
    |? 1 ?| |? 0 ?| 

REALIZACJA:

import numpy as np 
import scipy.ndimage as ndimage 
import matplotlib.pyplot as plt 

# Sample study area array 
example_array = np.array([[0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0], 
          [0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1], 
          [0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1], 
          [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0], 
          [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1], 
          [1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1], 
          [1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1], 
          [1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0], 
          [1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0], 
          [1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0], 
          [1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0], 
          [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]) 

# Get array shape 
row_count, column_count = example_array.shape 

# Iterate through kernel origins 
for (x,y), value in np.ndenumerate(example_array): 

    # Skip first and last rows and columns because kernel would be out of bounds 
    if not (x == 0 
     or x == row_count-1 
     or y == 0 
     or y == column_count-1): 

     # Extract kernel 
     kernel = example_array[x-1:x+2, y-1:y+2] 

     # Apply IF |? 1 ?| OR |? 0 ?| THEN origin(x,y) == 0 
     #   |0 1 0| |1 1 1| 
     #   |? 1 ?| |? 0 ?| 
     if ((kernel[1,0:3]).all() == 1 and kernel[0,1] == 0 and kernel[2,1] == 0 
      or (kernel[0:3,1]).all() == 1 and kernel[1,0] == 0 and kernel[1,2] == 0): 
      example_array[x,y] = 0 

# Identify discrete regions and assign unique IDs 
current_output, num_ids = ndimage.label(example_array, structure=np.ones((3,3))) 

# Plot outputs 
plt.imshow(example_array, cmap="spectral", interpolation='nearest') 
plt.imshow(current_output, cmap="spectral", interpolation='nearest') 

WYNIK: enter image description here

+0

Witam trzeciorzędny, dziękuję za odpowiedź. Czy możesz dać mi trochę więcej informacji na temat tego, w jaki sposób mogę to wdrożyć? –

+1

@Domentarz: Doceniam wysiłek, ale niestety nie osiągnęło to rezultatu, którego potrzebuję, z brakującymi danymi siedliskowymi pomiędzy oznaczonymi regionami, gdzie zamiast tego te komórki powinny być sklasyfikowane jako jeden lub drugi identyfikator (patrz "pożądany wynik") w powyższym pytaniu). –

Powiązane problemy