博主之前遇到过一个需求就是android实现远距离,不同角度,不同光线环境下要实现二维码的自动对焦放大,弱光补偿检测打卡闪光灯,还有就是二维码四周因裁剪不当或色彩区分度不够导致无法识别的问题,需要自动裁剪来识别二维码。
大家在android中可能都试用的zxing这个QRCode的开源库,但是你会发现zxing本身无法满足上述的需求,需要自己进行大量的改造,博主自己也尝试过改造,但效果并不理想,后来博主使用了HMS-ScanKit来实现。
方案一(推荐):使用HMS-ScanKit来实现
部分集成代码:
//在启动扫码Activity的地方添加动态权限申请
public void loadScanKitBtnClick(View view) {
requestPermission(CAMERA_REQ_CODE, DECODE);}private void requestPermission(int requestCode, int mode) {
ActivityCompat.requestPermissions(
this,
new String[]{Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE},
requestCode);
}
//扫码格式通过setHmsScanTypes指定为QR码,如果需要支持其他码可以自己指定
@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (permissions == null || grantResults == null) {
return;
}
if (grantResults.length < 2 || grantResults[0] != PackageManager.PERMISSION_GRANTED || grantResults[1] != PackageManager.PERMISSION_GRANTED) {
return;
}
if (requestCode == CAMERA_REQ_CODE) {
ScanUtil.startScan(this, REQUEST_CODE_SCAN_ONE, new HmsScanAnalyzerOptions.Creator().setHmsScanTypes(HmsScan.QRCODE_SCAN_TYPE).create());
}}
//在activity里面里面获取码结果
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode != RESULT_OK || data == null) {
return;
}
if (requestCode == REQUEST_CODE_SCAN_ONE) {
HmsScan obj = data.getParcelableExtra(ScanUtil.RESULT);
if (obj != null) {
this.textView.setText(obj.originalValue);
}
}}
具体实现方式转载地址:android二维码识别自动对焦放大,弱光补偿源码
方案二:使用zxing进行改造优化(效果不是很理想)
设计思路:
1、当要二维码处于摄像头画面中时,获取该二维码在屏幕中的宽度,与手机屏幕的宽度进行对比,小于手机屏幕宽度的1/4,则认为二维码在手机屏幕中较小(镜头较远),则需要放大摄像头焦距,而不需要移动手机来调整
2、摄像头焦距的放大。
主要实现代码:
@Override
public final Result decode(BinaryBitmap image, Map hints)
throws NotFoundException, ChecksumException, FormatException {
DecoderResult decoderResult;
ResultPoint[] points;
if (hints != null && hints.containsKey(DecodeHintType.PURE_BARCODE)) {
BitMatrix bits = extractPureBits(image.getBlackMatrix());
decoderResult = decoder.decode(bits, hints);
points = NO_POINTS;
} else {
//1、将图像进行二值化处理,1、0代表黑、白。( 二维码的使用getBlackMatrix方法 )
//2、寻找定位符、校正符,然后将原图像中符号码部分取出。(detector代码实现的功能)
DetectorResult detectorResult = new Detector(image.getBlackMatrix()).detect(hints);
if(activity!=null){
CameraManager cameraManager = activity.cameraManager;
ResultPoint[] p = detectorResult.getPoints();
//计算扫描框中的二维码的宽度,两点间距离公式
float point1X = p[0].getX();
float point1Y = p[0].getY();
float point2X = p[1].getX();
float point2Y = p[1].getY();
int len =(int) Math.sqrt(Math.abs(point1X-point2X)*Math.abs(point1X-point2X)+Math.abs(point1Y-point2Y)*Math.abs(point1Y-point2Y));
Rect frameRect = cameraManager.getFramingRect();
if(frameRect!=null){
int frameWidth = frameRect.right-frameRect.left;
Camera camera = cameraManager.getOpenCamera().getCamera();
Camera.Parameters parameters = camera.getParameters();
int maxZoom = parameters.getMaxZoom();
int zoom = parameters.getZoom();
if(parameters.isZoomSupported()){
if(len <= frameWidth/4) {//二维码在扫描框中的宽度小于扫描框的1/4,放大镜头
if (zoom == 0) {
zoom = maxZoom / 2;
} else if (zoom <= maxZoom - 10) {
zoom = zoom + 10;
} else {
zoom = maxZoom;
}
parameters.setZoom(zoom);
camera.setParameters(parameters);
return null;
}
}
}
}
//3、对符号码矩阵按照编码规范进行解码,得到实际信息(decoder代码实现的功能)
decoderResult = decoder.decode(detectorResult.getBits(), hints);
points = detectorResult.getPoints();
}
// If the code was mirrored: swap the bottom-left and the top-right points.
if (decoderResult.getOther() instanceof QRCodeDecoderMetaData) {
((QRCodeDecoderMetaData) decoderResult.getOther()).applyMirroredCorrection(points);
}
Result result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), points, BarcodeFormat.QR_CODE);
List byteSegments = decoderResult.getByteSegments();
if (byteSegments != null) {
result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments);
}
String ecLevel = decoderResult.getECLevel();
if (ecLevel != null) {
result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel);
}
if (decoderResult.hasStructuredAppend()) {
result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_SEQUENCE,
decoderResult.getStructuredAppendSequenceNumber());
result.putMetadata(ResultMetadataType.STRUCTURED_APPEND_PARITY,
decoderResult.getStructuredAppendParity());
}
return result;
}
github源码地址:GitHub - Alvin3225/CommonLibrary: common librarieshttps://github.com/Alvin9234/CommonLibrary
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)