65.9K
CodeProject 正在变化。 阅读更多。
Home

C# - 光学标记识别 (OMR) 引擎 2.1a (2016年3月)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.93/5 (30投票s)

2018年1月24日

CPOL

9分钟阅读

viewsIcon

246412

downloadIcon

1146

用于创建、检测和分析光学标记表(也称为气泡纸)的 API - 这是我于2012年编写的 C# OMR 引擎 1.0 的升级版本。

[重要通知]

我经常收到关于该项目可能存在的问题和未来的电子邮件。当腾不出时间回复所有这些信息时,我感到很伤心。我是在2016年编写这个程序的,之后一直忙于更重要的研究。如果您对这篇文章的回复需要更长时间,请您不要介意。

谁应该阅读?

  • 桌面、.NET 和 ASP.NET 开发者,他们正在寻找一个解决方案来将 OMR 识别集成到他们自己的应用程序中。
  • 那些正在为他们的学术机构寻找解决方案以实现气泡纸检查自动化的开发者。
  • 学习与 OMR 相关的图像处理的学生。
  • 那些刚接触 AForge.Net 并想学习一些基本知识的人。

第一类关注者应该留意以下标签:OMR Engine、OMR Console 和 OMR Reader。

第二类关注者应该寻找一个名为 OMR Tools 的可执行文件。

第三类和第四类关注者应该更多地关注 OMR Reader 和 image Utils。

背景

本文讨论了我最初于2012年编写的 OMR 引擎第二版的又一次更新。强烈建议读者先体验引擎的第一个版本,该版本位于 C# - 光学标记识别 (OMR) 引擎 1.0

我可能很久以前就放弃了这个项目,因为这个世界留给老式项目的时间很少了。我们已经转向 Xbox One 的 Kinect 2,这是一个图像处理的奇迹。但是,来自开发者和学生的请求和支持给了我足够的动力来撰写最新版本以及这篇文章。

对于那些之前因为我删除了源代码而感到失望的读者,我深表歉意,但我有我的理由。现在源代码已经在这里了,我尝试通过逐行注释使其更容易理解。

有些人可能会问,“为什么要做重复工作?”因为市面上有无数的 OMR 引擎甚至嵌入式系统。但这个项目是开源的,并且是用高级语言编写的。因此,与其他 .NET 应用程序集成不是问题。这正是我从一开始就一直投入时间的主要原因。

有什么新功能?

V2.1 更新 (2015年12月) “让它对 C# 开放,并开始使其跨平台”。

  • 在 CodeProject 文章中添加了源代码。
  • 为 GUI 界面添加了 ToolTip 文本,以帮助您。
  • 修复了许多 Bug,包括与注册表相关的异常。
  • 添加了一个新的工具,用于创建支持随机答案键的答题卡。
  • 添加了一个命令行工具,适用于那些不想被 .NET 环境困扰或希望从其他桌面应用程序访问该引擎的用户。
  • 为 OMR Engine 类(解决方案中最常用的类)的每一行添加了注释。
  • 内置支持答案分数计算。
  • 以及许多小型改进,以避免异常和故障。
  • 添加了更好的事件驱动方法,用于跟踪进程进行中的情况。那些无法忍受没有进度更新的进程的人会喜欢这个(就像我一样)。
  • 在 OMR 答题卡提取代码中进行了一些小的改进、调整和优化(算法保持不变)。

V2 配备了许多调整、更新、添加和移除。不幸的是,它完全移除了 OMR 答题卡的向后兼容性。

  1. 图像检测和分析现在更精确、更可靠、更快。
  2. 添加了一个完整的类,以更面向对象的方式管理 OMR 答题卡。
  3. 图像颜色校正方法已从试错法改为绝对法。
  4. 能够异步处理图像。
  5. XML 答题卡存储已更改为访问 2007 数据库。
  6. 添加了 OMR.helpers.dbOps 类,用于集中管理所有数据库操作。
  7. 改进了图像检测算法,以消耗更少的内存。
  8. 基于参数的输出质量和性能调整。
  9. 一个不错的 GUI,可以创建您自己的 OMR 答题卡。

[常见问题解答] 使用术语和基本概念

本节包含对最常问问题的解答。我建议所有人在继续之前阅读本节。

我们大多数人都知道 OMR 答题卡看起来是这样的。

此纸张上的黑色标记通常用于页面对齐检测。

但是,本引擎不使用此类纸张。本引擎使用的纸张看起来是这样的。

从相机拍摄的源图像可能看起来很粗糙。

角落里的四个方形块用于从相机图像中提取 OMR 答题卡。

答题卡定义保存在 Access 数据库中,以便移植。此数据库的结构非常简单且不言自明。但是,除非您想对引擎进行一些概念级别的更改,否则您无需理解它。

创建 OMR 答题卡

您无需了解如何创建这些答题卡,因为解决方案中有一个名为“OMR.forms.asnwerSheetDesigner”的类。

或者,您可以直接运行 OMR Tools 可执行文件来快速访问此窗口。

表单看起来是这样的。

OMR Sheet Designer

这是创建您自己选择的 OMR 答题卡的最简单、最全面的 GUI。为此,请理解以下术语。

  • 数字块:可用于记录学生注册号或学号以及答题卡的随机化代码。此块可以放置在不可见网格的任何位置。数字位数可以更改。只需将鼠标悬停在块的下边框上。这些块的视觉样式也可以更改。
  • 答案块:可用于记录选择题(MCQ)或是非题的答案。处理方式与注册块类似。这些块的视觉样式也可以更改。
  • 空白块/文本输入区域:一些机构使用手写签名/手写标记作为记录保存实践和其他原因。此块可用于识别纸张上的空白区域,需要此类输入。

