Java中的图像处理边缘检测
image-processing
java
7
0

这是我的情况。它涉及对齐扫描图像,这将解决扫描错误的问题。我必须将扫描的图像与Java程序对齐。

这些是更多详细信息:

  • 在一张纸上打印有一个类似表格的表格,它将被扫描成一个图像文件。
  • 我将使用Java打开图片,并且将有一个文本框覆盖。
  • 文本框应该与扫描的图像正确对齐。
  • 为了正确对齐,我的Java程序必须分析扫描的图像并在扫描的图像上检测表格边缘的坐标,从而定位图像和文本框,以使文本框和图像都正确对齐(以防万一扫描错误)

您会看到,扫描图像的人可能未必将图像放置在正确的位置,因此我需要我的程序在加载扫描图像时自动对齐。该程序将可在许多此类扫描图像上重用,因此我需要该程序具有这种灵活性。

我的问题是以下问题之一:

  1. 如何使用Java来检测表格上边缘的y坐标和表格最左边的x坐标。这张桌子是一张普通桌子,上面有很多单元,黑色细边框,印在白纸上(水平打印输出)

  2. 如果存在一种更简单的方法来自动对齐扫描图像,以使所有扫描图像的图形表都对齐到相同的x,y坐标,请共享此方法:)。

  3. 如果您不知道以上问题的答案,请告诉我应该从哪里开始。我对图形Java编程了解不多,并且大约有1个月的时间可以完成此程序。只是假设我的时间安排很紧,我必须使图形部分对我来说尽可能简单。

干杯,谢谢。

参考资料:
Stack Overflow
收藏
评论
共 2 个回答
高赞 时间 活跃

尝试从一个简单的场景开始,然后改进方法。

  1. 检测角落。
  2. 找到窗体边界中的角。
  3. 使用表格角坐标,计算旋转角度。
  4. 旋转/缩放图像。
  5. 相对于表单原点坐标映射表单中每个字段的位置。
  6. 匹配文本框。

本文结尾处介绍的程序执行步骤1至3。该程序是使用Marvin Framework实现的。下图显示了带有检测到的角的输出图像。

在此处输入图片说明

程序还输出: 旋转角度:1.6365770416167182

源代码:

import java.awt.Color;
import java.awt.Point;
import marvin.image.MarvinImage;
import marvin.io.MarvinImageIO;
import marvin.plugin.MarvinImagePlugin;
import marvin.util.MarvinAttributes;
import marvin.util.MarvinPluginLoader;

public class FormCorners {

public FormCorners(){
    // Load plug-in
    MarvinImagePlugin moravec = MarvinPluginLoader.loadImagePlugin("org.marvinproject.image.corner.moravec");
    MarvinAttributes attr = new MarvinAttributes();

    // Load image
    MarvinImage image = MarvinImageIO.loadImage("./res/printedForm.jpg");

    // Process and save output image
    moravec.setAttribute("threshold", 2000);
    moravec.process(image, null, attr);
    Point[] boundaries = boundaries(attr);
    image = showCorners(image, boundaries, 12);
    MarvinImageIO.saveImage(image, "./res/printedForm_output.jpg");

    // Print rotation angle
    double angle =  (Math.atan2((boundaries[1].y*-1)-(boundaries[0].y*-1),boundaries[1].x-boundaries[0].x) * 180 / Math.PI);
    angle =  angle >= 0 ? angle : angle + 360;
    System.out.println("Rotation angle:"+angle);
}

private Point[] boundaries(MarvinAttributes attr){
    Point upLeft = new Point(-1,-1);
    Point upRight = new Point(-1,-1);
    Point bottomLeft = new Point(-1,-1);
    Point bottomRight = new Point(-1,-1);
    double ulDistance=9999,blDistance=9999,urDistance=9999,brDistance=9999;
    double tempDistance=-1;
    int[][] cornernessMap = (int[][]) attr.get("cornernessMap");

    for(int x=0; x<cornernessMap.length; x++){
        for(int y=0; y<cornernessMap[0].length; y++){
            if(cornernessMap[x][y] > 0){
                if((tempDistance = Point.distance(x, y, 0, 0)) < ulDistance){
                    upLeft.x = x; upLeft.y = y;
                    ulDistance = tempDistance;
                } 
                if((tempDistance = Point.distance(x, y, cornernessMap.length, 0)) < urDistance){
                    upRight.x = x; upRight.y = y;
                    urDistance = tempDistance;
                }
                if((tempDistance = Point.distance(x, y, 0, cornernessMap[0].length)) < blDistance){
                    bottomLeft.x = x; bottomLeft.y = y;
                    blDistance = tempDistance;
                }
                if((tempDistance = Point.distance(x, y, cornernessMap.length, cornernessMap[0].length)) < brDistance){
                    bottomRight.x = x; bottomRight.y = y;
                    brDistance = tempDistance;
                }
            }
        }
    }
    return new Point[]{upLeft, upRight, bottomRight, bottomLeft};
}

private MarvinImage showCorners(MarvinImage image, Point[] points, int rectSize){
    MarvinImage ret = image.clone();
    for(Point p:points){
        ret.fillRect(p.x-(rectSize/2), p.y-(rectSize/2), rectSize, rectSize, Color.red);
    }
    return ret;
}

public static void main(String[] args) {
    new FormCorners();
}
}
收藏
评论

边缘检测通常是通过增强相邻像素之间的对比度来完成的,以便获得易于检测的线条,适合进行进一步处理。

为此,“内核”会根据像素的初始值和该像素的邻居的值来转换像素。好的边缘检测内核将增强相邻像素之间的差异,并降低具有相似邻域的像素的强度。

我将从查看Sobel运算符开始。这可能不会返回立即对您有用的结果;但是,如果您不熟悉该领域,就可以解决问题。

在获得一些清晰的干净边缘之后,可以使用较大的核来检测似乎在两行中发生90%弯曲的点,这可能会给您外部矩形的像素坐标,这可能足以满足您的目的。

对于这些外部坐标,要使新像素与旧像素之间的平均值进行堆肥并旋转并移动到“匹配”,还需要一点数学。结果(尤其是如果您不了解抗锯齿数学的结果)可能会很差,从而使图像模糊。

锐化滤镜可能是一个解决方案,但是它们也有其自身的问题,主要是通过增加颗粒感使图像更清晰。太多了,很明显原始图像不是高质量的扫描。

收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题

关于我们

常见问题

内容许可

联系我们

@2020 AskGo
京ICP备20001863号