python - 在图像中标记边缘
问题描述
我写了一个函数来标记像素级标记图像中对象的边缘:
import numpy as np
def mark_edges(image, marker):
axes = len(image.shape)
edges = []
for i in range(axes):
shiftright = np.greater(image, np.roll(image, 1, axis=i))
shiftleft = np.greater(image, np.roll(image, -1, axis=i))
idx = np.where(shiftright != shiftleft)
edges.append(idx)
for idx in edges:
image[idx] = marker
return image
对于孤立的对象,这很好,因为每个标签都大于背景:
a = np.zeros(40).reshape(5,8)
a[1:4, 1:7] = 2
print(mark_edges(a, 99))
[[ 0. 0. 0. 0. 0. 0. 0. 0.]
[ 0. 99. 99. 99. 99. 99. 99. 0.]
[ 0. 99. 2. 2. 2. 2. 99. 0.]
[ 0. 99. 99. 99. 99. 99. 99. 0.]
[ 0. 0. 0. 0. 0. 0. 0. 0.]]
但是,如果两个不同标记的对象彼此相邻,则结果会略有不同:
b = np.zeros(40).reshape(5,8)
b[1:4, 1:4] = 2
b[1:4, 4:7] = 4
print(mark_edges(b, 99))
[[ 0. 0. 0. 0. 0. 0. 0. 0.]
[ 0. 99. 99. 99. 99. 99. 99. 0.]
[ 0. 99. 2. 2. 99. 4. 99. 0.]
[ 0. 99. 99. 99. 99. 99. 99. 0.]
[ 0. 0. 0. 0. 0. 0. 0. 0.]]
理想情况下,位置 (2,3) 应该有另一个标记。我必须接受这种不准确还是有办法解决?
解决方案
而不是np.greater
,使用np.not_equal
. 这将导致所有区域的边缘都被标记,包括背景区域。
接下来,删除背景区域的边缘。
在下面的代码中,我使用“蒙版图像”而不是边缘像素列表。我发现这更容易使用,而且效率也很高。
import numpy as np
def mark_edges(image, marker):
axes = len(image.shape)
mask = np.zeros(image.shape, dtype=bool)
for i in range(axes):
shiftright = np.not_equal(image, np.roll(image, 1, axis=i))
shiftleft = np.not_equal(image, np.roll(image, -1, axis=i))
mask |= shiftright != shiftleft
mask[image==0] = 0
image[mask] = marker
return image
问题中图像b
的输出:
>>> b = np.zeros(40).reshape(5,8)
>>> b[1:4, 1:4] = 2
>>> b[1:4, 4:7] = 4
>>> print(mark_edges(b, 99))
[[ 0. 0. 0. 0. 0. 0. 0. 0.]
[ 0. 99. 99. 99. 99. 99. 99. 0.]
[ 0. 99. 2. 99. 99. 4. 99. 0.]
[ 0. 99. 99. 99. 99. 99. 99. 0.]
[ 0. 0. 0. 0. 0. 0. 0. 0.]]
推荐阅读
- excel - 在 Mac 中的 Microsoft Excel 中更改电子表格中活动单元格的颜色和/或宽度
- jenkins - 詹金斯:触发新工作后如何清理临时文件夹?
- azure - Azure Blob 容器 ResourceNotFound 错误
- python - 加快匹配字符串python
- c# - AutoMapper 不更新嵌套集合
- javascript - 从数组创建对象数组
- python-3.x - 如何在python的不同类中使用另一个类方法值?
- google-sheets - 从不同的表中复制多列并交替粘贴
- sql - PostgreSQL:使用视图和触发器在多个表中插入元组
- python - 如何从 regex.split() 获得正确的输出?