为什么在比较之前必须保存我的BufferedImage?

时间:2019-02-17 07:44:17

标签: java image-processing

我正在尝试从在线资源中分析基于图像的3位数字验证码。这些数字根本没有动。我使用BufferedImage的{​​{1}}方法从验证码中提取每个数字。我已经为每个数十个和数百个位置保存(0-9)。 (所以总共有30个数字)

我将在线图像的getSubimage(...)读入bytes,然后创建一个byte[]对象,如下所示:

BufferedImage

然后,我将该图像与驱动器上的图像列表进行比较:

BufferedImage captcha = ImageIO.read(new ByteArrayInputStream(captchaBytes));

这就是我比较两张图片的方式:

BufferedImage[] nums = new BufferedImage[10];
//Load images into the array here... The code is removed.
for(int i = 0; i < nums.length; i++) {
    double x;
    System.out.println(x = bufferedImagesEqualConfidence(nums[i], firstNumberImage));
    if(x > 0.98) {
        System.out.println("equal to image " + i + ".jpeg");
        isNewEntry = false;
        break;
    }
}

完全从包裹在我自己的static double bufferedImagesEqualConfidence(BufferedImage img1, BufferedImage img2) { double difference = 0; int pixels = img1.getWidth() * img1.getHeight(); if (img1.getWidth() == img2.getWidth() && img1.getHeight() == img2.getHeight()) { for (int x = 0; x < img1.getWidth(); x++) { for (int y = 0; y < img1.getHeight(); y++) { int rgbA = img1.getRGB(x, y); int rgbB = img2.getRGB(x, y); int redA = (rgbA >> 16) & 0xff; int greenA = (rgbA >> 8) & 0xff; int blueA = (rgbA) & 0xff; int redB = (rgbB >> 16) & 0xff; int greenB = (rgbB >> 8) & 0xff; int blueB = (rgbB) & 0xff; difference += Math.abs(redA - redB); difference += Math.abs(greenA - greenB); difference += Math.abs(blueA - blueB); } } } else { return 0.0; } return 1-((difference/(double)pixels) / 255.0); } 对象中的HttpURLConnection对象加载图像。因此,我这样做:HttpGet之所以有用,是因为保存byte[] captchaBytes = hg.readAndGetBytes();时,它将保存为驱动器上的有效映像。

但是,即使2张图像实际上是相同的,结果也显示它们根本不相似。但是,当我保存从网上资源下载的图像时,请重新阅读并进行比较,表明它们是相等的。当我说要保存并重新阅读时,这就是我正在做的事情:

BufferedImage captcha = ImageIO.read(new ByteArrayInputStream(captchaBytes));

图片格式:File temp = new File("temp.jpeg"); ImageIO.write(secondNumberImage, "jpeg", temp); secondNumberImage = ImageIO.read(temp);

我知道这可能与JPEG中的压缩有关,但是如何制作它,这样我就不必保存图像了?

1 个答案:

答案 0 :(得分:0)

问题出在我的bufferedImagesEqualConfidence方法内。仅仅比较RGB是不够的。我不得不比较各个R / G / B值。

我最初的bufferedImagesEqualConfidence无效:

static double bufferedImagesEqualConfidence(BufferedImage img1, BufferedImage img2) {
    int similarity = 0;
    int pixels = img1.getWidth() * img1.getHeight(); 
    if (img1.getWidth() == img2.getWidth() && img1.getHeight() == img2.getHeight()) {
        for (int x = 0; x < img1.getWidth(); x++) {
            for (int y = 0; y < img1.getHeight(); y++) {
                if (img1.getRGB(x, y) == img2.getRGB(x, y)) {
                    similarity++;
                }
            }
        }
    } else {
        return 0.0;
    }

    return similarity / (double)pixels;
}

(来源:Java Compare one BufferedImage to Another

起作用的bufferedImagesEqualConfidence是:

static double bufferedImagesEqualConfidence(BufferedImage img1, BufferedImage img2) {
    double difference = 0;
    int pixels = img1.getWidth() * img1.getHeight(); 
    if (img1.getWidth() == img2.getWidth() && img1.getHeight() == img2.getHeight()) {
        for (int x = 0; x < img1.getWidth(); x++) {
            for (int y = 0; y < img1.getHeight(); y++) {
                int rgbA = img1.getRGB(x, y); 
                int rgbB = img2.getRGB(x, y); 
                int redA = (rgbA >> 16) & 0xff; 
                int greenA = (rgbA >> 8) & 0xff; 
                int blueA = (rgbA) & 0xff; 
                int redB = (rgbB >> 16) & 0xff; 
                int greenB = (rgbB >> 8) & 0xff; 
                int blueB = (rgbB) & 0xff;                      
                difference += Math.abs(redA - redB); 
                difference += Math.abs(greenA - greenB); 
                difference += Math.abs(blueA - blueB); 
            }
        }
    } else {
        return 0.0;
    }

    return 1-((difference/(double)pixels) / 255.0);
}

(来源:Image Processing in Java

我猜想要找到两幅图像之间的相似性,您必须比较每个像素的单个R / G / B值,而不仅仅是整个RGB值。