我编写了一个函数来标记像素级标记图像中对象的边缘:
irb(main):004:0> @m.meetings.future.count()
(16.7ms) SELECT COUNT(*) FROM `meetings` WHERE `meetings`.`type` IN ('Org::Happenings::ScheduledHappening', 'Org::Happenings::RoomBooking', 'Org::Happenings::Meeting', 'Org::Happenings::Unavailability', 'Meeting', 'Unavailability') AND (start_time is not NULL and end_time > '2018-08-16 15:35:09.609774')
=> 3422
对于隔离的对象,这很好用,因为每个标签都大于背景:
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.]]
理想情况下,位置(2,3)应该有另一个标记。我必须接受这种不准确性吗?还是有办法解决?
答案 0 :(得分:0)
使用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.]]