使用Python、Numpy和Scikit image/OpenCV根据分水岭线的长度合并图像段

使用Python、Numpy和Scikit image/OpenCV根据分水岭线的长度合并图像段,python,numpy,opencv,image-segmentation,scikit-image,Python,Numpy,Opencv,Image Segmentation,Scikit Image,我正在研究一种基于分水岭的分割算法来分割荧光图像,例如: 因此,我获得了一个Numpy数组,每个片段都有标签。如果荧光图像中的相应区域之间有足够大的强度衰减,则这些区域由分水岭线分隔。对于非常大的强度衰减,它们通过简单的阈值完全分离。上图的结果如下: 我的算法在绝大多数情况下都表现良好。然而,它有时有一个轻微的倾向,以超期。如上图所示: 由于这些情况很难通过进一步研究基于强度的分割本身来改善(我冒着破坏其他东西的风险),因此我希望根据它们之间的分水岭线的长度以及上面和下面两个分段的平均最大

我正在研究一种基于分水岭的分割算法来分割荧光图像,例如:

因此,我获得了一个Numpy数组,每个片段都有标签。如果荧光图像中的相应区域之间有足够大的强度衰减,则这些区域由分水岭线分隔。对于非常大的强度衰减,它们通过简单的阈值完全分离。上图的结果如下:

我的算法在绝大多数情况下都表现良好。然而,它有时有一个轻微的倾向,以超期。如上图所示:

由于这些情况很难通过进一步研究基于强度的分割本身来改善(我冒着破坏其他东西的风险),因此我希望根据它们之间的分水岭线的长度以及上面和下面两个分段的平均最大宽度,有选择地合并相邻分段。 我知道在逐像素的基础上我必须做什么:

  • 查找在其直接邻域中具有两个不同标签值的像素。为每个段对分别存储这些像素(带有相应的段标签)
  • 计算每对相邻线段的像素数,以获得分水岭线的长度
  • 计算相邻管段的最大宽度(水平方向为简单起见)
  • 如果分水岭线长于两段平均宽度的给定阈值分数(用户定义),则合并相邻段。我可以通过将标签转换为二进制掩码,在适用的情况下使用存储的像素填充分水岭线,并重新标记二进制掩码来实现这一点

  • 因为在Python中,在单个像素上迭代通常很慢,所以我不确定如何为此编写性能代码。因此,我正在寻找关于如何使用Numpy和Skimage实现这一点的建议(OpenCV也是一个选项)。

    您没有提供如何获得初始细分。尽管如此,我认为改进分水岭线可以解决您的问题,这可以在分水岭层次结构框架中完成

    我通过图像补码指定分水岭的初始顺序,并使用另一个属性(体积)重新计算其分水岭线

    您描述的强度下降和面积是体积属性,您可以通过层次中的阈值来控制分割

    这是一个工作示例:

    导入cv2
    将numpy作为np导入
    进口希格拉汞
    从skimage.morphology导入移除\u小对象,标记
    将matplotlib.pyplot作为plt导入
    def main():
    img_path=“fig.png”
    img=cv2.imread(img\u路径)
    img=img[:,:,0]。复制()
    img=img.max()-img
    尺寸=图像形状[:2]
    graph=hg.get_4_邻接图(大小)
    边权重=hg.weight\u图(图,img,hg.WeightFunction.mean)
    树,高度=hg。准平坦区域层次结构(图,边权重)
    属性=hg.属性_体积(树木、高度)
    显著性=hg.显著性(树,属性)
    #看看这个:)
    #grid=hg.图4邻接图2哈利姆斯基(图,显著性)
    #plt.imshow(网格)
    #plt.show()
    属性方法=np.平均值(显著性)/4#任意
    面积法=500#任意
    分段=hg.标签化\u水平\u从\u阈值(树、属性、属性方法)
    分段=标签(删除小对象(分段、区域方法))
    plt.imshow(细分市场)
    plt.show()
    如果名称=“\uuuuu main\uuuuuuuu”:
    main()
    
    这就是结果


    您没有提供如何获得初始细分。尽管如此,我认为改进分水岭线可以解决您的问题,这可以在分水岭层次结构框架中完成

    我通过图像补码指定分水岭的初始顺序,并使用另一个属性(体积)重新计算其分水岭线

    您描述的强度下降和面积是体积属性,您可以通过层次中的阈值来控制分割

    这是一个工作示例:

    导入cv2
    将numpy作为np导入
    进口希格拉汞
    从skimage.morphology导入移除\u小对象,标记
    将matplotlib.pyplot作为plt导入
    def main():
    img_path=“fig.png”
    img=cv2.imread(img\u路径)
    img=img[:,:,0]。复制()
    img=img.max()-img
    尺寸=图像形状[:2]
    graph=hg.get_4_邻接图(大小)
    边权重=hg.weight\u图(图,img,hg.WeightFunction.mean)
    树,高度=hg。准平坦区域层次结构(图,边权重)
    属性=hg.属性_体积(树木、高度)
    显著性=hg.显著性(树,属性)
    #看看这个:)
    #grid=hg.图4邻接图2哈利姆斯基(图,显著性)
    #plt.imshow(网格)
    #plt.show()
    属性方法=np.平均值(显著性)/4#任意
    面积法=500#任意
    分段=hg.标签化\u水平\u从\u阈值(树、属性、属性方法)
    分段=标签(删除小对象(分段、区域方法))
    plt.imshow(细分市场)
    plt.show()
    如果名称=“\uuuuu main\uuuuuuuu”:
    main()
    
    这就是结果


    在您提到过过度分割的地方,我可以在初始图像中看到,在这段时间内,亮度较低,因此我认为不会发生过度分割。但是,如果它正在发生,你能不能也塑造分水岭代码。我们可能也会找到解决的办法。在你提到过过度分割的地方,我可以在最初的图像中看到,在那之间有一些低亮度,因此我不认为过度分割正在发生。但是,如果它正在发生,你能不能也塑造分水岭代码。我们也可以在这方面找到解决办法。