Python:二进制2D数组中的轮廓

Python:二进制2D数组中的轮廓,python,numpy,contour,Python,Numpy,Contour,我想用一种最简单的方法(不需要对图像的边界进行百万次检查)从二进制2D数组中获得轮廓,宽度为n个像素,进入正区域 例如: 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], ]) 用于呼叫,例如宽度=1。如果img[i,j

我想用一种最简单的方法(不需要对图像的边界进行百万次检查)从二进制2D数组中获得轮廓,宽度为n个像素,进入正区域

例如:

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],
               ])
用于呼叫,例如宽度=1。如果img[i,j]==1且任何相邻(img[i+1,j]、img[i-1,j]、img[i,j-1]、img[i,j+1])为0,则像素为正

或使用宽度=2的方式呼叫。宽度=1的所有像素以及满足img[i,j]==1且距离2个索引(欧几里德距离)存在值为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],
            ]) 
谢谢你的帮助

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

产出:

df:

轮廓:


希望这有帮助我想你要找的是

给定一个二进制数组
img
,这将生成一个
0
255
的数组,因此需要除以255。在我看来,width=2的过滤器是通过再次应用width=1的过滤器获得的,因此在最后,您的函数可能看起来像

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

这不是这个问题的确切答案,但分享了一个简单的方法来绘制图像轮廓;对于那些正在寻找的人来说

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)
检查此测试输出:

我在为此工作时写了这个解决方案

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)