小言_互联网的博客

“扫五福”的实现原理和技术详解

385人阅读  评论(0)

前言

年关扫福的号角一吹响,日常社交用语里就多了一句:你有敬业福嘛?今年是集五福的第6年,这场搭载手机的年味仪式,让古早的“福”文化又登上新时代的C位。

不难发现,我们拿着手机,不管面对的是笔端纤细的手写福,还是电子屏幕上五花八门的花体福,“扫福”功能都能轻易识别。那么,是什么技术实现扫福,又让扫福得以如此简单易操作,本文试着对扫福进行一次技术详解,看完这篇,没准你的app也能来一次“万物皆可扫”的有趣活动。

 “AR扫福”技术解读

1、OCR原理

“AR扫福”加持的第一个技术是光学字符识别技术(Optical Character Recognition, OCR),手机等电子设备扫描任意载体上较为清晰的字符,通过对字符明暗的检测确定其形状,再通过字符形状识别翻译输出对应的文字。

常见的OCR应用

如今OCR技术已经深入生活的诸多方面。例如,身份证、护照、车牌号等证件识别,纸质文档扫描识别,时下一些在线答题的学习软件也凭借OCR实现了拍照搜题功能。

OCR的技术路线 

 

预处理环节的五大“门神”

 (1)灰度化
字符输入设备后,在预处理环节,首先经过“灰度化”处理,降低复杂背景环境的干扰,只保留敏感度信息的图片。灰度化满足的公式一般为:Gray=0.299R+0.587G+0.114B
(2)二值化
图片灰度化后进行“二值化”做进一步背景简化,环节将图片简化为非黑即白的前景信息和背景信息,前景信息是需要读取的信息为为黑色,背景信息为白色。
(3)降噪
要完成更精确的识别还需要对图片进行降噪处理。图像噪声是指存在于图像数据中的不必要的或多余的干扰信息,图像噪声的来源在图像获取和传递过程中收到传感器材质、工作环境以及传输介质等的各种影响,都会产生。二值化后的字符周围小黑点越多图片噪声越大,影响字符的精确切割。所以二值化后再进行图片降噪成为必要。
(4)倾斜矫正
降噪处理后,为了方便后续的字符切割,还要进行一道倾斜校正的工序,即将歪斜的图片以字符的公正排布进行图片矫正。霍夫变换时最常用的矫正方法,基于二值图片进行直线检测,基本原理在于利用点与线的对偶性,将断续的字符连城一条直线,在进行直线水平矫正。
(5)字符切割
经过重重筛选,最后筛出具有明确清晰字符的图片,就可进行行切分和字符切分。为下一步字符识别和翻译输出做准备。

字符识别和翻译

 以上一顿操作,提取出真实需要的内容,处理清晰化的字符再与模板库进行匹配,输出匹配结果。 

2、用ML机器学习实现“扫福”功能

华为机器学习服务(HUAWEI ML Kit)提供文本识别能力,利用OCR技术,将拍摄到的文字提取出来,转换为文本信息。除了简体中文,该能力还支持在手机端识别日文、韩文、英文、西班牙文、葡萄牙文、意大利文、德文、法文和俄文,下面我们就来看看如何简单地实现这一强大功能。

在开始开发前,需要先配置HMS Core的Maven仓地址,具体可以参考:配置Maven仓地址

之后将文本识别的基础SDK包和语言包添加到依赖中。


  
  1. dependencies{
  2. ……
  3. // 引入基础SDK
  4. implementation 'com.huawei.hms:ml-computer-vision-ocr:2.0.5.300'
  5. // 引入中英文文字识别模型包
  6. implementation 'com.huawei.hms:ml-computer-vision-ocr-cn-model:2.0.5.300'
  7. ……
  8. }

