文章目录
  1. 1. 前言
  2. 2. 问题描述
  3. 3. 技术解决方案
    1. 3.0.1. 原始图
    2. 3.0.2. 识别答题卡区域
    3. 3.0.3. 图象纠偏
    4. 3.0.4. 答案区域识别
  • 4. 算法质量
    1. 4.1. 算法正确率和召回率
    2. 4.2. 算法执行时间
  • 5. 算法的调试和移植
  • 6. 总结
  • 前言

    本人今年主要在负责猿题库 iOS 客户端的开发,本文旨在通过分享猿题库 iOS 客户端开发过程中的技术细节,达到总结和交流的目的。

    这是本技术分享系列文章的第二篇。本文涉及的技术细节是:答题卡扫描算法。

    问题描述

    我们在调研用户需求的时候,发现有些用户很喜欢我们的猿题库产品,因为我们会根据用户对当前课程的知识点掌握情况,智能地给他出题。但是部分用户还是习惯在纸上做题,所以我们提供了试卷打印功能。

    但是,用户如果在纸上答题,无法方便地将答案上传到我们的服务器上。如果我们没有了用户做题数据,就无法根据他的成绩,做针对性的推荐和分析。所以,我们想到一种办法: 用户像传统考试那样,将答题结果填涂在答题卡上,然后我们提供一种用手机摄像头采集填涂结果的答题卡扫描算法,方便用户上传答题数据。

    上图是一个我们试验用的答题卡,通过手机摄像头获取,从中可以看到,该答题卡有以下问题:

    1. 由于手机摄像头无法完全正对答题卡,拍照角度有偏曲,答题卡在拍照后并不是完全的矩形。
    2. 用户填涂区域可能并不饱满和完整。
    3. 答题纸边缘可能有用户的草稿或其它干扰识别的信息。

    技术解决方案

    我们尝试了多种识别方案,最终采用的方案如下:

    1. 图象预处理,压缩图像大小,转彩色图像为灰度图像
    2. 识别答题卡区域
    3. 图象纠偏
    4. 答案区域识别

    该方案及相关算法细节我们还在申请专利,由于专利还在申请过程中,所以我们这次仅展示上述主要步骤的示例图片。等专利完全申请结束后,我会在此将算法细节公开。

    上述主要步骤的示例图如下:

    原始图

    识别答题卡区域

    图象纠偏

    答案区域识别

    答案已标注在图片每个题号的右边位置:

    算法质量

    算法正确率和召回率

    我们用收集来的 1000 套样本数据对算法进行评测,最终结果是:扫描题目准确率达到 99.67%,召回率达到 99.14%。主要识别失败的样本是:页面严重扭曲弯折的答题卡。我们也在一直改进算法,希望能够给用户提供更加精准的扫描结果。

    算法执行时间

    我们觉得让用户直接对着答题卡用拍摄的方式动态识别,比先拍一张照片再识别的方式更加方便。所以我们对答题卡识别算法的执行时间进行了一系列优化,最终保证每次识别时间小于 0.1 秒,这样的识别时间非常快,基本上用户把手机摄像头对准答题卡,扫描结果就出来了。

    算法的调试和移植

    由于我们整个技术团队都使用 Mac 电脑进行开发,所以我们对于算法的调试都是在 Mac 平台上完成的,我使用了开源的图象处理库 OpenCV,在搭建 OpenCV 环境时遇到一些问题,最终完成环境搭建后,我将相关的经验总结在博文 《在 MacOS 和 iOS 系统中使用 OpenCV》 中。

    由于算法需要同时应用在 iOS 和 Android 平台,所以我主要用 C++ 语言实现算法。Xcode 可以很好地支持 Objective-C 语言和 C++ 语言混编,只需要将相关的源文件扩展名从 .m 改为 .mm 即可。而 Android 平台所采用的 Java 语言,也支持通过 JNI 的方式来调用 C++ 的代码。这样就可以方便地将识别算法移植到手机中了。

    总结

    本文介绍了猿题库 iOS 客户端采用的答题卡扫描算法的大致步骤,以及算法的质量和移植方案。