Java 比较两幅图像并用矩形标记差异
编辑:更新了代码,下面的代码现在可以正确地围绕多个形状绘制矩形,但仍然存在一个小问题,即有时在一个形状上创建多个矩形 我有两个图像,我逐像素比较彼此,我希望我的程序在差异区域周围创建矩形(具有多个差异实例的多个矩形)。到目前为止,我只使用了一个矩形,所以如果我有多个“实例”,它们都会在一个大矩形中。现在我试图让程序创建多个矩形,但遇到了IndexOutOfBoundsException 程序本身将两幅图像叠加在一起,并将叠加后的图像与矩形一起输出到一个新文件中。被比较的两幅图像的宽度和高度一致 我将要在代码中绘制的矩形称为“区域”。 在运行比较时,区域列表正在不断更新 我问自己的第一个问题是,一个差异点(像素差异)何时属于一个区域? 我的尝试是定义一个“公差”,只要被比较的像素在最后发现的差异点的公差范围内,它就属于同一区域。我很快意识到,当我的图像上有一个巨大的U形的形状时,这就不起作用了,因为顶点之间的距离足够远,不在公差范围内。现在我有点困了,因为我觉得我走错了路 以下是我目前掌握的代码:Java 比较两幅图像并用矩形标记差异,java,image,image-processing,Java,Image,Image Processing,编辑:更新了代码,下面的代码现在可以正确地围绕多个形状绘制矩形,但仍然存在一个小问题,即有时在一个形状上创建多个矩形 我有两个图像,我逐像素比较彼此,我希望我的程序在差异区域周围创建矩形(具有多个差异实例的多个矩形)。到目前为止,我只使用了一个矩形,所以如果我有多个“实例”,它们都会在一个大矩形中。现在我试图让程序创建多个矩形,但遇到了IndexOutOfBoundsException 程序本身将两幅图像叠加在一起,并将叠加后的图像与矩形一起输出到一个新文件中。被比较的两幅图像的宽度和高度一致
private void compareImages() throws IOException{
BufferedImage img1;
BufferedImage img2;
try {
img1 = ImageIO.read(new File(path_to_img1));
img2 = ImageIO.read(new File(path_to_img2));
} catch (Throwable e) {
System.out.println("Unable to load the Images!");
return;
}
BufferedImage dest = new BufferedImage(img1.getWidth(), img1.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D gfx = dest.createGraphics();
gfx.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.65f));
//Compare Images pixel by pixel
int sX = 9999; //Start X
int sY = 9999; //Start Y
int eX = 0; //End X
int eY = 0; //End Y
boolean isDrawable = false;
boolean loadedRegion = false;
List<Rectangle> regions = new ArrayList<>();
List<Rectangle> check_regions = new ArrayList<>();
Rectangle tmp_comparison;
int regionID = 0;
int tolerance = 25;
for (int i = 0; i < img1.getHeight(); i++) {
for (int j = 0; j < img1.getWidth(); j++) {
loadedRegion = false;
regionID = 0;
sX = 9999;
sY = 9999;
eX = 0;
eY = 0;
if ( img1.getRGB(j, i) != img2.getRGB(j, i) ){
isDrawable = true;
if (regions.size() != 0){
//Attempting to locate a matching existing Region
tmp_comparison = new Rectangle(j, i, 1, 1);
for (int trID = 0; trID<regions.size(); trID++){
if (tmp_comparison.intersects(check_regions.get(trID).getBounds()) == true) {
// Region found
sX = (int) regions.get(trID).getX();
sY = (int) regions.get(trID).getY();
eX = (int) regions.get(trID).getWidth();
eY = (int) regions.get(trID).getHeight();
regionID = trID;
loadedRegion = true;
break;
}
}
}
//Update Region Dimension
if (j<sX){
sX = j;
}
if (j>eX){
eX = j;
}
if (i<sY){
sY = i;
}
if (i>eY){
eY = i;
}
if (regions.size() == 0 || loadedRegion == false){
regions.add(new Rectangle(sX, sY, eX, eY));
check_regions.add(new Rectangle(sX-tolerance, sY-tolerance, eX-sX+(tolerance*2), eY-sY+(tolerance*2)));
} else {
regions.set(regionID, new Rectangle(sX, sY, eX, eY));
check_regions.set(regionID, new Rectangle(sX-tolerance, sY-tolerance, eX-sX+(tolerance*2), eY-sY+(tolerance*2)));
}
}
}
}
// If there are any differences, draw the Regions
// Regions are 10px bigger in all directions as compared to the actual rectangles of difference
if (isDrawable == true){
gfx.setPaint(Color.red);
for (int i = 0; i<regions.size(); i++) {
int dsX = 0;
int dsY = 0;
int deX = 0;
int deY = 0;
sX = (int) regions.get(i).getX();
sY = (int) regions.get(i).getY();
eX = (int) regions.get(i).getWidth();
eY = (int) regions.get(i).getHeight();
if (sX>=10){dsX = sX-10;}
if (eX<=img1.getWidth()-10){deX = eX-sX+20;}
if (sY>=10){dsY = sY-10;}
if (eY<=img1.getHeight()-10){deY = eY-sY+20;}
gfx.draw(new Rectangle2D.Double(dsX, dsY, deX, deY));
}
}
gfx.drawImage(img1, 0, 0, null);
gfx.drawImage(img2, 0, 0, null);
gfx.dispose();
File out = new File("C:\\output.png");
ImageIO.write(dest, "PNG", out);
}
private void compareImages()引发IOException{
缓冲图像img1;
缓冲图像img2;
试一试{
img1=ImageIO.read(新文件(路径_到_img1));
img2=ImageIO.read(新文件(路径_到_img2));
}捕获(可丢弃的e){
System.out.println(“无法加载图像!”);
返回;
}
BuffereImage dest=新的BuffereImage(img1.getWidth(),img1.getHeight(),BuffereImage.TYPE_INT_ARGB);
Graphics2D gfx=dest.createGraphics();
setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.65f));
//逐像素比较图像
int sX=9999;//开始X
int sY=9999;//开始Y
int eX=0;//结束X
int-eY=0;//结束Y
布尔值isDrawable=false;
布尔loadedRegion=false;
列表区域=新的ArrayList();
列表检查区域=新建ArrayList();
矩形tmp_比较;
int regionID=0;
int公差=25;
对于(int i=0;i for(int trID=0;trID为了更好的帮助,请尽快发布一个合适的帖子,请lastX=j;
和lastY=i;
是你想要的吗?是不是j
和i
倒置了?FrakTool我不完全确定你在问什么。对于循环遍历像素,j是遍历宽度(即x)我正在迭代高度(y)。对于每个y,它首先迭代所有x,基本上从左到右,然后跳到下一行。我一有更新就会发布。我想要的不是“lastX”和“lastY”,但在区域列表中正确定义了矩形,以便程序以后绘制。下面是一个简化的图像:如果我比较了两个图像并发现了一些差异,这就是我在输出@Frakcool中想要的,我发现了我的错误并更新了主帖子的代码。它现在可以运行,我的状态如下:Img1=,Img2=Blank白色PNG,尺寸与Img1相同,输出=,预期输出=
private void oneRectangle() throws IOException{
BufferedImage img1;
BufferedImage img2;
try {
img1 = ImageIO.read(new File(path_to_img1));
img2 = ImageIO.read(new File(path_to_img2));
} catch (Throwable e) {
System.out.println("Unable to load the Images!");
return;
}
BufferedImage dest = new BufferedImage(img1.getWidth(), img1.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D gfx = dest.createGraphics();
gfx.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.65f));
//Compare Images pixel by pixel
boolean isDrawable = false;
int sX = 9999;
int sY = 9999;
int eX = 0;
int eY = 0;
for (int i = 0; i < img1.getHeight(); i++) {
for (int j = 0; j < img1.getWidth(); j++) {
if ( img1.getRGB(j, i) != img2.getRGB(j, i) ){
isDrawable = true;
if (j<sX){
sX = j;
}
if (j>eX){
eX = j;
}
if (i<sY){
sY = i;
}
if (i>eY){
eY = i;
}
}
}
}
// Draw rectangle if there are any differences
if (isDrawable == true){
gfx.setPaint(Color.red);
int dsX = 0;
int dsY = 0;
int deX = 0;
int deY = 0;
if (sX>=10){dsX = sX-10;}
if (eX<=img1.getWidth()-10){deX = eX-sX+20;}
if (sY>=10){dsY = sY-10;}
if (eY<=img1.getHeight()-10){deY = eY-sY+20;}
gfx.fill(new Rectangle2D.Double(dsX, dsY, deX, deY));
}
gfx.drawImage(img1, 0, 0, null);
gfx.drawImage(img2, 0, 0, null);
gfx.dispose();
File out = new File("C:\\output.png");
ImageIO.write(dest, "PNG", out);
}