1.二维码动画
2.zxing和zbar的区别
3.功能介绍 扫描二维码 生成logo 图片的二维码识别
4.原理和重要的类
5.扫描识别率低的问题
6.扫描二维码放大效果
7.相机框架和效果分析
Android中二维码扫描的最常用库是zxing和zbar,zxing项目地址为https://github.com/zxing/zxing,
目前还有多个人在维护。zbar主要用C来写的,对速度有要求的可使用zbar,但目前没有在维护,项目地址:https://github.com/ZBar/ZBar。
zxing有多个人在维护,覆盖主流编程语言,也是目前还在维护的较受欢迎的二维码扫描开源项目之一。zbar则是主要用C来写的,速度极快,推出了iPhone的SDK和Android的相关调用方法(JNI),但这个项目已经有几年不维护了,目前并没有维护下去的意思,
在研究 ZXing 之前,我一直好奇二维码是根据什么生成的,并且最大能保存多少的信息,去查阅了一下资料,正好解决了我的疑问,在此介绍一下。
二维条码是指在一维条码(条形码)的基础上扩展出另一维具有可读性的条码,使用黑白矩形图案表示二进制数据,被设备扫描后可获取其中所包含的信息。一维条码的宽度记载着数据,而其长度没有记载数据。二维条码的长度、宽度均记载着数据。二维条码有一维条码没有的“定位点”和“容错机制”。容错机制在即使没有辨识到全部的条码、或是说条码有污损时,也可以正确地还原条码上的信息。二维条码的种类很多,不同的机构开发出的二维条码具有不同的结构以及编写、读取方法。
原理步骤:
1获取相机的一帧图片
2.对图片进行一定的预处理,只保留亮度信息,成为灰度图像
3.对灰度图像进行二维码解析,解析成功进入下一步,不成返回步骤2
4.默认是NV21.NV21属于YUV图像,和RGB图像有所不同
整个扫描过程分为三步:相机画面预览→捕获相机预览帧数据→处理并返回帧数据
根据二维码的原理,我们只需要图像的亮度信息来进行二维码解析,所以我们要把获取到的彩色图像转换为灰度图像。YUV图像转换为灰度图像的方法,以及RGB图像转换为灰度图像的方法,在后续文章中会有介绍,这里只说原理,具体实现就不再赘述。
其实条码扫描的过程很容易理解,就是将摄像头捕捉到的预览帧数组进行处理,发现其中的一维码或二维码并进行解码
QRCode,就是我们经常用手机扫一扫的二维码
二维码里面保存的信息:
Zxing
默认的是横屏扫码,多数情况下需要改为竖屏扫描。
提高识别
Zxing默认的是横屏扫码,多数情况下需要改为竖屏扫描。
CaptureActivity的配置,将Activity竖屏显示:
android:screenOrientation="portrait"
1
CameraManager类中的getFramingRectInPreview()方法,将left, right, top, bottom改变,供第4步的buildLuminanceSource内部计算使用。
//竖屏
rect.left = rect.left * cameraResolution.y / screenResolution.x;
rect.right = rect.right * cameraResolution.y / screenResolution.x;
rect.top = rect.top * cameraResolution.x / screenResolution.y;
rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y;
1
CameraConfigurationManager类中的setDesiredCameraParameters(OpenCamera camera, boolean safeMode)方法,在setParameters之前添加,设置PreviewDisplay的方向,使SurfaceView画面方向为竖直方向。
theCamera.setDisplayOrientation(90);
---------------------
demo
public class ScanActivity extends AppCompatActivity {
private CaptureManager capture;
private ImageButton buttonLed;
private DecoratedBarcodeView barcodeScannerView;
private boolean bTorch = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
barcodeScannerView = initializeContent();
buttonLed = findViewById(R.id.button_led);
/*根据闪光灯状态设置imagebutton*/
barcodeScannerView.setTorchListener(new DecoratedBarcodeView.TorchListener() {
@Override
public void onTorchOn() {
buttonLed.setBackground(getResources().getDrawable(R.drawable.image_bg_on));
bTorch = true;
}
@Override
public void onTorchOff() {
buttonLed.setBackground(getResources().getDrawable(R.drawable.image_bg_off));
bTorch = false;
}
});
/*开关闪光灯*/
buttonLed.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(bTorch){
barcodeScannerView.setTorchOff();
} else {
barcodeScannerView.setTorchOn();
}
}
});
capture = new CaptureManager(this, barcodeScannerView);
capture.initializeFromIntent(getIntent(), savedInstanceState);
capture.decode();
}
/**
* Override to use a different layout.
*
* @return the DecoratedBarcodeView
*/
protected DecoratedBarcodeView initializeContent() {
setContentView(R.layout.activity_scan);
return (DecoratedBarcodeView)findViewById(R.id.dbv);
}
@Override
protected void onResume() {
super.onResume();
capture.onResume();
}
@Override
protected void onPause() {
super.onPause();
capture.onPause();
barcodeScannerView.setTorchOff();
}
@Override
protected void onDestroy() {
super.onDestroy();
capture.onDestroy();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
capture.onSaveInstanceState(outState);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
capture.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return barcodeScannerView.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event);
}
}
来源: https://www.jianshu.com/p/de972f5652db
重要的类
3.CameraConfigurationManager.class中的initFromCameraParameters()方法
参考博客:
https://www.jianshu.com/p/1cf060c33147
https://blog.csdn.net/weixin_36570478/article/details/83062172