Python:二进制二维数组中的轮廓
Python: Contour in binary 2D array
我想以最简单的方式(无需对图像边界进行百万次检查)从二进制二维数组中获取轮廓,其中 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.
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. width = 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:
轮廓:
希望这对您有所帮助
我想你要找的是
scipy.misc.imfilter(img, "find_edges")
.
给定一个二进制数组 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)
检查这个测试输出:
我在为此 PR 工作时写了这个解决方案。
我想以最简单的方式(无需对图像边界进行百万次检查)从二进制二维数组中获取轮廓,其中 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.
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. width = 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:
轮廓:
希望这对您有所帮助
我想你要找的是
scipy.misc.imfilter(img, "find_edges")
.
给定一个二进制数组 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)
检查这个测试输出:
我在为此 PR 工作时写了这个解决方案。