笔画宽度变换 (SWT) 实现 (Python)

Posted

技术标签:

【中文标题】笔画宽度变换 (SWT) 实现 (Python)【英文标题】:Stroke Width Transform (SWT) implementation (Python) 【发布时间】:2012-06-22 09:23:43 【问题描述】:

谁能描述我如何在 python 中使用 opencv 或 simplecv 实现 SWT?

【问题讨论】:

如果您正在寻找论文实现,您可以添加指向该论文的链接,或者至少提供指向 SWT 的链接。 可能有用:***.com/questions/4837124/… 我已经看过了,但是链接坏了,没有代码或伪代码可用。 该链接绝对有效:sites.google.com/site/roboticssaurav/strokewidthnokia 可以在here找到一个matlab实现(基于C++ mex文件)。 【参考方案1】:

好的,就这样吧:

实现细节的链接,底部有代码下载链接:SWT

为了完整起见,还提到 SWT 或 Stroke Width Transform 是 Epshtein 和其他人在 2010 年设计的,并且已证明是迄今为止最成功的文本检测方法之一。它不使用机器学习或复杂的测试。基本上在对输入图像进行 Canny 边缘检测之后,它会计算构成图像中对象的每个笔划的粗细。由于文本的笔画粗细一致,这可能是一种强大的识别功能。

链接中给出的实现是使用 C++、OpenCV 和 Boost 库,它们在计算 SWT 步骤后用于连接图遍历等。我个人已经在 Ubuntu 上对其进行了测试,它工作得很好(而且效率很高),尽管准确度并不准确。

【讨论】:

【参考方案2】:

我实现了类似于中描述的基于距离变换的 SWT Huizhong Chen、Sam S. Tsai、Georg Schroth、David M. Chen、Radek Grzeszczuk、Bernd Girod 的具有边缘增强的最大稳定极端区域的自然图像中的鲁棒文本检测 >'。

这与论文中描述的不同,但粗略的近似值符合我的目的。认为我应该分享它,以便有人可能会发现它有用(并指出任何错误/改进)。它用 C++ 实现并使用 OpenCV。

    // bw8u : we want to calculate the SWT of this. NOTE: Its background pixels are 0 and forground pixels are 1 (not 255!)
    Mat bw32f, swt32f, kernel;
    double min, max;
    int strokeRadius;

    bw8u.convertTo(bw32f, CV_32F);  // format conversion for multiplication
    distanceTransform(bw8u, swt32f, CV_DIST_L2, 5); // distance transform
    minMaxLoc(swt32f, NULL, &max);  // find max
    strokeRadius = (int)ceil(max);  // half the max stroke width
    kernel = getStructuringElement(MORPH_RECT, Size(3, 3)); // 3x3 kernel used to select 8-connected neighbors

    for (int j = 0; j < strokeRadius; j++)
    
        dilate(swt32f, swt32f, kernel); // assign the max in 3x3 neighborhood to each center pixel
        swt32f = swt32f.mul(bw32f); // apply mask to restore original shape and to avoid unnecessary max propogation
    
    // swt32f : resulting SWT image

【讨论】:

距离变换的局部最大值将产生半笔画宽度。这是一个很好的观察结果,尽管 2011-2012 年的一些论文将这个确切的东西与 MSER 等区域检测器结合使用。 @AruniRC 给定链接中的论文提供了有关此方法的详细信息。其实这个半笔画宽度的东西不是我的观察。真的很抱歉,如果我的文字让它看起来像是我的。这一切都应该归功于本文的作者。 哦,我根本不是那个意思。只是一个观察。抱歉,我之前没有看到 ICIP 论文链接是我的错。事实上,使用距离变换来获得半宽在实现方面更加容易和优雅。就个人而言,我使用拉普拉斯算子来获得 dist 的局部极值。反式图像,但你的扩张方式更干净。 你的方法的输入图像的背景值必须为0,前景值必须为1?我怎么会意识到这一点? @BastianSchoettle 我们将 SWT 应用于二进制图像,因此您可以使用 threshold 并将 maxval 设置为 1 来创建此二进制图像。只是一个例子。【参考方案3】:

这里有一个完整的库SWTloc这里是算法的Python 3实现


v2.0.0 以上

安装库

pip install swtloc

转换图像

import swtloc as swt
imgpath = 'images/path_to_image.jpeg'
swtl = swt.SWTLocalizer(image_paths=imgpath)
swtImgObj = swtl.swtimages[0]
swt_mat = swtImgObj.transformImage(text_mode='lb_df',
                                   auto_canny_sigma=1.0,
                                   maximum_stroke_width=20)


本地化字母

localized_letters = swtImgObj.localizeLetters(minimum_pixels_per_cc=100,
                                              maximum_pixels_per_cc=10_000,
                                              acceptable_aspect_ratio=0.2)


本地化单词

localized_words = swtImgObj.localizeWords()

完全披露:我是这个库的作者

【讨论】:

以上是关于笔画宽度变换 (SWT) 实现 (Python)的主要内容,如果未能解决你的问题,请参考以下文章

图像处理小字典——SWT

需要整理的博客

确定签名捕获笔画宽度的屏幕尺寸的最佳方法?

如何绘制具有可变笔画宽度的路径

固定 SVG 中的笔画宽度

MK 圆 - 笔画宽度相当于米