最实用的功能之一是背景图像。您可以使用任何 PDF 文件作为答题卡的背景。此功能通常用于在答题卡上添加自定义文本和图形,这些文本和图形可能(也可能不)是 OMR 结果的一部分。只需参考上面的示例图像即可获得灵感。

编辑完成后,选择一个答题卡名称,然后保存数据库。这将生成三个文件:一个数据库文件、一个高分辨率的光栅化图像和一个可打印的 PDF 文件。不幸的是,我忘记将可打印文件移到选定的输出目录,它们被复制到了项目目录中。请不要介意。

答案键制作器

为了自动化创建 OMR 答案键的过程,开发了 OMR Answer key Maker。GUI 包含帮助提示,无需解释。

Answer Key Designer

OMR 控制台

对于那些不想要任何 C# 代码并希望从其他应用程序使用该引擎的用户,可以选择使用 OMR 控制台。在命令行中键入“Help”以阅读有关用法的信息。该控制台还可以接受命令行启动参数,无需用户手动输入。

OMR Console

代码组织

我已尽力简化与先前版本相比的各项工作。从上面的附件下载并解压缩源代码或相关发行版,然后了解代码。

设置好一切后,您会发现有一个主命名空间,其中包含引擎。以下是它们的用途:

  • OMR >> 包含引擎的命名空间
  • OMR.helpers >> 包含一些类,用作辅助类,例如数据库读取、图像实用程序和 PDF 转换包装器。
  • OMR.OMRReader >> 引擎的核心类,实际执行答题卡检测和分析算法。
  • OMR.OMREngine >> 与其名称不同,此类实际上是 OMR.OMRReader 的包装器。为了最方便地使用该命名空间,这是最推荐的类。
  • 其他所有内容都起着明显的作用,但当您开始使用 OMR.OMREngine 时,与您无关。

设置一切

无需下载任何外部库。唯一缺少的是 Ghost script DLL,它将在需要时自动下载。只需解压缩源代码并进行编译。使用提供的示例文件即可开始。

Using the Code

除非您想深入研究引擎的底层并进行修改(我觉得这很有趣),否则您只会使用一个类:“OMR.OMREngine”。

这是声明引擎并使用它的方法。

您需要

  1. 包含相机/扫描仪图像的 *.jpg 文件。
  2. 包含 OMR 答题卡定义的数据库地址。您无需了解数据库的结构。(我稍后会讨论它。)
  3. 来自数据库的 OMR 答题卡名称。(我稍后会讨论它。)
 OMR.OMREngine engine = new OMREngine(filenamet.Text, "omrSheet1.accdb", "A4_sq_1");
            engine.onAsyncCompletion += 
            new OMR.AsyncCompletionEventHandler(engine_onAsyncCompletion);
            engine.onAsyncProgressUpdated += 
            new OMR.AsyncProgressEventHandler(engine_onAsyncProgressUpdated);
            engine.StartProcessAsync();

很简单吧?是的。事件声明不是强制性的。您可以使用同步方法,或者从 engine.Progressengine.ResultReady 属性获取异步进程的状态。

如果进程退出时 ResultReady 设置为 true,则表示已检测并分析了一张答题卡。

结果组织在“engine”成员的属性中。我稍后将讨论答题卡的结构,但根据从数据库查询的定义,结果将被编译。

以下可能是您正在寻找的内容。

  • engine.NumberBlocks[index]
    • >RecognisedImage
    • >BinaryMaskedOMs
    • >BlockID
    • >NumberOfLines
    • >Options
    • >StartOfInd
  • engine.AnswerBlock[index]
    • >RecognisedImage
    • >BinaryMaskedOMs
    • >BlockID
    • >Digits
  • engine.EmptyBlock[index]
    • >RecognisedImage
    • >BlockID

所有这些块还包含 ToString 重载,可将结果和分数转换为人类可读的 string

此类中还有许多其他有用的属性和函数。所有这些都有文本说明。只需使用 Visual Studio 阅读这些详细信息。

此引擎的概念是为您提供一个 API。这是最基本和最有组织的信息,需要进行分析和图像处理。其他一切都由开发人员决定。例如:

  • BinaryMaskedOMs 转换为答题卡的得分。
  • RegistrationBlocks 获取学生注册号/答题卡的随机化代码。
  • 将结果整理成 MS Excel 或 Word 格式,甚至自动发送给相关部门。

项目历史和未来

本文是我另一篇文章的续集,C# - 光学标记识别 (OMR) 引擎 1.0

此版本被标记为 alpha,仅仅是因为我还没有测试所有代码分支,也没有进行我们通常进行的所有质量控制检查。但是,我已经测试了它用于非常基本的功能,并且效果非常好。 我是我公司的唯一员工,在没有报酬的情况下无法自愿做这么多事情。 在未来的版本中,将完成以下工作,敬请关注。

  • 100% 代码覆盖率
  • 移除所有冗余/辅助代码
  • 使用 MATLAB 进行图像处理,以实现更强大的图像识别。
  • 移除调试辅助代码。
  • 优化多线程性能。
  • 能够直接从网络摄像头图像/扫描仪图像获取和转换。

历史

  • 2018年1月24日:初始版本
© . All rights reserved.