2017-01-27 4 views
1

Ich möchte auf eine möglichst einfache Art und Weise (ohne Million Überprüfung der Bildgrenzen) die Kontur, mit der Breite von n Pixeln in den positiven Bereich, aus dem binären 2D-Array holen.Python: Kontur im binären 2D-Array

Beispiel:

img = np.array([ 
       [0, 0, 0, 1, 1, 1, 1, 1, 0], 
       [0, 1, 1, 1, 1, 1, 1, 1, 1], 
       [0, 1, 1, 1, 0, 0, 0, 0, 0], 
       ]) 

für den Aufruf mit z.B. Breite = 1. Pixel sind positiv, wenn img [i, j] == 1 und irgendein Nachbar (img [i + 1, j], img [i-1, j], img [i, j-1], img [ i, j + 1]) ist 0.

contour1 = get_countor(img, width = 1) 
contour1 = ([ 
       [0, 0, 0, 1, 0, 0, 0, 1, 0], 
       [0, 1, 1, 0, 1, 1, 1, 1, 1], 
       [0, 1, 0, 1, 0, 0, 0, 0, 0], 
      ]) 

oder mit z width = 2. Alle Pixel ab Breite = 1 sind positiv, ebenso wie diejenigen, die img [i, j] == 1 erfüllen und für die bei 2 Indizes (euklidischer Abstand) ein Pixel mit dem Wert 0 existiert.

contour2 = get_countor(img, width = 2) 
contour2 = ([ 
       [0, 0, 0, 1, 1, 1, 1, 1, 0], 
       [0, 1, 1, 1, 1, 1, 1, 1, 1], 
       [0, 1, 1, 1, 0, 0, 0, 0, 0], 
      ]) 

Vielen Dank für Ihre Hilfe.

Antwort

0
import numpy as np 
import pandas as pd 
import random 

df = pd.DataFrame([], columns=[0,1,2,3,4,5,6,7,8,9]) 

for i in np.arange(10): 
    df.loc[len(df)] = np.random.randint(0,2,10) 

df = df.astype(bool) 

contour = df & ((df-df.shift(-1, axis=0).fillna(1))|(df-df.shift(1,axis=0).fillna(1))|(df-df.shift(-1,axis=1).fillna(1))|(df-df.shift(1,axis=1).fillna(1))) 

Ausgänge:

df:

enter image description here

Kontur:

enter image description here

hoffen, dass diese hilft

0

Ich denke, was Sie suchen, ist scipy.misc.imfilter(img, "find_edges").

Bei einem binären Array img dies ein Array mit 0 und 255 produzieren wird, so dass Sie durch 255 zu teilen brauchen, wie ich es sehe, die Filter mit einer Breite 2 = durch Anwendung des Filters mit einer Breite erhalten wird, = 1 ein anderes Mal, so dass am Ende könnte Ihre Funktion aussieht

def get_countor(img, width = 1): 
    for i in range(width): 
     img = scipy.misc.imfilter(img, "find_edges")/255 
    return img 
0

nicht die genaue Antwort auf diese Frage, aber eine einfache Art und Weise teilt Konturen in Bildern zu ziehen; für Leute, die nur danach suchen.

from PIL import Image 
from PIL import ImageFilter 
import numpy as np 


def draw_contour(img, mask, contour_width, contour_color): 
    """Draw contour on a pillow image from a numpy 2D mask.""" 
    contour = Image.fromarray(mask) 
    contour = contour.resize(img.size) 
    contour = contour.filter(ImageFilter.FIND_EDGES) 
    contour = np.array(contour) 

    # make sure borders are not drawn 
    contour[[0, -1], :] = 0 
    contour[:, [0, -1]] = 0 

    # use a gaussian to define the contour width 
    radius = contour_width/10 
    contour = Image.fromarray(contour) 
    contour = contour.filter(ImageFilter.GaussianBlur(radius=radius)) 
    contour = np.array(contour) > 0 
    contour = np.dstack((contour, contour, contour)) 

    # color the contour 
    ret = np.array(img) * np.invert(contour) 
    if contour_color != 'black': 
     color = Image.new(img.mode, img.size, contour_color) 
     ret += np.array(color) * contour 

    return Image.fromarray(ret) 

prüft diesen Testausgang: enter image description here

Ich schrieb diese Lösung während der Arbeit für diesen PR.