如何用java将图像分成两部分

Kir*_*ril 5 java graphics image-manipulation image-processing

我想知道是否存在基于某些特征分割图像的"智能"方式.

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

这是图像"看起来"的样子:

-------------------------
----WWW---------WWWWW----
---WWWWWWW----WWWWWW-----
-----WWWW-------WWW------
-------------------------
Run Code Online (Sandbox Code Playgroud)

由此产生的分裂将是这样的:

------------     -------------
----WWW-----     ----WWWWW----
---WWWWWWW--     --WWWWWW-----
-----WWWW---     ----WWW------
------------     -------------
Run Code Online (Sandbox Code Playgroud)

我计划采取的步骤,以分割图像:

  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"));
}
Run Code Online (Sandbox Code Playgroud)

Tre*_*son 5

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

此列可能不会是blob之间差距的中心.您可以从此列进行另一次向外搜索,向左移动以查找所有类似的列,然后向右移动.

-------------------------
----WWW---------WWWWW----
---WWWWWWW----WWWWWW-----
-----WWWW-------WWW------
-------------------------
Run Code Online (Sandbox Code Playgroud)

col avg:

---wwWWwww-----wWWWWww---
Run Code Online (Sandbox Code Playgroud)

根据两个blob之间空白的空白(像素值),您可以将阈值设置得相当低.如果有一些噪音,它必须要高一点.

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