首页 > 解决方案 > OpenCV - 用二进制垫上的线条细化会导致随机水平虚线

问题描述

我正在编写一种从二进制图像(背景为黑色)中细化白线的方法。本质上,代码循环遍历图像并找到同一行中的连续白色像素,将它们全部变为黑色,最后将中间的像素变为白色。该算法可以很好地细化线条,但会在根本不应该有任何东西的地方产生随机的水平虚线。下面是一个例子:

图像到细线来自: 在此处输入图像描述

算法运行后的图像: 在此处输入图像描述

显然,图像顶部和底部附近的虚线不应该存在,因为原始图像中没有白色区域,但不知何故它们是生成的。我附上了我的代码来做下面的细化,非常感谢任何帮助!

//Line thining
    double[] rgbCanny;
    int inARow = 0;

    for(int i = 0; i < noiseReducedCanny.size().height; i++) {
        for(int j = 0; j < noiseReducedCanny.size().width; j++) {

            rgbCanny = noiseReducedCanny.get(i, j);

            if(rgbCanny[0] == 255) {
                inARow++;
            } else {
                if(inARow != 0 && inARow % 2 == 1) {
                    int middle = (int) Math.ceil(j - inARow / 2.0);
                    for(int x = j - inARow; x < j; x++) {
                        noiseReducedCanny.put(i, x, new double[]{0, 0, 0});
                    }
                    noiseReducedCanny.put(i, middle, new double[]{255, 255, 255});
                } else if (inARow != 0 && inARow % 2 == 0) {
                    int middle = j - inARow / 2;
                    for(int x = j - inARow; x < j; x++) {
                        noiseReducedCanny.put(i, x, new double[]{0, 0, 0});
                    }
                    noiseReducedCanny.put(i, middle, new double[]{255, 255, 255});
                }
                inARow = 0;
            }
        }
    }

标签: javaandroidopencv

解决方案


请注意,即使算法似乎有效,您的线条也不是 1 像素宽。它们是 3 像素宽。

显然put()是设置 3 个连续的白色像素,从给定的索引 ( middle) 开始。2 个意外像素导致您的算法“反馈”到自身,这意味着它们正在触发inARow++线路。

我不是 OpenCV 人,而且我无法轻松put()找到mat. 然而,似乎有可能改变这一点:

new double[]{255, 255, 255}

对此:

new double[]{255}

将导致所需的行为。

您可能还想修复“黑化”线。


推荐阅读