Не удается прочитать QR-код с камеры

#android #zxing

#Android #zxing

Вопрос:

Редактировать:

Поиграв с ним несколько часов, я пришел к выводу, что проблема в качестве изображения. Например, первое изображение — это то, как оно появилось с камеры. Декодер не может его прочитать. Второе изображение превращается в черно-белое с регулируемой контрастностью, и декодер отлично его считывает.

Поскольку демонстрационное приложение, поставляемое с zxing, способно считывать первое изображение с монитора за несколько секунд, я думаю, что проблема может быть в какой-то настройке глубоко в библиотеке zxing. Он не ждет достаточно долго, чтобы обработать изображение, но выдает NotFound почти мгновенно.

введите описание изображения здесь
введите описание изображения здесь


Я создаю простое приложение для чтения QR-кодов. Вот скриншот. Верхняя черная область — это surfaceview, который показывает кадры с камеры. Он работает нормально, только вы не видите его на скриншоте.

Затем, когда я нажимаю кнопку, растровое изображение берется из этого surfaceview, помещается в ImageView ниже и пытается быть прочитанным библиотекой zxing.

Тем не менее, он выдаст NotFoundException. :/

 **10-17 19:53:15.382: WARN/System.err(2238): com.google.zxing.NotFoundException
10-17 19:53:15.382: WARN/dalvikvm(2238): getStackTrace() called but no trace available**
  

С другой стороны, если я обрезаю qr-изображение с этого снимка экрана, помещаю его в imageview (вместо ленты с камеры) и пытаюсь его декодировать, все работает нормально. Поэтому само QR-изображение и его качество в порядке… но тогда почему он не декодируется в первом сценарии?

Спасибо!

введите описание изображения здесь

 public void dec(View v)
{

ImageView ivCam2 = (ImageView)findViewById(R.id.imageView2);
ivCam2.setImageBitmap(bm);

BitmapDrawable drawable = (BitmapDrawable) ivCam2.getDrawable();
Bitmap bMap = drawable.getBitmap();

TextView textv = (TextView) findViewById(R.id.mytext);

LuminanceSource source = new RGBLuminanceSource(bMap); 
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Reader reader = new MultiFormatReader();
try {
     Result result = reader.decode(bitmap);
     Global.text = result.getText(); 
        byte[] rawBytes = result.getRawBytes(); 
        BarcodeFormat format = result.getBarcodeFormat(); 
        ResultPoint[] points = result.getResultPoints();
        textv.setText(Global.text);

} catch (NotFoundException e) {
    textv.setText("NotFoundException");
} catch (ChecksumException e) {
    textv.setText("ChecksumException");
} catch (FormatException e) {
    textv.setText("FormatException");
}  

}
  

как создается растровое изображение:

     @Override
    public void surfaceCreated(SurfaceHolder holder) 
    {
            try
            {
                    this.camera = Camera.open();
                    this.camera.setPreviewDisplay(this.holder);

                    this.camera.setPreviewCallback(new PreviewCallback() {

                      public void onPreviewFrame(byte[] _data, Camera _camera) {

                        Camera.Parameters params = _camera.getParameters();
                           int w = params.getPreviewSize().width;
                           int h = params.getPreviewSize().height;
                           int format = params.getPreviewFormat();
                           YuvImage image = new YuvImage(_data, format, w, h, null);

                           ByteArrayOutputStream out = new ByteArrayOutputStream();
                           Rect area = new Rect(0, 0, w, h);
                           image.compressToJpeg(area, 50, out);

                           bm = BitmapFactory.decodeByteArray(out.toByteArray(), 0, out.size());

                      }
                    });

            }
            catch(IOException ioe)
            {
                    ioe.printStackTrace(System.out);
            }
    }
  

Комментарии:

1. Как вы получаете растровое изображение из SurfaceView? Используете ли вы SurfaceView.getDrawingCache() ?

2. Нет, см. Выше. 🙂 Но я предполагаю, что с растровым изображением все в порядке, так как оно отображается в imageview.

3. можете ли вы добавить строку e.printStackTrace() в оператор catch, чтобы мы могли видеть, что происходит не так?

Ответ №1:

Я написал этот код. Быстрое возвращение не проблема. Декодирование происходит очень быстро на мобильном устройстве и очень быстро на рабочем столе.

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

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

Тем не менее, вы можете сделать еще больше. Например, установите подсказку TRY_HARDER для декодера, чтобы он тратил намного больше процессора на попытку декодирования. Вы также можете попробовать другую реализацию бинаризатора, чем HybridBinarizer по умолчанию.

(Остальное выглядит просто отлично. Я предполагаю, что RGBLuminanceSource это получение данных в ожидаемом формате; это должно быть из Bitmap )

Комментарии:

1. Спасибо за ответ! Не могли бы вы, пожалуйста, объяснить, куда я должен поместить этот TRY_HARDER и как мне попробовать разные реализации бинаризатора? Еще раз спасибо! 🙂

2. decode() содержит несколько Hashtable подсказок. Установите значение key DecodeHintType.TRY_HARDER Boolean.TRUE в этом аргументе. Вы видите, где вы используете HybridBinarizer ? Попробуйте другую реализацию.

3. Спасибо… Я установил для него значение TryHarder, теперь это занимает примерно 2 секунды, но все равно не дает результата. :/

4. Да, но это не то, что я думал, было проблемой. Вы выделили правильное пустое пространство вокруг изображения, как я упоминал выше?

5. Да, я сделал, все еще ничего. 🙂 Думаю, мне придется реализовать ZXING, как говорится в damianflannery.wordpress.com/2011/06/13 /… , надеюсь, я помогу. 🙂

Ответ №2:

Посмотрите на это: http://zxing.org/w/docs/javadoc/com/google/zxing/NotFoundException.html Исключение означает, что штрих-код не был найден на изображении. Мое предложение состояло бы в том, чтобы использовать вашу работу, которая работает, вместо того, чтобы пытаться декодировать не обрезанное изображение.

Комментарии:

1. Ну, чтобы заставить это работать, я вручную обрезал изображение в Photoshop из скриншота и загрузил его в декодер, просто чтобы убедиться, что это сработает, и это сработало. (для этого изображение в порядке) Вы предлагаете мне делать это каждый раз, когда я хочу что-то отсканировать ??? : P

2. В вашем описании вы ничего не сказали об обрезке изображения вручную. Я предположил, что вы обрезали его в программном обеспечении.