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
- GCC 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 函数使用的 Gy 矩阵的零行引起的(在 Canny 函数文章中提到过)。
如果这确实是 Canny 的限制,那么处理这种情况的常用方法是什么(简而言之)?
我凭经验处理了这个问题:我创建了一个白色到黑色的渐变图像,上面有一个黑色的光栅图案。光栅应代表原始测试图像在不同背景上的线条。
这是我们的输入图像:
(为更漂亮的帖子裁剪和调整大小,下载原版。)
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);
}
然后我们可以检查生成的边缘。
使用这一衬里,生成所有图像的马赛克(精灵),以便于检查:
$ convert gradient-grating.out.lb-0-*.png +append gradient-grating.out.lb.png
这是结果:
可以看出,随着阈值的增加,Canny 无法在最小值侧(顶部)检测到越来越多的边缘。我预料到了这一点。尽管在最大值方面,无论给出什么阈值,Canny 都无法检测到边缘。
解决方案
尝试保存图像,然后直接打开图像文件。这可能只是绘图仪如何渲染图像的问题。
我自己也有同样的问题,但解决了。我正在使用 matplotlib 通过 jupyter 笔记本查看我的边缘图像。100% 水平边缘在笔记本内显示时不会呈现。但是当我将它保存为png并直接打开图像文件时,水平边缘实际上是存在的。
推荐阅读
- html - 当主体标签具有无法更改的填充时,如何修复容器标签以将其向上移动
- hyperledger-fabric - 生成新频道 configtx
- forms - 为什么没有使用 Spring Boot 命令对象发布对象/复杂类型?
- json - 如何创建表格并从任何单元格中的数据填充
- azure - 使用 Azure DevOps DACPAC 任务在 Azure SQL DB 的主数据库上运行 SQL 命令
- python - 如何根据字符串值在复杂的树状嵌套字典中搜索键值对,该字符串值在 Python 中包含类似 Jinja 的分隔符
- python - Pandas 通过远程服务器 ip 地址读取 csv
- java - spring-integration 和 spring-batch 项目有什么区别?
- python - 具有可变格式(小数位)的装饰器计时器功能?
- amazon-web-services - 如何使用 CloudFormation 配置 CloudFront 以将“ForwardedValues”中的“Headers”属性设置为“all”?