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

18

有人能描述一下如何使用OpenCV或SimpleCV在Python中实现SWT吗?


1
如果您正在寻找一份论文实现,您可以添加该论文的链接,或者至少提供一个关于SWT是什么的链接。 - Abid Rahman K
可能会有用:https://dev59.com/Sm445IYBdhLWcg3we6V9 - Abid Rahman K
我已经看过它们了,但链接已损坏,没有可用的代码或伪代码。 - pylover
1
那个链接绝对有效:https://sites.google.com/site/roboticssaurav/strokewidthnokia - AruniRC
@AruniRC,谢谢。请将您的链接作为答案发送给我,我会接受它。 - pylover
2
可以在这里找到基于C++ mex文件的Matlab实现。 - Shai
3个回答

17

好的,下面开始:

链接中包含实现细节和代码下载链接:SWT

为了完整起见,还要提到 SWT 或 Stroke Width Transform,它是由 Epshtein 等人于 2010 年设计的,并且已经成为迄今为止最成功的文本检测方法之一。它不使用机器学习或复杂的测试。基本上,在输入图像上执行 Canny 边缘检测后,它计算组成图像对象的每个笔画的粗细。由于文本具有均匀粗细的笔画,因此这可以成为一个强大的识别特征。

链接中提供的实现使用 C++、OpenCV 和 Boost 库,在计算 SWT 步骤后用于连接图遍历等操作。就个人而言,我在 Ubuntu 上进行了测试,它表现得相当不错(而且效率很高),尽管准确性不是完全精确。


8
我实现了类似于基于 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
1
@AruniRC 在给定链接中的论文提供了关于这种方法的详细信息。实际上,这个半笔画宽度的问题并不是我的观察结果。如果我的写作让人们产生这种误解,我真的很抱歉。所有的功劳应该归给这篇论文的作者们。 - dhanushka
1
哦,我完全不是那个意思。只是一些观察。对于之前没有看到ICIP论文链接是我的错误和抱歉。实际上,使用距离变换来获取半宽更易于实现和优雅。个人而言,我曾经使用拉普拉斯算子来获取距离变换图像的局部极值,但你的膨胀方法更干净。 - AruniRC
你的方法的输入图像必须具有零的背景值和一的前景值。我该如何实现这个要求? - Bastian
1
@BastianSchoettle 我们将 SWT 应用于二进制图像,因此您可以使用 threshold 并将 maxval 设置为 1 来创建此二进制图像。这只是一个例子。 - dhanushka
谢谢...我写代码的速度比思考的速度快。发表评论几分钟后,我就解决了问题。 - Bastian

5

这里有一个完整的库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()

图片说明

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接