图像裁剪,使用 Java 删除图像中不需要的白色部分 [重复]

Posted

技术标签:

【中文标题】图像裁剪,使用 Java 删除图像中不需要的白色部分 [重复]【英文标题】:Image crop, Remove unwanted white portion of Image using Java [duplicate] 【发布时间】:2018-02-08 07:30:41 【问题描述】:

图像裁剪,使用 Java 删除图像中不需要的白色部分。 我们如何使用 Java 删除图像中不需要的白色部分?我有具有计划白色区域的图像,我想使用 JAVA 代码从有用的主图像中删除图像中未使用的白色部分。您可以在显示的图像下方获得清晰的想法。我需要使用 Java 代码执行此任务。

Click here to view image

【问题讨论】:

啊,BufferedImage#subImageBufferedImage#drawImage?您知道要删除多少图像吗?是否总是保持相同的风格 - 图像布局的稳定性如何? 图片大小、分辨率、高度、宽度等。总是一样的,实际上我想裁剪图像,因为我在哪里使用这个图像,因为白色的未使用区域,它看起来不太好。 @MadProgrammer 图片位置呢?它会一直在顶部吗? 是的,它总是在最前面。 @MadProgrammer 这不是引用问题的重复,因为当前问题更笼统,而另一个问题没有解决一般情况。现在的问题还需要修剪图像的顶部和左侧,而不仅仅是右侧和底部。需要使用不同的 API 进行裁剪。 【参考方案1】:

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

这是非常低效的。我曾想过使用分而治之的方法,但我真的没有时间充实它。

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;
    

【讨论】:

它效率低下,因为您正在为每个像素创建所有颜色 - 哇浪费内存颜色是巨大的浪费 - 除非你有一台并行机器,否则没有分治法 - 2-3 个核心什么都不做 @gpasch 懒惰;考虑到可能的空白量,从每个边缘遍历像素是有效的。当我说分而治之时,我说的是简单地使用二分搜索风格的方法,简单地分割图像并检查中间的像素,但我更喜欢去睡觉;)【参考方案2】:

您可以使用图像处理框架来简化图像处理。

在下面的示例中,我使用了Marvin。我的做法:

    使用灰度阈值将白色像素与图像的其余部分分开。 找到黑色部分的边界框 使用在上一步中检测到的片段裁剪原始图像。

输入:

输出 (board_cropped.png):

源代码:

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 运算符的条件:``` java if(r.y == -1 || x

以上是关于图像裁剪,使用 Java 删除图像中不需要的白色部分 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何裁剪来自java端的动态图像?

如何使用 OpenCV 裁剪图像中的白色斑块并制作护照大小的照片

如何使用 PIL 在单个白色背景上检测和裁剪多个图像?

不使用内置函数进行图像裁剪的matlab代码

Opencv c ++检测并裁剪图像上的白色区域

java中的图像裁剪