android超好用基于zxing全屏扫条形码【详细步骤】(二)

倾然丶 夕夏残阳落幕 提交于 2019-12-04 19:18:19

经过了android超好用基于zxing全屏扫码【详细步骤】(一),我已扫了3天的条形码,但是还不太满意,原因如下:当相机正着和反着的时候能实现扫码,侧着不行。怎么能实现任意角度扫码呢?

1.调整摄像头方向

参考了:http://blog.sina.com.cn/s/blog_7b7ddaf90101dval.html
首先是相机问题:相机旋转时不太舒服,参考了这篇文改了一下,没改角度依然默认orientation是portrait。这篇文章讲的不太清楚,这里稍微展开:首先改一下扫码那个CameraManager添加一个方法setCameraDisplayOrientation这个可以调整摄像头方向,

 public void setCameraDisplayOrientation(Activity activity, int cameraId) {
    android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
    android.hardware.Camera.getCameraInfo(cameraId, info);
    int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
    int degrees = 0;
    switch (rotation) {
      case Surface.ROTATION_0:
        degrees = 0;
        break;
      case Surface.ROTATION_90:
        degrees = 90;
        break;
      case Surface.ROTATION_180:
        degrees = 180;
        break;
      case Surface.ROTATION_270:
        degrees = 270;
        break;
      default:
        break;
    }
    int result;
    if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
      result = (info.orientation + degrees) % 360;
      result = (360 - result) % 360; // compensate the mirror
    } else { // back-facing
      result = (info.orientation - degrees + 360) % 360;
    }
    camera.setDisplayOrientation(result);
  }

然后在扫码那个Activity中添加如下方法:

 @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
                               int height) {
                               //第二个参数0代表前置摄像头,1代表后置摄像头
        CameraManager.get().setCameraDisplayOrientation(this,1);
    }

这样当摄像头旋转的时候,视野比较舒适连续,然而实践时并不能实现任意角度扫码。

于是我脑洞了一下:现在是正和反的条形码都能识别,如果识别的时候同时识别0度和90度两种就可以实现任意角度识别了,0度能识别就代表0度和180度能识别,90度能识别就代表90和270能识别,再加上允许一定的角度误差,几乎能识别所有角度了,于是我修改了DecodeHandler的decode方法,如下:

private void decode(byte[] data, int width, int height) {
    long start = System.currentTimeMillis();
    Result rawResult = null;

    //modify here
    byte[] rotatedData = new byte[data.length];
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++)
            rotatedData[x * height + height - y - 1] = data[x + y * width];
    }
    int tmp = width; // Here we are swapping, that's the difference to #11
    width = height;
    height = tmp;

    PlanarYUVLuminanceSource source = CameraManager.get().buildLuminanceSource(rotatedData, width, height);
    BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
    try {
      rawResult = multiFormatReader.decodeWithState(bitmap);
    } catch (ReaderException re) {
      // continue
      try {
        source = CameraManager.get().buildLuminanceSource(data, height, width);
        bitmap = new BinaryBitmap(new HybridBinarizer(source));
        rawResult = multiFormatReader.decodeWithState(bitmap);
      } catch (NotFoundException e) {
      }
    } finally {
      multiFormatReader.reset();
    }

    if (rawResult != null) {
      long end = System.currentTimeMillis();
      Log.d(TAG, "Found barcode (" + (end - start) + " ms):\n" + rawResult.toString());
      Message message = Message.obtain(activity.getHandler(), R.id.decode_succeeded, rawResult);
      Bundle bundle = new Bundle();
//      bundle.putParcelable(DecodeThread.BARCODE_BITMAP, source.renderCroppedGreyscaleBitmap());
//      message.setData(bundle);
      //Log.d(TAG, "Sending decode succeeded message...");
      message.sendToTarget();
    } else {
      Message message = Message.obtain(activity.getHandler(), R.id.decode_failed);
      message.sendToTarget();
    }
  }

试了一下,至少四个角度支持,允许大约30度的误差,very good!又解决了一个难题。

可试着试着发现扫码正确率又降低了T T,这个问题一直再纠结,各种优化后都对扫码的正确率有一定影响,下次要好好了解图像识别的原理了。

建议大家测试扫条形码的时候,采用现实条码,连续不同角度扫50次不出错才能确定当前修改的成果是有效的。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!