我对Java还是个新手,所以我不确定这个方法是否是个好主意,但基本上我是在尝试检查一个图像在另一个图像中的示例,所以为了测试这个方法是否有效,我有一个200x148 jpg
,从中获取字节,然后从窗口的屏幕截图中获取字节,再从窗口的屏幕截图中获取字节,然后比较它们。
现在,由于第一张图片通常不会出现在截图中,我在我的照片应用程序中打开它,并在程序休眠时将其放入(在它截图之前)。而且是的,我可以通过看截图来确认第一张图片在截图中。然而,当我比较字符串时(检查包含图像1的所有字节数据的String是否在包含图像2的所有字节数据的String中),结果为负。
下面是我目前尝试使用的代码:
public static void main(String[] args) throws IOException, HeadlessException, AWTException, InterruptedException {
// Get the first image
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(ImageIO.read(new File("profile.jpg")), "jpg", baos);
byte[] bytes = baos.toByteArray();
String bytes1S = "";
for (int i = 0; i < bytes.length; i++) {
bytes1S += bytes[i];
}
// Give yourself enough time to open the other image
TimeUnit.SECONDS.sleep(6);
// Take the screenshot
BufferedImage image = new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
ImageIO.write(image, "jpg", new File("screenshot.jpg"));
baos = new ByteArrayOutputStream();
ImageIO.write(ImageIO.read(new File("screenshot.jpg")), "jpg", baos);
byte[] bytes2 = baos.toByteArray();
String bytes2S = "";
for (int i = 0; i < bytes2.length; i++) {
bytes2S += bytes2[i];
}
// Check if the second String of bytes contains the first String of bytes.
if (bytes2S.contains(bytes1S))
System.out.println("Yes");
else
System.out.println("No");
}
作为参考,这是第一张图片和它的截图:
它没有检测到屏幕截图中的第一个图像的原因是什么?有没有更好的方法来做到这一点(最好不使用其他库)?
1条答案
按热度按时间2mbi3lxu1#
一种强力方法是简单地将两个图像都作为
BufferedImage
对象加载,然后逐个像素地遍历“主”图像,看看是否可以在其中找到“子图像”。我已经实现了这一点前一段时间,并将张贴下面的代码作为一个MCVE。
但是注意:当你把图像保存为JPG文件时,它们会被压缩,而这种压缩是 * 有损 * 的。这意味着像素不会有完全相同的颜色,即使它们在屏幕上是相等的。在下面的例子中,这个问题实际上得到了解决,用一个“阈值”来定义像素可能有多大的不同。但这有点武断,不那么可靠。(更强大的解决方案需要更多的努力)。
我强烈建议将图片保存为PNG文件。它们使用无损压缩。所以对于PNG文件,你可以在下面的代码中设置
threshold=0
。