Декодирование цветного изображения с использованием библиотеки ZXing на Java

Я пытаюсь декодировать цветной QR-код на Java с библиотекой ZXing. Из некоторых исследований я знаю, что ZXing уже умеет это делать. Но я делал это в течение 2 дней, и я пытался прочитать QR-изображение из файла и вычислить самый темный и самый яркий цвет на изображении. Затем измените каждый пиксель переднего плана на черный, а остальные на белый. После этого я получу QR-код, как и стандартные. Затем используйте функцию для чтения QR-кода:

Однако это работает только для QR-кода с двумя разными цветами, если он доходит до трех цветов, то в большинстве случаев это не сработает. Разве что новое изображение, преобразованное из цветного в серое, не превысит процент исправления ошибок.

И я пробовал другие методы, но каждый метод работает только для определенного типа QR-кода (с логотипом, разноцветными, фигурными шаблонами Finder и т. д.).

И то, что я ищу, — это способ декодировать все виды QR-кода. По крайней мере, для разноцветных и фигурных шаблонов Finder.

Подробнее:

1) Это код, который я использую для декодирования зеленого QR на эта страница (второй QR), а также используется для декодирования третьего QR (с чем-то вроде логотипа над шаблоном выравнивания), найденного на том же веб-сайте, который определенно не работает:

public class Decoder
{
  public static void main(String[] args)
  {
    // input image file
    File imageFile = new File("/Users/User/Desktop/QR/green.png");
    BufferedImage image = null;
    try
    {
      image = ImageIO.read(imageFile);
    }
    catch (IOException e)
    {
      System.out.println("io outch");
    }
    int imageWidth = image.getWidth();
    int imageHeight = image.getHeight();
    int total = 0;
    int dark = image.getRGB(0, 0);
    int light = image.getRGB(0, 0);
    int backgroundColor = 0;
    int foregroundColor = 0;
    FinderPattern topLeftFinder;
    for (int x = 0; x < imageWidth; x ++)
    {
      for (int y = 0; y <imageHeight; y ++)
      {
        total = total + image.getRGB(x, y);
      }
    }
    //int average = total / (imageWidth * imageHeight);
    //System.out.println("total" + total + " average " + average);
    for (int x = 0; x < imageWidth; x ++)
    {
      for (int y = 0; y <imageHeight; y ++)
      {
        if (image.getRGB(x, y) < dark)
        {
          dark = image.getRGB(x, y);
        }
        if (image.getRGB(x, y) > light)
        {
          light = image.getRGB(x, y);
        }
      }
    }
    for (int x = 0; x < imageWidth; x ++)
    {
      for (int y = 0; y <imageHeight; y ++)
      {
        if (image.getRGB(x, y) >= (dark - light) / 4)
        {
          image.setRGB(x, y, -1);
        }
        else if (image.getRGB(x, y) <= (dark - light) * 3 / 4)
        {
          image.setRGB(x, y, -16777216);
        }
        else
        {
          image.setRGB(x, y, -1);
        }
      }
    }
    System.out.println("total" + dark + " average " + light);
    File outputFile = new File("/Users/Desktop/QR/outputQR.png");
    //ImageIO.write(image, "png", file);
    try
    {
      ImageIO.write(image, "png", outputFile);
    }
    catch (IOException e)
    {
      System.out.println(e.getMessage());
    }
    // creating binary bitmap from source image
    LuminanceSource lumSource = new BufferedImageLuminanceSource(image);
    BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(lumSource));
    Hashtable<DecodeHintType, Object> hint = new Hashtable<DecodeHintType, Object>();
    hint.put(DecodeHintType.TRY_HARDER, BarcodeFormat.QR_CODE);
    // decoding
    QRCodeReader QRreader = new QRCodeReader();
    Result result = null;
    try
    {
      result = QRreader.decode(bitmap, hint);
    }
    catch (ReaderException e)
    {
      System.out.println("error during reading");
    }
    // getting output text
    String decodedText = result.getText();
    System.out.println(decodedText);
  }
}

