Почему я должен сохранить свой BufferedImage перед сравнением? - PullRequest
0 голосов
/ 17 февраля 2019

Я пытаюсь проанализировать основанную на изображениях 3d-цифру капчи с онлайн-ресурса.Числа не двигаются вообще.Я использую BufferedImage s getSubimage(...) метод для извлечения каждого числа из капчи.Я сохранил (0-9) для каждого из десятков и сотен мест.(Итого 30 номеров)

Я читаю 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(); Что, как я знаю, работает, потому что когда я сохраняю BufferedImage captcha = ImageIO.read(new ByteArrayInputStream(captchaBytes));, он сохраняет как допустимое изображение на моем диске.

Однако, даже если 2 изображения фактически совпадают, результат показываетони совсем не похожи.НО, когда я сначала сохраняю изображение, загруженное с онлайн-ресурса, перечитываю его и сравниваю, оно показывает, что они равны.Это то, что я делаю, когда говорю, что сохраняю и перечитываю:

File temp = new File("temp.jpeg");
ImageIO.write(secondNumberImage, "jpeg", temp);
secondNumberImage = ImageIO.read(temp);

Формат изображения: JPEG

Я знаю, что это может быть связано со сжатиемиз ImageIO.write(...), но как мне сделать так, чтобы мне не нужно было сохранять изображение?

1 Ответ

0 голосов
/ 17 февраля 2019

Проблема была в моем методе 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. Сравнение одного BufferedImage с другим )

.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);
}

(Источник: Обработка изображений на Java )

Я думаю, чтобы найти сходство между двумя изображениями, которые вы должны сравнить отдельныеЗначения R / G / B для каждого пикселя, а не всего значения RGB.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...