图像裁剪,使用Java去除图像中不需要的白色部分。

3

使用Java进行图像裁剪,去除不需要的白色部分。

如何使用Java去除图像中不需要的白色部分?我有一张图片,其中有一个纯白色区域,我想使用JAVA代码除去该无用的白色部分,只保留我的主要图像。您可以从下面展示的图像中获得更清晰的理解。我需要使用Java代码执行此任务。

点击这里查看图片


啊,BufferedImage#subImageBufferedImage#drawImage?你知道你想要移除多少图像吗?它的样式总是一样的吗 - 图像布局有多恒定? - MadProgrammer
图像大小、分辨率、高度、宽度等始终保持不变,实际上我想裁剪图像,因为在我使用这个图像的地方,由于未使用的白色区域,它看起来不好。@MadProgrammer - Mehul Purohit
图片位置怎么样?它会一直在顶部吗? - MadProgrammer
是的,它将始终处于顶部。@MadProgrammer - Mehul Purohit
这不是引用问题的重复,因为当前问题更为普遍,而其他问题并未涉及一般情况。当前问题还需要修剪图像的顶部和左侧,而不仅仅是右侧和底部。需要使用不同的API进行裁剪。 - Joe Lapp
2个回答

1
这是一种(非常)简单的暴力方法示例。基本上,它会遍历图像,直到颜色从所需的填充颜色改变。

Example

这非常低效。我曾考虑使用分治方法,但实在没有时间去详细阐述。
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;

public class Test {

    public static void main(String[] args) throws IOException {
        BufferedImage img = ImageIO.read(new File("/Users/swhitehead/Downloads/47hb1.png"));
        Rectangle bounds = getBounds(img, Color.WHITE);
        System.out.println(bounds);
        BufferedImage trimmed = img.getSubimage(bounds.x, bounds.y, bounds.width, bounds.height);
        JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(trimmed)));
    }

    public static Rectangle getBounds(BufferedImage img, Color fillColor) {
        int top = getYInset(img, 20, 0, 1, fillColor);
        int bottom = getYInset(img, 20, img.getHeight() - 1, -1, fillColor);
        int left = getXInset(img, 0, top, 1, fillColor);
        int right = getXInset(img, img.getWidth() - 1, top, -1, fillColor);

        return new Rectangle(left, top, right - left, bottom - top);
    }

    public static int getYInset(BufferedImage img, int x, int y, int step, Color fillColor) {
        while (new Color(img.getRGB(x, y), true).equals(fillColor)) {
            y += step;
        }
        return y;
    }

    public static int getXInset(BufferedImage img, int x, int y, int step, Color fillColor) {
        while (new Color(img.getRGB(x, y), true).equals(fillColor)) {
            x += step;
        }
        return x;
    }
}

1
这是因为您为每个像素创建了所有的颜色,非常低效 - 真是一种浪费内存的行为。颜色是不可避免的巨大资源浪费者 - 除非您有一个并行计算机,否则没有分治法可言 - 2-3个内核也无法发挥作用。 - gpasch
@gpasch 太懒了;从每个边缘开始逐像素行走效率低下,考虑到可能存在的白色空间。当我说分而治之时,我是指简单地使用二分搜索风格的方法,只需将图像分成两半并检查中间的像素,但我更愿意去睡觉 ;) - MadProgrammer

0

你可以使用图像处理框架来使图像操作更加简单。

在下面的例子中,我使用了Marvin。我的方法:

  1. 使用灰度阈值分离白色像素和其余部分的像素。
  2. 找到黑色分割线的边界框。
  3. 使用在前一步中检测到的分割线裁剪原始图像。

输入:

enter image description here

输出(board_cropped.png):

enter image description here

源代码:

import static marvin.MarvinPluginCollection.*;
import java.awt.Rectangle;
import marvin.image.MarvinImage;
import marvin.io.MarvinImageIO;

public class BoardSegmentation {

    public BoardSegmentation() {
        MarvinImage imageOriginal = MarvinImageIO.loadImage("./res/board.png");
        MarvinImage image = imageOriginal.clone();
        thresholding(image, 250);
        Rectangle rect = getBoundingBox(image);
        crop(imageOriginal, image, rect.x, rect.y, rect.width, rect.height);
        MarvinImageIO.saveImage(image, "./res/board_cropped.png");
    }
    public Rectangle getBoundingBox(MarvinImage image) {
        Rectangle r = new Rectangle();
        r.x = -1; r.y = -1; r.width = -1; r.height = -1;
        for(int y=0; y<image.getHeight(); y++) {
            for(int x=0; x<image.getWidth(); x++) {
                if(image.getIntColor(x, y) == 0xFF000000) {
                    if(r.x == -1 || x < r.x) {  r.x = x;    }
                    if(r.width == -1 || x > r.x + r.width) {    r.width = x - r.x;  }
                    if(r.y == -1 || x < r.y) {  r.y = y;    }
                    if(r.height == -1 || y > r.y + r.height) {  r.height = y - r.y; }
                }
            }
        }
        return r;
    }
    public static void main(String[] args) {
        new BoardSegmentation();
    }
}

你的解决方案非常有意思,但受到一个小错误的影响。请查看第三个嵌套if运算符的条件:if(r.y == -1 || x < r.y) { r.y = y; }应该是(注意y): if(r.y == -1 || ((y)) < r.y) { r.y = y; } - Edoardo Vencia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接