【问题标题】:Tranform HSV mask into a set of points将 HSV 掩码转换为一组点
【发布时间】:2019-01-19 04:31:50
【问题描述】:

我从图像创建了一个 HSV 掩码。结果如下:

我希望这个面具可以用一组点来表示。我最初的想法是使用Skimage Skeletonize创建一条线,然后使用滑动窗口计算局部均值来创建点。

但是,skeletonize 花费的时间太长。每帧需要0.4s。这对于视频处理来说不是一个好主意。

【问题讨论】:

  • 1.这与 HSV 无关。 2. 矢量化是一个缓慢的过程,因此除非您获得更多信息或场景限制(形状、方向复杂性),否则不要期望快速结果...

标签: python algorithm opencv image-processing video-processing


【解决方案1】:

你想要面具的所有 True 元素的点,还是只想要一个骨架?如果是前者..

import skimage as ski
from skimage import io
import numpy as np
mask = ski.io.imread('./mask.png')[:,:,0]/255
mask = mask.astype('bool')

s0,s1 = mask.shape # dimensions of mask 
a0,a1 = np.arange(s0),np.arange(s1) # make two 1d coordinate arrays
coords = np.array(np.meshgrid(a0,a1)).T # cartesian product into a coordinate matrix 
coords = coords[mask] # mask out the points of interest

如果是后者,您可以使用类似的方式快速获取蒙版中对象的起点和终点(从左到右)

start_mat = np.stack((np.roll(mask,1,axis=1),mask),-1)
start_mask = np.fromiter(map(lambda p: np.alltrue(p==np.array([False,True])),start_mat[mask]),dtype=bool)
starts = coords[start_mask]

end_mat = np.stack((np.roll(mask,-1,axis=1),mask),-1)
end_mask = np.fromiter(map(lambda p: np.alltrue(p==np.array([False,True])),end_mat[mask]),dtype=bool)
ends = coords[end_mask]

这将为您提供对象的粗略轮廓。轮廓点在图形斜率为 0 的任何地方都将丢失。您可能必须为这些区域考虑垂直差异方案。同样的想法也适用于np.roll(...,axis=0)。您可以将滚动行的唯一点与滚动列的点连接起来,以获得完整的轮廓。

平均正确的对来得到骨架并不容易。

这是一个最终的大纲。你绝对可以让这个速度超过 0.4 秒:

【讨论】:

    【解决方案2】:

    一个简单的 For 循环不能工作吗?

    扫描位图的每个“跨”行以查找...

    • X 位置 from BlackWhite = 新 start point

    • 现在也在同一扫描行中寻找新的 X-pos:
      from WhiteBlack 相遇 = new end point .

    • 要么将点放在起点/终点以实现“轮廓”效果,
      要么将点放在“中心”效果 dot.x = (end_point - start_point) / 2

    【讨论】:

    • 我相信把点放在中心不像这个 VC。想想 OP 提供的图像上的“手臂”与“身体”相交会发生什么但是如果你能想到一种从起点和终点获取骨架的方法,我展示了一种比 for 循环更快的方法来获取我的答案中的起点和终点
    • 此外,此轮廓检测无法给出掩码中图形斜率为 0 的点。在这些情况下,必须在 y 方向上有所不同。
    猜你喜欢
    • 2021-09-18
    • 2022-10-18
    • 2020-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-15
    • 2017-06-29
    相关资源
    最近更新 更多