简体   繁体   English

Python:二进制二维数组中的轮廓

[英]Python: Contour in binary 2D array

I would like to in a simplest possible way (without million checking of boundaries of image) get the contour, with the width of n pixels going into the positive area, from the binary 2D array.我想以最简单的方式(无需对图像边界进行百万次检查)从二进制 2D 数组中获取轮廓,其中 n 个像素的宽度进入正区域。

Example:例子:

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

For calling with eg width = 1. Pixels are positive if img[i,j]==1 and any neighbour (img[i+1,j], img[i-1,j], img[i,j-1], img[i,j+1]) is 0.例如宽度 = 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],
            ])

or calling with eg width = 2. All pixels from width = 1 are positive as well as the ones that satisfy img[i, j] == 1 and for which with 2 indices away (euclidian distance) exists a pixel with value 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],
            ]) 

Thank you for your help.感谢您的帮助。

Not the exact answer for this question, but sharing a simple way to draw contours in images;不是这个问题的确切答案,而是分享一种在图像中绘制轮廓的简单方法; for folks that are just looking for that.对于那些只是在寻找那个的人。

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)

Check this test output:检查此测试输出: 在此处输入图片说明

I wrote this solution whilst working for this PR .我在为这个PR工作时写了这个解决方案。

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

outputs:输出:

df: df:

在此处输入图片说明

contour:轮廓:

在此处输入图片说明

hope this helps希望这可以帮助

I think what you're looking for is scipy.misc.imfilter(img, "find_edges") .我想你要找的是scipy.misc.imfilter(img, "find_edges")

Given a binary array img this will produce an array with 0 and 255 , so you'll need to divide by 255. As I see it, the filter with width=2 is obtained by applying the filter with width=1 another time, so at the end your function could look like给定一个二进制数组img这将产生一个包含0255的数组,所以你需要除以 255。正如我所见,宽度=2 的过滤器是通过再次应用宽度=1 的过滤器获得的,所以最后你的函数可能看起来像

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM