本帖最后由 云天 于 2026-6-21 18:15 编辑
【项目简介】每次考试后手动批改选择题,不仅耗时费力,还容易出错。我利用LattePanda Alpha开发板和普通USB摄像头,配合一个纯前端HTML网页,制作了一套智能答题卡自动批阅系统。学生只需将答题卡放在摄像头下,系统就能自动识别考号、批改选择题,并实时生成统计报表。 主要功能: 【硬件清单】
硬件 | 型号/规格 | 用途 | | 主机 | LattePanda Alpha 864s(Intel i5-8200Y, 8GB内存) | 运行网页文件、图像处理 | | 摄像头 | 普通USB摄像头(笔记本内置或外接) | 拍摄答题卡图像 | | 显示器 | 普通电脑显示器 | 显示界面和识别结果 | | 支架 | 激光切割亚克力板 | 固定摄像头,保证拍摄角度垂直 |
【软件清单】
软件 | 用途 | | Windows 11 Pro(LattePanda预装) | 操作系统 | | Chrome / Edge 浏览器 | 运行HTML网页 | | Chart.js 4.4.0 | 统计图表渲染 |
【制作过程】
1. 摄像头支架设计与制作答题卡识别的关键在于摄像头必须垂直于答题卡拍摄,否则图像畸变会导致识别失败。我使用激光切割机切割亚克力板制作了一个简易支架: 

亚克力板透明度高、易于激光切割加工,是制作支架的理想材料。如果条件有限,也可以使用硬纸板或3D打印制作简易支架。
2. 硬件组装与连接
LattePanda Alpha是一款巴掌大小的x86单板电脑,尺寸仅115mm×78mm[,性能足以流畅运行网页应用。组装步骤:
3. 答题卡模板设计答题卡需要包含以下元素: 四个黑色定位块:分布在四角,用于检测答题卡是否放置到位 考号涂点区域:每行0-9数字,行数=考号位数(支持1-3位) 选择题区域:10道题,每题A/B/C/D四个选项框(22×22像素)

网页内置了答题卡模板预览功能,点击“下载PDF模板”按钮即可生成并打印。 【技术原理与代码分析】
OMR识别原理
光学标记识别(OMR)是一种通过检测纸张上标记区域的明暗变化来读取信息的计算技术。本系统的识别流程如下:核心代码解析获取摄像头视频流
- const stream = await navigator.mediaDevices.getUserMedia({
- video: {
- deviceId: deviceId ? { exact: deviceId } : undefined,
- width: { ideal: 640 },
- height: { ideal: 480 }
- }
- });
- video.srcObject = stream;
复制代码 黑色像素占比检测- function getBlackRatio(imageData, x, y, w, h) {
- const data = imageData.data;
- let dark = 0, total = 0;
- for (let row = y; row < y+h && row<480; row++) {
- for (let col = x; col < x+w && col<640; col++) {
- const idx = (row*640+col)*4;
- const b = (data[idx]+data[idx+1]+data[idx+2])/3;
- if (b < 100) dark++; // 亮度<100判定为黑色
- total++;
- }
- }
- return total === 0 ? 0 : dark/total;
- }
复制代码 考号识别(带唯一性校验)- function recognizeId(imageData) {
- let id = '';
- for (let row = 0; row < idDigits; row++) {
- let ratios = [];
- for (let d = 0; d <= 9; d++) {
- const rect = idRectList.find(r => r.row === row && r.digit === d);
- const ratio = getBlackRatio(imageData, rect.x, rect.y, rect.w, rect.h);
- ratios.push({ digit: d, ratio });
- }
- ratios.sort((a,b) => b.ratio - a.ratio);
- // 最高占比必须 > 0.15,且比次高至少高出0.1,确保唯一涂黑
- if (ratios[0].ratio < 0.15 || ratios[0].ratio - ratios[1].ratio < 0.1) {
- id += '?'; // 无效
- } else {
- id += ratios[0].digit.toString();
- }
- }
- return id;
- }
复制代码
布局参数(可自定义)所有布局参数集中在代码开头的“布局参数”区域,方便调整:
参数 | 默认值 | 说明 | | OFFSET_X | 140 | 选项整体水平偏移 | | OPT_W / OPT_H | 22 | 选项框尺寸 | | stepY | 38 | 选项行高 | | ID_START_Y | 30 | 考号区域起始Y | | ID_ROW_HEIGHT | 25 | 考号行高 | | CORNERS | 66/558/402等 | 四个定位块坐标 |
【遇到的问题与解决方案】
问题一:白色检测区在普通光照下数值为0现象:最初设计了白色检测区(要求左侧定位块右侧20像素区域白色占比>70%),但普通A4纸在常规光照下检测值一直为0,只有极强光才有数值。 原因:白色亮度阈值设置为200过高,普通光照下纸张亮度达不到该标准。 解决:将白色亮度阈值从200降至150,并最终完全移除了白色检测区,改为仅依赖四个黑色定位块的对齐检测,大幅降低了对光照条件的要求。
问题二:第9题显示不全,第10题不显示现象:答题卡选项区域整体靠下,导致底部题目超出画面。 原因:考号区域行高和选项起始Y值设置不当,10道题的总高度超过了480像素。 解决:调整布局参数: 问题三:左侧定位块一直闪烁,无法对齐现象:右侧两个定位点识别正常,但左侧两个一直闪烁。 原因:左侧定位块需要同时满足黑色检测(>65%)和白色检测(>70%),光照或纸张阴影导致白色区域不达标。 解决:最终移除白色检测区,只检测黑色定位块是否对齐,同时允许用户通过滑块调节涂黑阈值。
问题四:同一张答题卡被重复识别现象:智能模式下,答题卡一直放在摄像头下,系统会反复识别同一张卡。 解决:引入全局考号去重机制(recognizedIds集合),只有考号从未被识别过才触发批阅。手动拍照和连续模式也会将考号加入集合,清空统计记录时同步清空集合。 【功能演示】
摄像头预览与辅助线摄像头画面叠加了青色虚线辅助框,精确标示每个选项的识别区域,方便用户将答题卡对准。 智能定位识别点击“智能定位识别”按钮后,系统自动检测四个黑色定位块是否对齐。对齐后自动识别考号,若考号有效且未被识别过,立即执行批阅并记录结果。 统计报表右侧面板实时显示: 累计批阅答题卡数量 平均正确率与平均分 每道题的正误率柱状图 每份答题卡的详细识别记录(考号、每题答案、得分)
【总结与展望】本项目利用LattePanda Alpha的强大算力和纯前端技术,实现了一套低成本、高可用的智能答题卡批阅系统。全部代码运行在浏览器中,无需安装任何额外软件,跨平台兼容性好。 未来可扩展方向: 增加更多题型支持(判断题、填空题) 接入数据库,实现历次成绩追踪 增加学生信息管理功能 支持导出Excel成绩报表
【附件】 云天智能答题卡批阅系统.zip
|