0
点赞
收藏
分享

微信扫一扫

OpenCV实现答题卡自动打分!

洲行 2023-10-13 阅读 30

目录

1,主要原理以及函数介绍

全部代码,以

2 , 实现过程

3,结果展示


1,主要原理以及函数介绍

创建一个ArgumentParser对象,并将其赋值给变量ap。这个对象可以接受我们的脚本的命令行参数,从而实现根据命令行参数执行不同的操作。

添加一个命令行参数-i/--image,并指定它是必需的,用户必须提供一个图像路径作为输入。

解析命令行参数并将它们存储在args字典中

定义一个字典,其中包含每道题目的正确答案。键是问题的索引、值是正确答案的编号

定义函数order_points,用于按照指定顺序找到四个坐标点

定义函数four_point_transform,用于执行透视变换。

透视变换是一种在图像处理领域中常用的变换方式,它可以将一个平面上的图像投影到一个新的视平面上。透视变换通常用于纠正图像中的透视畸变,例如将斜着拍摄的照片转换为正常的平面视图。在透视变换中,图像中的平行线可能会变成不平行线,而原本不平行的线可能会变成平行线。函数four_point_transform就是利用四个特定的点来确定透视变换矩阵,并对输入的图像进行透视变换。

定义函数sort_contours,用于对轮廓进行排序

定义函数cv_show,用于显示图像。

读取输入的图像,并将其存储在变量image中

复制图像,用于在图像上绘制轮廓

查找图像中的轮廓,使用外部轮廓检查模式(RETR_EXTERNAL)只检测外部轮廓,使用简单的轮廓逼近算法(CHAIN_APPROX_SIMPLE)来减少点数。返回值是一个元组,其中第二个元素表示轮廓列表

将找到的轮廓绘制在图像上,颜色为红色

初始化docCnt变量,用于存储找到的四个坐标点

如果找到了轮廓,则执行以下操作

对轮廓根据其面积大小进行排序,从大到小排列

使用迭代逼近算法获取轮廓的近似形状。如果近似的轮廓拥有四个顶点,则将其作为找到的四个坐标点。

对图像进行透视变换,将找到的四个坐标点映射到新的矩阵中

对变换后的图像进行二值化处理,使用Otsu's自适应阈值处理算法来获取最优阈值。返回值是一个元组,其中第二个元素是处理后的图像。

复制处理后的图像,用于在上面绘制轮廓

查找处理后图像中的轮廓,并使用RETR_EXTERNAL和CHAIN_APPROX_SIMPLE参数。

将找到的轮廓绘制在二值化图像上

调用cv_show函数,显示绘制轮廓后的图像

questionCnts = sort_contours(questionCnts,method="top-to-bottom")[0]:对questionCnts列表中的轮廓按照从上到下的顺序进行排序。

for (q, i) in enumerate(np.arange(0, len(questionCnts), 5)):对每一行问题进行处理。

cnts = sort_contours(questionCnts[i:i + 5])[0]:对每个问题中的五个选项进行排序。

bubbled = None:初始化变量bubbled,用于保存所选答案。

for (j, c) in enumerate(cnts)::遍历每个选项。

mask = np.zeros(thresh.shape, dtype="uint8") :创建一个全黑图像,大小与thresh相同。

cv2.drawContours(mask, [c], -1, 255, -1):绘制选项的轮廓。

mask = cv2.bitwise_and(thresh, thresh, mask=mask):将二值化图像thresh与mask相乘,只保留交集部分。

total = cv2.countNonZero(mask):计算非零像素的数目,用于判断是否选择了这个选项。

if bubbled is None or total > bubbled[0]::如果之前没有选择过或者当前选择的像素数更多,则更新选择。

bubbled = (total, j):将当前选择的像素数以及选项索引保存到bubbled变量中。

color = (0, 0, 255):初始化颜色为红色。

k = ANSWER_KEY[q]:获取当前问题的正确答案。

if k == bubbled[1]::如果当前选项是正确的,则将颜色设置为绿色,并增加正确计数器。

color = (0, 255, 0)
correct += 1

cv2.drawContours(warped, [cnts[k]], -1, color, 3):将选项的轮廓绘制在变换后的图像上,颜色为正确或错误的颜色。

score = (correct / 5.0) * 100:计算得分。

print("[INFO] score: {:.2f}%".format(score)):输出得分。

cv2.putText(warped, "{:.2f}%".format(score), (10, 30),cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 0, 255), 2):在变换后的图像上绘制得分。

cv2.imshow("Original", image):显示原始图像。

cv2.imshow("Exam", warped):显示处理结果。

cv2.waitKey(0):等待用户按下任意键。

全部代码,以

2 , 实现过程

  1. 导入所需的库和模块:首先导入numpy、argparse、imutils和cv2等库,用于进行科学计算、命令行参数解析、图像处理和机器视觉任务。

  2. 解析命令行参数:使用argparse库创建ArgumentParser对象,并添加一个命令行参数-i/--image,要求用户提供一个输入图像的路径。然后使用ap.parse_args()方法解析命令行参数,并将结果存储在args字典中。

  3. 定义正确答案字典:创建一个字典,其中包含每道题目的正确答案编号。

  4. 函数定义:定义了四个函数,分别用于找到四个坐标点、执行透视变换、对轮廓进行排序以及显示图像。

  5. 读取输入图像:使用cv2.imread()函数读取输入的图像,并将其存储在变量image中。

  6. 图像预处理:将图像转换为灰度图像,然后应用高斯模糊以平滑边缘并减少噪声。接下来使用Canny算法进行边缘检测,得到二值化的边缘图像。

  7. 查找轮廓:使用cv2.findContours()函数查找图像中的轮廓,并使用外部轮廓检查模式(RETR_EXTERNAL)只检测外部轮廓,使用简单的轮廓逼近算法(CHAIN_APPROX_SIMPLE)来减少点数。获取到的轮廓存储在cnts变量中。

  8. 找到答题卡区域:遍历轮廓,计算轮廓周长和近似形状,并通过一系列条件判断找到包含答题卡的轮廓。将找到的四个坐标点保存到docCnt变量中。

  9. 执行透视变换:使用four_point_transform()函数对图像进行透视变换,将找到的四个坐标点映射到新的矩阵中。

  10. 对变换后的图像进行二值化处理:使用Otsu's自适应阈值处理算法对图像进行二值化处理,得到二值化的图像。

  11. 查找轮廓:使用cv2.findContours()函数再次查找处理后图像中的轮廓,并使用RETR_EXTERNAL和CHAIN_APPROX_SIMPLE参数。

  12. 处理每个问题的选项:遍历每个问题所在的行,对该行中的五个选项进行处理。首先对选项进行排序,然后使用遍历的方式计算每个选项中非零像素的数量,根据数量确定是否选择了该选项,同时记录最多选择的选项和其索引。

  13. 计算得分:根据正确的选项数量和总题数计算得分,同时输出得分。

  14. 显示结果:在变换后的图像上绘制得分,并显示原始图像和处理结果。

  15. 等待用户按下任意键结束程序。

3,结果展示

高斯滤波后结果

边缘检测结果

图像轮廓检测结果:

透视变换结果:

二值化处理结果:

mask,只保留交集部分

遍历每一个结果,计算非零像素的数目,用于判断是否选择了这个选项

计算的得分并显示

举报

相关推荐

0 条评论