java - 如何用java把一张图片一分为二

标签 java graphics image-processing image-manipulation

我想知道是否有一种“智能”的方法可以根据某些特征分割图像。

图像为 300x57,黑白(实际上是灰度,但大多数颜色不是黑色就是白色),它由两个主要特征(我们称之为 Blob )组成,由黑色空间分隔,每个 Blob 的宽度略有不同,高度, Blob 的位置也不同, Blob 永远不会重叠!

图像“看起来”是这样的:

-------------------------
----WWW---------WWWWW----
---WWWWWWW----WWWWWW-----
-----WWWW-------WWW------
-------------------------

由此产生的 split 将是这样的:

------------     -------------
----WWW-----     ----WWWWW----
---WWWWWWW--     --WWWWWW-----
-----WWWW---     ----WWW------
------------     -------------

为了拆分图像我计划采取的步骤:

  1. 将图像从一侧扫描到另一侧。
  2. 确定 Blob 的边缘。
  3. 取两条内边之间的距离。
  4. 在内部距离的中间分割图像。
  5. 将两张图片另存为单独的文件。

如果我对图像宽度进行归一化处理就好了,这样我所有的图像在保存时都具有统一的宽度。

我没有图像处理方面的经验,所以我不知道执行此操作的有效方法是什么。我目前正在使用 BufferedImage,获取宽度/高度,迭代每个像素等。我的问题没有错误的解决方案,但我正在寻找更高效的解决方案(代码更少 + 更快)。我也一直在研究 java.awt.Graphics...

如果我能得到一些更有效的方法来完成这项任务的想法,我将不胜感激。我想坚持使用 Java 的内置库,那么在这种情况下 BufferedImage 或 Graphics2D 是最有效的使用方法吗?

编辑: 这是阅读建议后的代码:

public void splitAndSaveImage( BufferedImage image ) throws IOException
{
    // Process image ------------------------------------------         
    int height = image.getHeight();
    int width = image.getWidth();
    boolean edgeDetected = false;
    double averageColor = 0;
    int threshold = -10;
    int rightEdge = 0;
    int leftEdge = 0;
    int middle = 0;

    // Scan the image and determine the edges of the blobs.
    for(int w = 0; w < width; ++w)
    {               
        for(int h = 0; h < height; ++h)
        {
            averageColor += image.getRGB(w, h);
        }

        averageColor = Math.round(averageColor/(double)height);

        if( averageColor /*!=-1*/< threshold && !edgeDetected )
        {
            // Detected the beginning of the right blob
            edgeDetected = true;
            rightEdge = w;
        }else if( averageColor >= threshold && edgeDetected )
        {
            // Detected the end of the left blob
            edgeDetected = false;
            leftEdge = leftEdge==0? w:leftEdge;
        }

        averageColor = 0;
    }

    // Split the image at the middle of the inside distance.
    middle = (leftEdge + rightEdge)/2;

    // Crop the image
    BufferedImage leftImage = image.getSubimage(0, 0, middle, height);

    BufferedImage rightImage = image.getSubimage(middle, 0, (width-middle), height);

    // Save the image
    // Save to file -------------------------------------------
    ImageIO.write(leftImage, "jpeg", new File("leftImage.jpeg"));

    ImageIO.write(rightImage, "jpeg", new File("rightImage.jpeg"));
}

最佳答案

执行此操作的一种简单方法是对每列(向下)中的像素值求和,以创建一个平均值数组(与输入图像的宽度相同)。从数组的中间开始,搜索最小值。这将是您可以拆分图像的列。

此列可能不会成为 blob 之间间隙的中心。您可以从该列再进行一次向外搜索,先向左查找所有类似的列,然后再向右查找。

-------------------------
----WWW---------WWWWW----
---WWWWWWW----WWWWWW-----
-----WWWW-------WWW------
-------------------------

平均列数:

---wwWWwww-----wWWWWww---

根据两个 Blob 之间的空间有多空白(像素值方面),您可以将阈值设置得非常低。如果有一些噪音,它必须高一点。

找到正确的阈值可能是一件苦差事,除非您可以通过算法确定它。

关于java - 如何用java把一张图片一分为二,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2148974/

相关文章:

python - 我怎样才能柔化这张图片的边缘

OpenCV:在顶部和底部配置中绘制匹配项?

java - 将 Spring Security 添加到 Spring Boot 应用程序导致异常

java - 如何在 JLabel 上绘图?

java - 手动数组排序返回 nullpointerexception

Java Graphics : Each time it repaints, 我得到一个 blackflash

c++ - 使用(MFC 的)CImage::SetPixel() 改变像素的颜色

OpenCV:使曲线变直

JavaFX:如何根据 GridPane 内动态创建的文本字段的值计算平均值?

java - GridBagLayout 控制 Swing 中的对齐方式