图像裁剪,使用 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#subImage
? BufferedImage#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 删除图像中不需要的白色部分 [重复]的主要内容,如果未能解决你的问题,请参考以下文章