2) А это код, используемый для декодирования этого QR который изначально работал нормально, но не знаю, почему он не работает прямо сейчас. И этот код не будет декодировать QR, упомянутые выше.

public class Decoder
{
    public static void main(String[] args)
    {
        // input image file
        File imageFile = new File("/Users/User/Desktop/QR/bigfinderQR.png");
        BufferedImage image = null;
        try
        {
            image = ImageIO.read(imageFile);
        }
        catch (IOException e)
        {
            System.out.println("io outch");
        }
        // creating binary bitmap from source image
        LuminanceSource lumSource = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(lumSource));
        Hashtable<DecodeHintType, Object> hint = new Hashtable<DecodeHintType, Object>();
        hint.put(DecodeHintType.TRY_HARDER, BarcodeFormat.QR_CODE);
        // decoding
        QRCodeReader QRreader = new QRCodeReader();
        Result result = null;
        try
        {
            result = QRreader.decode(bitmap, hint);
        }
        catch (ReaderException e)
        {
            System.out.println("error during reading");
        }
        // getting output text
        String decodedText = result.getText();
        System.out.println(decodedText);
    }
}

person user1139921    schedule 10.01.2012    source источник


Ответы (2)


Он просто бинаризируется на основе вычисленной яркости каждого пикселя. Все, что разумно похоже на темное на светлом, должно быть в порядке. Тысяча цветов — это хорошо. Если это свет в темноте (инвертированный), вам нужно инвертировать изображение или изменить код, чтобы инвертировать изображение. Это почти наверняка не проблема.

Искажение шаблонов поиска — дело более хитрое, поскольку таким образом легче сделать его недействительным. Вам нужно будет сохранить почти 1:1:3:1:1 темное-светло-темное-светло-темное соотношение, сканируя шаблон по горизонтали и вертикали. Немного скруглить углы — это нормально. Вы не могли бы, например, поместить пробел между черными модулями.

Можете ли вы опубликовать исходное изображение, которое вы пытаетесь декодировать? Я мог бы очень быстро сказать вам, что правильно, а что нет.

person Sean Owen    schedule 10.01.2012
comment
Привет, Шон, я отредактировал свой исходный пост, добавив в него некоторые подробности. не могли бы вы проверить эти изменения и дайте мне знать, что мне нужно искать. что я делаю, так это разрабатываю декодер/валидатор (по крайней мере, для QR прямо сейчас), используя Java с библиотекой ZXing. Мой английский не так хорош, поэтому, если я сделаю что-то непонятное, дайте мне знать, пожалуйста. Спасибо. - person user1139921; 10.01.2012
comment
И еще одна вещь о том, что вы сказали. Немного скруглить углы — это нормально. Есть ли ограничение на то, насколько я могу округлить или исказить каждое кодовое слово или модуль, и декодер все равно сможет прочитать. - person user1139921; 10.01.2012
comment
Я не мог дать жесткий предел. Я могу вам сказать, что декодер ищет точку, где поперечное сечение по вертикали и горизонтали видит черное и белое в пропорциях 1:1:3:1:1, плюс-минус какой-то небольшой коэффициент. Это удивительно снисходительно, но это та область изображения, с которой вам следует возиться меньше всего. - person Sean Owen; 11.01.2012

Изменение QR-кода всегда рискованно. ZXing настроен на работу в соответствии со стандартом ISO, а цветной код, не говоря уже о «образных шаблонах Finder», далеко не соответствует стандарту. Если вы исказите QR-код, вы должны ожидать, что некоторые, если не все, декодеры выйдут из строя.

ZXing предназначен для максимального успеха на стандартных образах. Некоторые из вещей, которые он делает для этого, на самом деле заставят его плохо работать с искаженными изображениями. Например, алгоритмы, улучшающие скорость декодирования изображений с тенями, могут работать против обработки равномерно освещенных, но цветных изображений.

А ZXing, как известно, чувствителен к искажениям шаблона поиска. Поскольку такие искажения нестандартны, менять это неинтересно.

person smparkes    schedule 10.01.2012