唐巧的博客

猿题库iOS客户端的技术细节(二):答题卡扫描算法

字数统计: 1.1k阅读时长: 3 min
2013/10/19

前言

本人今年主要在负责猿题库 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 客户端采用的答题卡扫描算法的大致步骤,以及算法的质量和移植方案。

CATALOG
  1. 1. 前言
  2. 2. 问题描述
  3. 3. 技术解决方案
    1. 3.1. 原始图
    2. 3.2. 识别答题卡区域
    3. 3.3. 图象纠偏
    4. 3.4. 答案区域识别
  4. 4. 算法质量
    1. 4.1. 算法正确率和召回率
    2. 4.2. 算法执行时间
  5. 5. 算法的调试和移植
  6. 6. 总结