SmartCamera 高性能相机实时采集识别框架, 支持算法可配置化调优 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
pqpo
V2EX    程序员

SmartCamera 高性能相机实时采集识别框架, 支持算法可配置化调优

  pqpo 2018-08-27 16:19:20 +08:00 2020 次点击
这是一个创建于 2621 天前的主题,其中的信息可能已经有所发展或是发生改变。

English

SmartCamera 是一个 Android 相机拓展库,提供了一个高度可定制的实时扫描模块能够实时采集并且识别相机内物体边框是否吻合指定区域。如果觉得还不错,欢迎 star,fork。

语言描述起来略显生涩,具体实现的功能如下图所示,适用于身份证,名片,文档等内容的扫描、自动拍摄并且裁剪, 你也可以下载 apk 体验:

SmartCamera-Sample-debug.apk

在相机实现上,SmartCamera 以源码的方式引用了 Google 开源的 CameraView ,并且稍作修改以支持 Camera.PreviewCallback 回调来获取相机预览流。

SmartCameraView 继承于修改后的 CameraView,为其添加了一个选框蒙版视图( MaskView )和一个实时扫描模块( SmartScanner )。其中选框视图即是你看到的相机上面的那层选取框,并配备了一个由上到下的扫描效果,当然你也可以实现 MaskViewImpl 接口来自定义选框视图。

实时扫描模块( SmartScanner )是本库的核心功能所在,配合相机 PreviewCallback 接口回调的预览流和选框视图 MaskView 提供的选框区域 RectF,能以不错的性能实时判断出内容是否吻合选框

你也可以关注我的另一个库 SmartCropper: 一个简单易用的智能图片裁剪库,适用于身份证,名片,文档等照片的裁剪。

扫描算法调优

SmartScanner 提供了丰富的算法配置,使用者可以自己修改扫描算法以获得更好的适配性,阅读附录一提供的各参数使用说明来获得更好的识别效果。

为了更方便、高效地调优算法,SmartScanner 贴心地为你提供了扫描预览模式,开启预览功能后,你可以通过 SmartScanner 获取每一帧处理的结果输出到 ImageView 中实时观察 native 层扫描的结果,其中白线区域即为边缘检测的结果,白线加粗区域即为识别出的边框。

你的目标是通过调节 SmartScanner 的各个参数使得内容边界清晰可见,识别出的边框(白色加粗线段)准确无误

注:SmartCamera 在各方面做了性能以及内存上的优化,但是出于不必要的性能资源浪费,算法参数调优结束后请关闭预览模式。

接入

1.根目录下的 build.gradle 添加:

allprojects { repositories { ... maven { url 'https://jitpack.io' } } } 

2.添加依赖

dependencies { implementation 'com.github.pqpo:SmartCamera:v1.0.0' } 

注意:由于使用了 JNI, 请避免混淆

-keep class me.pqpo.smartcameralib.**{*;} 

使用

1. 引入相机布局,并启动相机(必要时启动预览)

<me.pqpo.smartcameralib.SmartCameraView android:id="@+id/camera_view" android:layout_width="match_parent" android:layout_height="match_parent"/> 
@Override protected void onResume() { super.onResume(); mCameraView.start(); mCameraView.startScan(); } @Override protected void onPause() { mCameraView.stop(); super.onPause(); if (alertDialog != null) { alertDialog.dismiss(); } mCameraView.stopScan(); } 

注:若开启了预览别忘了调用相应开启、结束预览的方法。

2. 修改扫描模块参数(可选,调优算法,同时按第 4 步中开启预览模式)

扫描模块各个参数含义详见附录一 
private void initScannerParams() { SmartScanner.DEBUG = true; SmartScanner.detectiOnRatio= 0.1f; SmartScanner.checkMinLengthRatio = 0.8f; SmartScanner.cannyThreshold1 = 20; SmartScanner.cannyThreshold2 = 50; SmartScanner.houghLinesThreshold = 130; SmartScanner.houghLinesMinLineLength = 80; SmartScanner.houghLinesMaxLineGap = 10; SmartScanner.firstGaussianBlurRadius = 3; SmartScanner.secOndGaussianBlurRadius= 3; SmartScanner.maxSize = 300; SmartScanner.angleThreshold = 5; // don't forget reload params SmartScanner.reloadParams(); } 

注: 修改参数后别忘记通知 native 层重新加载参数:SmartScanner.reloadParams();

3. 配置蒙版选框视图(可选,若要修改默认的视图, 或要修改选框区域)

配置 MaskView 各个方法的含义详见附录二 
final MaskView maskView = (MaskView) mCameraView.getMaskView();; maskView.setMaskLineColor(0xff00adb5); maskView.setShowScanLine(true); maskView.setScanLineGradient(0xff00adb5, 0x0000adb5); maskView.setMaskLineWidth(2); maskView.setMaskRadius(5); maskView.setScanSpeed(6); maskView.setScanGradientSpread(80); mCameraView.post(new Runnable() { @Override public void run() { int width = mCameraView.getWidth(); int height = mCameraView.getHeight(); if (width < height) { maskView.setMaskSize((int) (width * 0.6f), (int) (width * 0.6f / 0.63)); maskView.setMaskOffset(0, -(int)(width * 0.1)); } else { maskView.setMaskSize((int) (width * 0.6f), (int) (width * 0.6f * 0.63)); } } }); mCameraView.setMaskView(maskView); 

4. 配置 SmartCameraView

1. 开启预览:

mCameraView.getSmartScanner().setPreview(true); mCameraView.setOnScanResultListener(new SmartCameraView.OnScanResultListener() { @Override public boolean onScanResult(SmartCameraView smartCameraView, int result) { Bitmap previewBitmap = smartCameraView.getPreviewBitmap(); if (previewBitmap != null) { ivPreview.setImageBitmap(previewBitmap); } return false; } }); 

通过第一句代码开启了预览模式。
你可以通过 setOnScanResultListener 设置回调获得每一帧的扫描结果,其中 result == 1 表示识别结果吻合边框
若开启了预览模式,你可以在回调中使用 smartCameraView.getPreviewBitmap() 方法获取每一帧处理的结果。
返回值为 false 表示不拦截扫描结果,这时 SmartCameraView 内部会在 result 为 1 的情况下自动触发拍照,若你自己处理了扫描结果返回 true 即可。

2. 获取拍照结果,并且裁剪选框区域:

mCameraView.addCallback(new CameraView.Callback() { @Override public void onPictureTaken(CameraView cameraView, byte[] data) { super.onPictureTaken(cameraView, data); // 异步裁剪图片 mCameraView.cropImage(data, new SmartCameraView.CropCallback() { @Override public void onCropped(Bitmap cropBitmap) { if (cropBitmap != null) { showPicture(cropBitmap); } } ); } }); 

获取拍照结果的回调是 CameraView 提供的,你只需要在内部调用 SmartCameraView 提供的 cropImage 方法即可获取选框区域内的裁剪图片

注:其他关于 SmartCameraView 的使用方法同 CameraView ,另外更具体的使用方法请参考 app 内代码

附录

见 github

感谢


关于我:

目前尚无回复
关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5117 人在线   最高记录 6679       Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 27ms UTC 08:15 PVG 16:15 LAX 01:15 JFK 04:15
Do have faith in what you're doing.
ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86