bwmorph 的 Python 等效项

2023-12-07

我仍在用 Python 编写指纹图像预处理器。我在 MATLAB 中看到有一个特殊的函数可以消除 H 中断和杂散:

bwmorph(a , 'hbreak')
bwmorph(a , 'spur')

我搜索了 scikit、OpenCV 等,但找不到这两种用法的等效项bwmorph。有人可以指出我正确的方向还是我必须实施自己的方向?


2017年10月编辑

skimage 模块现在至少有 2 个选项:骨架化 and thin

比较示例

from skimage.morphology import thin, skeletonize
import numpy as np
import matplotlib.pyplot as plt

square = np.zeros((7, 7), dtype=np.uint8)
square[1:-1, 2:-2] = 1
square[0, 1] =  1
thinned = thin(square)
skel = skeletonize(square)

f, ax = plt.subplots(2, 2)
ax[0,0].imshow(square)
ax[0,0].set_title('original')
ax[0,0].get_xaxis().set_visible(False)
ax[0,1].axis('off')
ax[1,0].imshow(thinned)
ax[1,0].set_title('morphology.thin')
ax[1,1].imshow(skel)
ax[1,1].set_title('morphology.skeletonize')
plt.show()

example of skimage.morphology.thin/skeletonize

原帖

我在 joefutrelle 上找到了这个解决方案github.

它(视觉上)似乎给出了与 Matlab 版本类似的结果。

希望有帮助!

Edit:

正如评论中指出的那样,我将扩展我的最初帖子,因为提到的链接可能会发生变化:

在 Matlab 中寻找 Python 中 bwmorph 的替代品时,我偶然发现了以下代码乔·富特雷尔在 Github 上(在这篇文章的末尾,因为它很长)。

我已经找到了两种方法来将其实现到我的脚本中(我是初学者,我确信有更好的方法!):

1)将整个代码复制到脚本中,然后调用该函数(但这会使脚本更难阅读)

2)将代码复制到新的Python文件“foo”中并保存。现在将其复制到 Python\Lib(例如 C:\Program Files\Python35\Lib)文件夹中。在原始脚本中,您可以通过编写以下内容来调用该函数:

from foo import bwmorph_thin

然后,您将向该函数提供二进制图像:

Original

skeleton = bwmorph_thin(foo_image, n_iter = math.inf)

Skeleton

import numpy as np
from scipy import ndimage as ndi

# lookup tables for bwmorph_thin

G123_LUT = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1,
       0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0,
       1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
       0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1,
       0, 0, 0], dtype=np.bool)

G123P_LUT = np.array([0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
       1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0,
       0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
       1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1,
       0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0], dtype=np.bool)

def bwmorph_thin(image, n_iter=None):
    """
    Perform morphological thinning of a binary image

    Parameters
    ----------
    image : binary (M, N) ndarray
        The image to be thinned.

    n_iter : int, number of iterations, optional
        Regardless of the value of this parameter, the thinned image
        is returned immediately if an iteration produces no change.
        If this parameter is specified it thus sets an upper bound on
        the number of iterations performed.

    Returns
    -------
    out : ndarray of bools
        Thinned image.

    See also
    --------
    skeletonize

    Notes
    -----
    This algorithm [1]_ works by making multiple passes over the image,
    removing pixels matching a set of criteria designed to thin
    connected regions while preserving eight-connected components and
    2 x 2 squares [2]_. In each of the two sub-iterations the algorithm
    correlates the intermediate skeleton image with a neighborhood mask,
    then looks up each neighborhood in a lookup table indicating whether
    the central pixel should be deleted in that sub-iteration.

    References
    ----------
    .. [1] Z. Guo and R. W. Hall, "Parallel thinning with
           two-subiteration algorithms," Comm. ACM, vol. 32, no. 3,
           pp. 359-373, 1989.
    .. [2] Lam, L., Seong-Whan Lee, and Ching Y. Suen, "Thinning
           Methodologies-A Comprehensive Survey," IEEE Transactions on
           Pattern Analysis and Machine Intelligence, Vol 14, No. 9,
           September 1992, p. 879

    Examples
    --------
    >>> square = np.zeros((7, 7), dtype=np.uint8)
    >>> square[1:-1, 2:-2] = 1
    >>> square[0,1] =  1
    >>> square
    array([[0, 1, 0, 0, 0, 0, 0],
           [0, 0, 1, 1, 1, 0, 0],
           [0, 0, 1, 1, 1, 0, 0],
           [0, 0, 1, 1, 1, 0, 0],
           [0, 0, 1, 1, 1, 0, 0],
           [0, 0, 1, 1, 1, 0, 0],
           [0, 0, 0, 0, 0, 0, 0]], dtype=uint8)
    >>> skel = bwmorph_thin(square)
    >>> skel.astype(np.uint8)
    array([[0, 1, 0, 0, 0, 0, 0],
           [0, 0, 1, 0, 0, 0, 0],
           [0, 0, 0, 1, 0, 0, 0],
           [0, 0, 0, 1, 0, 0, 0],
           [0, 0, 0, 1, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0]], dtype=uint8)
    """
    # check parameters
    if n_iter is None:
        n = -1
    elif n_iter <= 0:
        raise ValueError('n_iter must be > 0')
    else:
        n = n_iter

    # check that we have a 2d binary image, and convert it
    # to uint8
    skel = np.array(image).astype(np.uint8)

    if skel.ndim != 2:
        raise ValueError('2D array required')
    if not np.all(np.in1d(image.flat,(0,1))):
        raise ValueError('Image contains values other than 0 and 1')

    # neighborhood mask
    mask = np.array([[ 8,  4,  2],
                     [16,  0,  1],
                     [32, 64,128]],dtype=np.uint8)

    # iterate either 1) indefinitely or 2) up to iteration limit
    while n != 0:
        before = np.sum(skel) # count points before thinning

        # for each subiteration
        for lut in [G123_LUT, G123P_LUT]:
            # correlate image with neighborhood mask
            N = ndi.correlate(skel, mask, mode='constant')
            # take deletion decision from this subiteration's LUT
            D = np.take(lut, N)
            # perform deletion
            skel[D] = 0

        after = np.sum(skel) # coint points after thinning

        if before == after:
            # iteration had no effect: finish
            break

        # count down to iteration limit (or endlessly negative)
        n -= 1

    return skel.astype(np.bool)

