android 整理
优化zxing 扫描二维码出现卡顿 扫描慢等现象;
主要在几个方面解决这个问题
1. 扫描精度问题 PlanarYUVLuminanceSource
2. 二维码图像识别精度探究 小1 图像/像素编码格式
小2 二维码图像识别算法选择
3. 图像大小对识别精度的影响
4. 相机预览倍数设置及聚焦时间调整
1. 解决方案 :解决办法很简单,就是不仅仅使用聚焦框里的图像数据,而是采用全幅图像的数据。
public PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height) {
// 直接返回整幅图像的数据,而不计算聚焦框大小。
return new PlanarYUVLuminanceSource(data, width, height, 0, 0, width, height, false);
},
在使用zxing解析二维码时,允许事先进行相关配置,这个文件通过Map<DecodeHintType, ?>键值对来保存,
然后使用方法public void setHints(Map<DecodeHintType,?> hints)
来设置到相应的解码器中。DecodeHintType是一个枚举类;
2.1 从像素的角度,目前大部分Android手机摄像头设置的默认格式是yuv420sp
大部分二维码的识别都是基于二值化的方法,在色域的处理上,YUV的二值化效果要优于RGB,并且RGB图像在处理中不支持旋转
Bitmap是由ARGB值编码得到的,因此如果需要转换成YUV,还需要做一点小小的变换。
首先,如果每次都生成新的YUV数组,不知道在扫一扫解码时要进行GC多少次。。。所以就采用了静态的数组变量来存储数据,
只有当当前的长宽乘积超过数组大小时,才重新生成新的yuvs。其次,如果鉴于YUV的特性,长宽只能是偶数个像素点,
否则可能会造成数组溢出(不信可以尝试)。最后,使用完了Bitmap要记得回收,那玩意吃内存不是随便说说的。
2.2 二维码扫描精度和许多因素有关,最关键的因素是扫描算法。目前在图形识别领域中,较常用的二维码识别算法主要有两种,
分别是HybridBinarizer和GlobalHistogramBinarizer,这两种算法都是基于二值化,即将图片的色域变为黑白两个颜色,
然后提取图形中的二维码矩阵。实际上,zxing中的HybridBinarizer继承自GlobalHistogramBinarizer,并在此基础上做了功能性的改进。
GlobalHistogramBinarizer算法适合于低端的设备,对手机的CPU和内存要求不高。但它选择了全部的黑点来计算,因此无法处理阴影和渐变这两种情况。
HybridBinarizer算法在执行效率上要慢于GlobalHistogramBinarizer算法,但识别相对更有效。它专门为以白色为背景的连续黑色块二维码图像解析而设计,
也更适合用来解析具有严重阴影和渐变的二维码图像。
3. Android图片优化需要通过在解析图片的时候,设置BitmapFactory.Options.inSampleSize的值,根据比例压缩图片大小。
在进行图片二维码解析的线程中,通过设置不同的图片大小,来测试二维码的识别率。这个测试过程我忘记保存了,
只记得测试了压缩成最大宽高值为2048、1024、512、256和128像素的包含二维码的图片,但实际的测试结果是,
当MAX_PICTURE_PIXEL=256的时候识别率最高。
4. 通过测试可以发现,每个手机的最大放大倍数几乎是不一样的,这可能和摄像头的型号有关。如果设置成一个固定的值,
那可能会产生在某些手机上过度放大,某些手机上放大的倍数不够。索性相机的参数设定里给我们提供了最大的放大倍数值,
通过取放大倍数值的N分之一作为当前的放大倍数,就完美地解决了手机的适配问题。zxing默认的相机聚焦时间是2s,
可以根据扫描的视觉适当调整。聚焦时间的调整也很简单,在AutoFocusCallback这个类里,
调整AUTO_FOCUS_INTERVAL_MS这个值就可以了。
// 需要判断摄像头是否支持缩放
Parameters parameters = camera.getParameters();
if (parameters.isZoomSupported()) {
// 设置成最大倍数的1/10,基本符合远近需求
parameters.setZoom(parameters.getMaxZoom() / 10);
}