java - Canny 边缘检测不检测 100% 水平/未旋转的线

Canny 边缘检测是否应该检测纯的、非旋转的水平线?

这些是输入图像:

100% 水平(非旋转)非模糊线
右:旋转 1° 的同一图像

对应的输出“边缘”图像:

(为了更好的判断,图像在这里缩放了 2 倍,没有平滑。)

使用阈值 low=250x0.66 和 high=250x1.33 以及内核大小 k=3 处理图像。

虽然阶梯图像产生了令人满意的结果,但前者图像却没有。

图像目前没有进一步预处理,您看到的是 Canny 中的内容。

我创建了第一张图片作为测试数据。这可能是一个构造的案例,尽管这样的线条可能会出现在现实世界的场景中。

MCVE:

public class q58884116 {
    public static void main(String[] args) throws Exception {
        System.load(new File(Paths.get("target", "classes", "libopencv_java412.so").toString()).getAbsolutePath());

        File inFile = new File(args[0]);
        File outFile = new File(args[1]);

        Mat imageColor = Imgcodecs.imread(inFile.getAbsolutePath(), Imgcodecs.IMREAD_COLOR);
        Mat patternProbeImage = new Mat();
        Imgproc.cvtColor(imageColor, patternProbeImage, Imgproc.COLOR_BGR2GRAY);

        Mat edges = new Mat();
        // Value determined from histogram in Gimp.
        Imgproc.Canny(patternProbeImage, edges, 250 * 0.66, 250 * 1.33, 3, true);

        Imgcodecs.imwrite(outFile.getAbsolutePath(), edges);
    }
}

输入图像(未缩放):input.png

  • 从 Git 编译
  • OpenCV 4.1.2
  • cmake 3.7.2
  • 海湾合作委员会 6.3.0
  • openjdk 1.8.0_232
  • 使用 Java 库。

构建步骤:

$ git clone https://github.com/opencv/opencv.git
$ cd opencv/
$ git checkout 4.1.2
$ cd cmake/
$ cmake -DCMAKE_INSTALL_PREFIX="/opt/opencv" ..
$ make -j4
$ make install

我必须承认,我不熟悉 Canny 背后的理论,甚至不熟悉一般的计算机视觉。我才刚刚开始。虽然我可以想象这可能是由 Sobel function 使用的 Gy 矩阵的零行引起的。 (在 Canny 函数文章中提到过)。

如果这确实是 Canny 的局限性,那么处理此类情况的常用方法是什么(简而言之)?


我是根据经验来处理这个问题的:我创建了一个白到黑的渐变图像 上面有黑色的光栅图案。光栅应代表 不同背景上原始测试图像的线条。

这是我们的输入图像:

(为更漂亮的帖子裁剪和调整大小,download original。)

MCVE 被扩展以生成各种阈值范围的边缘(不是 每种可能的组合都有,但数量相当):

for (int i = 0; i < 255 - 50; i++) {
    Mat edges = new Mat();
    Imgproc.Canny(patternProbeImage, edges, i, i + 50, 3, true);

    Imgcodecs.imwrite(getOutputFile(outFile, "lb-0-" + String.format("%03d", i)).getAbsolutePath(), edges);
}

然后我们可以检查生成的边。

使用这个衬垫,可以生成所有图像的马赛克( Sprite ),以便更容易 检查:

$ convert gradient-grating.out.lb-0-*.png +append  gradient-grating.out.lb.png

这是结果:

可以看出,Canny 无法在最小值上检测到越来越多的边缘 值侧(顶部)随着阈值的降低而增加。我预料到了这一点。尽管在最大值方面,无论给定什么阈值,Canny 都永远无法检测到边缘。

最佳答案

尝试保存图像,然后直接打开图像文件。这可能只是绘图仪如何渲染图像的问题。

我自己也遇到了同样的问题,但是已经解决了。我正在使用 matplotlib 通过 jupyter notebook 查看我的边缘图像。 100% 的水平边缘在笔记本内部显示时不会呈现。但是当我将它保存为png并直接打开图像文件时,水平边缘实际上就在那里。

https://stackoverflow.com/questions/58884116/

相关文章:

amazon-web-services - 您应该使用客户端凭据授权类型来验证服务器到服务器吗?

mysql - 在 macOS Catalina 10.15.1 下安装 DBD::mysql 时遇

python - 设置 scipy.signal.peak_widths 的绝对值

apache-spark - 使用来自 s3 存储桶的数据在 AWS EMR 上使用 pyspark

leaflet - 校正 Rayshader 的卫星图像覆盖

google-cloud-platform - 使用 --allow-unauthenticated

apache-zookeeper - Chubby Sequencer 的目的是什么

docker - 让 docker build --memory-swap=20g 使用可用的交换空

javascript - 如何使用 ngx-export-as 中的选项

node.js - 使用 fetch API 时如何记录实际的请求 header