为了实现实时根据拍摄到的画面进行文字识别,我们选用ML Kit的端侧视频流文本识别能力,首先创建并初始化一个LensEngine对象


  
  1. private LensEngine lensEngine = null;
  2. private void createLensEngine() {
  3. if ( this.lensEngine == null) {
  4. this.lensEngine = new LensEngine( this, this.cameraConfiguration, this.graphicOverlay);
  5. }
  6. try {
  7. this.lensEngine.setMachineLearningFrameTransactor( this.localTextTransactor);
  8. isInitialization = true;
  9. } catch (Exception e) {
  10. Toast.makeText(
  11. this,
  12. "Can not create image transactor: " + e.getMessage(),
  13. Toast.LENGTH_LONG)
  14. .show();
  15. }
  16. }

接下来创建文本识别的处理类“LocalTextTransactor”,继承BaseTransactor<MLText>接口

public class LocalTextTransactor extends BaseTransactor<MLText>

在其中的LocalTextTransactor方法中,创建一个MLTextAnalyzer文本分析器,并且将识别的语种设置为中文“zh”


  
  1. MLLocalTextSetting options = new MLLocalTextSetting.Factory()
  2. .setOCRMode(MLLocalTextSetting.OCR_TRACKING_MODE)
  3. .setLanguage(language)
  4. .create();
  5. MLTextAnalyzer analyzer = MLAnalyzerFactory.getInstance().getLocalTextAnalyzer(options);

当获取到文本的识别结果之后,将识别到的字符打印显示到对应的位置


  
  1. protected void onSuccess(
  2. Bitmap originalCameraImage,
  3. MLText results,
  4. FrameMetadata frameMetadata,
  5. GraphicOverlay graphicOverlay) {
  6. this.mlText =results;
  7. this.latestImageMetaData = frameMetadata;
  8. graphicOverlay.clear();
  9. List<MLText.Block> blocks = results.getBlocks();
  10. if ((Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) && originalCameraImage != null) {
  11. CameraImageGraphic imageGraphic = new CameraImageGraphic(graphicOverlay, originalCameraImage);
  12. graphicOverlay.addGraphic(imageGraphic);
  13. }
  14. if (blocks.size() > 0) {
  15. this.mCount = 0;
  16. this.mHandler.sendEmptyMessage(Constant.SHOW_TAKE_PHOTO_BUTTON);
  17. } else {
  18. this.mCount++;
  19. if ( this.mCount > 1) {
  20. this.mHandler.sendEmptyMessage(Constant.HIDE_TAKE_PHOTO_BUTTON);
  21. }
  22. }
  23. for (int i = 0; i < blocks.size(); i++) {
  24. List<MLText.TextLine> lines = blocks. get(i).getContents();
  25. for (int j = 0; j < lines.size(); j++) {
  26. // Display by line, without displaying empty lines.
  27. if (lines. get(j).getStringValue() != null && lines. get(j).getStringValue().trim().length() != 0) {
  28. BaseGraphic textGraphic = new LocalTextGraphic(graphicOverlay,
  29. lines. get(j));
  30. graphicOverlay.addGraphic(textGraphic);
  31. }
  32. }
  33. }
  34. graphicOverlay.postInvalidate();
  35. }

调用LensEngine的run方法,启动相机读取视频流,即可进行识别


  
  1. SurfaceView mSurfaceView = findViewById(R.id.surface_view);
  2. try {
  3. lensEngine.run(mSurfaceView.getHolder());
  4. } catch (IOException e) {
  5. // 异常处理逻辑。
  6. }
  7. 识别完成之后,停止分析器,释放对应的视频流资源
  8. if (analyzer != null) {
  9. try {
  10. analyzer.stop();
  11. } catch (IOException e) {
  12. // 异常处理。
  13. }
  14. }
  15. if (lensEngine != null) {
  16. lensEngine.release();

总结与思考

凭借OCR技术和华为机器学习能力,能轻易实现“扫福”,强大的功能带来的识别范围不止于“福”字,“万物皆可扫”也成为可能,如何更好地利用功能为运营加分,为增长蓄能,“扫福”已经做了一个不错的示范,更好的范例和成果等你去大胆实践。

>>访问华为开发者联盟官网,了解更多相关内容

>>获取开发指导文档

>>华为移动服务开源仓库地址:GitHubGitee

关注我们,第一时间了解华为移动服务最新技术资讯~


转载:https://blog.csdn.net/HUAWEI_HMSCore/article/details/113770425
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场