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

公司有个项目是这样的:要求扫条形码能识别上面的数字。于是选用了zxing进行扫码,可一定要吐槽的是:太慢了,一个条形码要扫5-10秒才能识别。于是换用了zbar进行扫码。
zbar的速度很快,秒扫,但后面发现一个严重的问题,太不准了!不准到一个条形码我能扫到好多种结果出来。例如下图:
android超好用基于zxing全屏扫码【详细步骤】(一)_第1张图片
这个图使用zbar我扫到3-5种不同的结果出来,当然,也有个办法能防止zbar扫出错误的结果:
改一下CaptureActivity的PreviewCallback:

PreviewCallback previewCb = new PreviewCallback() {
        public void onPreviewFrame(byte[] data, Camera camera) {
            Camera.Parameters parameters = camera.getParameters();
            Size size = parameters.getPreviewSize();

            Image barcode = new Image(size.width, size.height, "Y800");
            barcode.setData(data);

            int result = scanner.scanImage(barcode);
            if (result != 0) {
                previewing = false;
                mCamera.setPreviewCallback(null);
                mCamera.stopPreview();
                SymbolSet syms = scanner.getResults();
                Symbol bestSym = null;
                for (Symbol sym : syms) {
                    if(bestSym == null || bestSym.getQuality()< sym.getQuality()){
                        bestSym = sym;
                    }
                }
                if(bestSym == null)
                    return;

                int quality = bestSym.getQuality();
                Intent intent = new Intent();
                intent.putExtra("BarCode", quality>2?bestSym.getData():"");
                intent.putExtra("hasBarCode", quality>2);
                setResult(RESULT_OK, intent);
                finish();
            }
        }
    };

这里如果quality<2就算扫码失败,进行相应处理,可无语的是仍然不准。。。。

于是我问老大能用zxing吗?老大吐槽说:zxing扫条形码太慢了。。。于是我抓耳挠腮,想着解决问题的办法。
想到了如下方法:

1.找个新的扫码框架处理
2.改进zbar,让它识别率变高
3.改进zxing,让它识别速度变快

1.找个新的扫码框架

结果是失败了,没有合适的扫码框架,所有扫码都是在zbar或zxing基础上进行改进的,所以这条跳过

2和3

想了一下2一定是整个算法都要改了,可能要改c代码,这方面勉强看的懂比较弱,估计耗时会很久,于是还是选3.找到了http://blog.csdn.net/f820306455/article/details/54137182这篇文章,给了比较大的启发,图像算法什么的完全不会,但把握会的地方改了一下,基本秒扫。下面讲一下改造步骤。

改造步骤

1.删除bundle传bitmap的部分直接改为全屏识别


a.全屏扫样式更改
CameraManager.java
需要更改buildLuminanceSource()方法:

 public PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height) {
    return new PlanarYUVLuminanceSource(data, width, height, 0, 0,
            width, height);
            }

但单单这样改不行,会无法识别,需要去除外部的遮盖框,直接用全屏扫码:
ViewfinderView.java
需要更改onDraw():

public void onDraw(Canvas canvas) {
    postInvalidateDelayed(ANIMATION_DELAY, 0, 0,
                getWidth(), getHeight());
}

b.去掉传递图片(一般只需要扫码的条码号或者网址,扫码图片本身我们不关心,如果需要这部分需要对这个图片进行压缩处理,不然会出错)

MipActivityCapture.java
这里需要删掉handleDecode里面的bundle.putParcelable("bitmap", barcode);,barcode这个参数也可以不用传递了。
相应的在CaptureActivityHandler.java的handleMessage中只需要传递msg.obj,下面这句可以删掉:

 Bitmap barcode = bundle == null ? null :
            (Bitmap) bundle.getParcelable(DecodeThread.BARCODE_BITMAP);

然后把DecodeHandler.java的decode()方法也改一下:
删掉下面的部分

   Bundle bundle = new Bundle();
      bundle.putParcelable(DecodeThread.BARCODE_BITMAP, source.renderCroppedGreyscaleBitmap());
      message.setData(bundle);

2.增加自动对焦的速度

AutoFocusCallback.java的AUTOFOCUS_INTERVAL_MS的值改为500L【如果调整了相机形变建议1000L-1500L】,这个值不能过小,不然扫码还没扫全对焦已经结束了。会导致扫码结果不准

3.相机放大比例改为最高的1/10

修改CameraConfigurationManager的setDesiredCameraParameters():
去掉setZoom(parameters);改为:
这个是指相机倍数,建议1/5-1/10,1/5识别速度更快,1/10的视野更舒服
1/10:

1/5:

拍摄距离大概在25厘米左右

parameters.setZoom(parameters.getMaxZoom() / 10);

这样就可以了。
注意:资源没有进行相机音频权限申请,请打开引用权限进行测试,或者自己申请相关权限。
资源地址:http://download.csdn.net/download/yu_duan_hun/10261413

补充:然后还是不满意,因为相机变形了。。。各种网上的例子试过了,修正了形变就是扫不出来,郁闷。

后面无意按照:http://blog.csdn.net/qq_1991/article/details/53586408的第二点改了(第一点不要改无用且扫码失效),解决。实测发现这样会导致识别率降低,识别速度变慢,而且出现一定的错误几率。尤其是条形码很长的时候,以前秒扫的,现在难以识别了,请开发的各位考虑

防止链接失效,这里贴一下:
找到CameraConfigurationManager类的setDesiredCameraParameters(Camera camera)方法,将其中的代码注释,然后添加如下代码:

Camera.Parameters parameters = camera.getParameters();
List.Size> supportedPreviewSizes = parameters.getSupportedPreviewSizes();
int position = 0;
if(supportedPreviewSizes.size() > 2){
    position = supportedPreviewSizes.size() / 2 + 1;// supportedPreviewSizes.get();
}else {
    position = supportedPreviewSizes.size() / 2;
}

int width = supportedPreviewSizes.get(position).width;
int height = supportedPreviewSizes.get(position).height;
camera.setDisplayOrientation(90);
cameraResolution.x = width;
cameraResolution.y = height;
parameters.setPreviewSize(width, height);
setFlash(parameters);
setZoom(parameters);
camera.setParameters(parameters);

你可能感兴趣的:(归纳整理)