经过了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次不出错才能确定当前修改的成果是有效的。
来源:CSDN
作者:yu_duan_hun
链接:https://blog.csdn.net/yu_duan_hun/article/details/79398363