"""
# here's how to make the LUTs

def nabe(n):
    return np.array([n>>i&1 for i in range(0,9)]).astype(np.bool)

def hood(n):
    return np.take(nabe(n), np.array([[3, 2, 1],
                                      [4, 8, 0],
                                      [5, 6, 7]]))
def G1(n):
    s = 0
    bits = nabe(n)
    for i in (0,2,4,6):
        if not(bits[i]) and (bits[i+1] or bits[(i+2) % 8]):
            s += 1
    return s==1

g1_lut = np.array([G1(n) for n in range(256)])

def G2(n):
    n1, n2 = 0, 0
    bits = nabe(n)
    for k in (1,3,5,7):
        if bits[k] or bits[k-1]:
            n1 += 1
        if bits[k] or bits[(k+1) % 8]:
            n2 += 1
    return min(n1,n2) in [2,3]

g2_lut = np.array([G2(n) for n in range(256)])

g12_lut = g1_lut & g2_lut

def G3(n):
    bits = nabe(n)
    return not((bits[1] or bits[2] or not(bits[7])) and bits[0])

def G3p(n):
    bits = nabe(n)
    return not((bits[5] or bits[6] or not(bits[3])) and bits[4])

g3_lut = np.array([G3(n) for n in range(256)])
g3p_lut = np.array([G3p(n) for n in range(256)])

g123_lut  = g12_lut & g3_lut
g123p_lut = g12_lut & g3p_lut
"""`
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

bwmorph 的 Python 等效项 的相关文章

随机推荐

  • Kendo UI Angular:(SystemJS) 意外标记 <

    我在使用 IIS 的 ASP NET Core 解决方案上使用 VS2015 RC3 Angular2 2 0 0 每当我尝试添加新的 UI 模块 例如下拉列表或输入 时 我都会收到 SystemJS 错误 但奇怪的是我的按钮可以正常工作
  • 使用 VBA 更新 Excel 切片器选择的性能较差

    我正在使用 VBA 模拟单击 Excel 切片器 但遇到了严重的性能问题 用户单击 X 轴上带有日期的柱形图 单击某列时 会在包含日期列表的切片器中选择相应的日期 该列表将随着时间的推移而不断增长 据我所知 为非 OLAP 数据源 我的情况
  • 带圆角的矩形旋转器

    我正在尝试制作加载程序 它看起来像这样 CodePen 但我需要有圆形边框和矩形 而不是盒子 这样我就可以将我们公司的标志放置到装载机上 我尝试再制作一层 这将制作内联半径和包装器 我设置border radius and overflow
  • 将 Datagridview 值更新到数据库中

    我正在开发一个表单应用程序 用户可以从数据库获取表数据 进入可编辑的 gridviewcontrol 以便用户可以更新网格中的一些数据 当用户单击表单上的更新按钮时 更新的数据网格值应该在数据库中更新 用户可以一次更新更多列值 我第一次在数
  • MySQL 错误 1060:重复的列名 ALTER TABLE

    由于我没有创建的代码中的错误 我在查询时遇到了一些问题 query this gt db gt query ALTER TABLE DB PREFIX customer ADD customer type TINYINT 1 NOT NUL
  • Django时区感知DateTimeField默认值时区感知错误

    我正在尝试将 DateTimeField 添加到我的 django 模型中 并以最大时间戳作为默认值 我已经弄清楚 Django 中的最大时间戳是 9999 12 31 23 59 59 与我的 postgres 数据库中使用的最大时间戳不
  • 内存通常比磁盘快多少?

    IDE SCSI SSD SATA 或所有这些 我很惊讶 本文中间的图3 大数据的病理学 表示进行顺序访问时内存仅快 6 倍左右 内存为 350 Mvalues sec 而磁盘为 58 Mvalues sec 但当您进行随机访问时 速度大约
  • std::enable_if 如何工作?

    我刚刚问了这个问题 std numeric limits 作为条件 我明白用法在哪里std enable if将有条件地定义方法的返回类型 导致该方法无法编译 template
  • 按 Column.DisplayMember 对 DataGridView 进行排序

    我有一个DataGridView有几个DataGridViewComboBoxColumn实际值与 ID 相关联 但DisplayMember是查找表中的字符串对应项 我试图做到这一点 以便当我按该列排序时 排序是根据DisplayMemb
  • 适用于 SUN Solaris 和 linux 的 awk + ​​fit 语法

    需要以下方面的帮助 当我在 Linux 上运行以下命令时 它运行良好 awk v NAME MACHINE 1 NAME etc hosts 但在 SUN Solaris 上我得到以下信息 awk v NAME MACHINE 1 NAME
  • 使用 Spring 依赖注入的自定义转换器

    有没有一种方法可以在 Dozer 中定义自定义转换器 用于将一种顶级类型转换为另一种顶级类型 而另一种类型本身就是一个 Spring bean 因此可以注入其依赖项 dozer 文档建议添加以下 XML 定义
  • 如何在 ios 图表中添加标记到中心位置,同时水平滚动并增加scaleX并启用拖动

    我正在使用 Daniel Cohen Gindi 的图表框架 我通过增加scaleX值并启用拖动来水平滚动图表 如这个问题的答案中所述 快速设置我的条形图的水平滚动 我想当用户水平滚动时在中心位置添加标记 我知道每当用户拖动图表时都会调用
  • 如何更改 Zend Framework 的包含目录

    我收到以下错误消息 Warning include once Zend Db php function include once failed to open stream No such file or directory in C Ea
  • 如何将日期变量转换为java.sql.date

    我在尝试将日期变量插入数据库表时遇到困难 我的变量叫做 Date date4 date4 变量值是从具有日历选择器的文本框中读取的 为了插入日期列 我将字段类型设置为日期 preparedstmt setDate 4 date4 然而 提交
  • 检查数组是否包含其他数组的所有元素?

    我有2个数组 第二个数组必须包含第一个数组中的所有元素 如何检查 谢谢 For example array 1 Array 0 gt Email 1 gt 1 Name array 2 Array 0 gt 1 Name 1 gt In t
  • 在 msvc++ 2010 Express 中似乎找不到 std::thread

    我最近一直在阅读有关 c 的各种新添加内容 我对此感到非常兴奋 并且我已经了解了新的 std unique ptr 和 std shared ptr 对象 它们非常有用 现在我正在寻找对于我听说过的本机线程库 但似乎无法在任何地方找到它 我
  • 无法在本地有效地使用 Git

    请参见格雷格的回答 我不明白丹尼尔的声明线程完全地 为什么要手动复制文件 周围有什么吗 当然你应该只是 将它们添加到存储库中 然后查看 并根据需要进行承诺 我没看到 需要移动文件 这似乎违背了整个目的 本地结账 我目前正在使用 rsync
  • 如何在单击按钮时检查 gridview 列中复选框的状态

    我在gridview中使用了复选框列 单击链接按钮时 应检查 gridview 中的复选框是否已选中 如果没有选中任何复选框 则应显示警报 至少选中一个复选框 您必须向页面添加一些自定义 Javascript 以便显示客户端警报 下面是我编
  • jQuery 的“双击”事件(移动设备为 dblclick)

    我有以下 jquery 事件处理函数 target on dblclick function respond to double click event 我的问题是这个事件处理程序不适用于触摸设备 iPhone iPad 谁能推荐一个可靠的
  • bwmorph 的 Python 等效项

    我仍在用 Python 编写指纹图像预处理器 我在 MATLAB 中看到有一个特殊的函数可以消除 H 中断和杂散 bwmorph a hbreak bwmorph a spur 我搜索了 scikit OpenCV 等 但找不到这两种用法的