2017-01-27 5 views
1

Я хотел бы простейшим способом (без миллиона проверок границ изображения) получить контур с шириной n пикселей, идущих в положительную область, из двоичного 2D-массива.Python: Контур в двоичном двумерном массиве

Пример:

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], 
       ]) 

Для вызова, например, с width = 1. Пиксели положительны, если img [i, j] == 1 и любой сосед (img [i + 1, j], img [i-1, j], img [i, j-1], img [ i, j + 1]) равно 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], 
      ]) 

или вызов, например, width = 2. Все пиксели с шириной = 1 являются положительными, а также те, которые удовлетворяют img [i, j] == 1 и для которых с двумя индексами (эвклидово расстояние) существует пиксель со значением 0.

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], 
      ]) 

Благодарим за помощь.

ответ

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))) 

выходы:

ДФ:

enter image description here

контур:

enter image description here

надежда эта помогает

0

Я думаю, что вы ищете scipy.misc.imfilter(img, "find_edges").

Учитывая бинарный массив img это будет производить массив с 0 и 255, так что вам нужно разделить на 255. Как я понимаю, фильтр с шириной = 2 получается путем применения фильтра с шириной = 1 в другой раз, так что в конце концов ваша функция может выглядеть

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

не точный ответ на этот вопрос, но обмен простой способ рисования контуров изображений; для людей, которые просто ищут это.

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) 

Проверить этот тест выход: enter image description here

Я написал это решение во время работы для этого PR.

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