opencv实现答题卡识别

2023-11-18


"""
识别答题卡
"""

import cv2
import numpy as np

def showImg(img_name, img):
cv2.imshow(img_name, img)
cv2.waitKey()
cv2.destroyAllWindows()

def get_max_rect(sorted_cnts):
for cnt in sorted_cnts:
# 轮廓近似
possible_cnts = []
epsilon = 0.1 * cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, epsilon, True)
if len(approx) == 4:
possible_cnts.append(cnt)
possible_cnts = sorted(possible_cnts, key=lambda x: cv2.arcLength(x, True))
return possible_cnts

def get_max_bounding_rect(possible_cnts):
# for cnt in possible_cnts:
# x, y, w, h = cv2.boundingRect(cnt)

sorted_cnts = sorted(possible_cnts, key=lambda cnt: cv2.boundingRect(cnt)[2]*cv2.boundingRect(cnt)[3], reverse=True)
print(sorted_cnts[0])

def show_countour(img, cnt):
img_copy = img.copy()
cv2.drawContours(img_copy, cnt, -1, (0,255, 0), 3)
showImg("img_copy", img_copy)


# 读取答题卡图片,并显示
answer_sheet_img = cv2.imread("t1.jpg")
print(answer_sheet_img.shape)
showImg("answer_sheet_img", answer_sheet_img)

# 高斯滤波,去除噪音
blur = cv2.GaussianBlur(answer_sheet_img,(5,5),0)
showImg("blur", blur)

# 图像转灰度值
sheet_gray = cv2.cvtColor(blur, cv2.COLOR_BGR2GRAY)
showImg("sheet_gray", sheet_gray)

# 二值化
retval, sheet_threshold = cv2.threshold(sheet_gray,177, 255, cv2.THRESH_BINARY)
# print(type(sheet_threshold), sheet_threshold)
showImg("sheet_threshold", sheet_threshold)

# 边界检测
edges = cv2.Canny(sheet_threshold, 100, 200)
showImg("edges", edges)
# print(type(edges))

# 寻找轮廓
copy_edges = edges.copy()
img_copy = answer_sheet_img.copy()
img, cnts, hierarchy = cv2.findContours(copy_edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img_copy, cnts, -1, (0,0,255), 1)
showImg("img_copy", img_copy)

# 对所有轮廓加一个外接矩形,找最大的外接矩形
max_area_index = None
area = 0
for index, cnt in enumerate(cnts):
x, y, w, h = cv2.boundingRect(cnt)
if w*h > area:
max_area_index = index
show_countour(answer_sheet_img, cnts[max_area_index])

# 仿射,拿到答题卡主要部位
x, y, w, h = cv2.boundingRect(cnts[max_area_index]) # 最大的边界
cv2.rectangle(answer_sheet_img, (x, y),(x+w, y+h), (0,0,255), 2)
showImg("answer_sheet_img", answer_sheet_img)
pts1 = np.float32([[x,y], [x+w, y], [x+w, y+h]])
pts2 = np.float32([[0,0], [w, 0], [w, h]])

M = cv2.getAffineTransform(pts1, pts2)
sheet_threshold_copy = sheet_threshold.copy()
dst = cv2.warpAffine(sheet_threshold_copy, M, (w, h))
showImg("dst", dst)
print(answer_sheet_img.shape)
part_sheet_img = answer_sheet_img[y:y+h, x:x+w]
showImg("part_sheet_img", part_sheet_img)

# 对答案区域灰度,二值,找轮廓
part_answer_gray = cv2.cvtColor(part_sheet_img, cv2.COLOR_BGR2GRAY) # 灰度
ret, threshold_answer = cv2.threshold(part_answer_gray, 175, 255, cv2.THRESH_BINARY)
showImg("threshold_answer", threshold_answer)

img, answer_cnts, x = cv2.findContours(threshold_answer, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
part_sheet_img_copy = part_sheet_img.copy()
cv2.drawContours(part_sheet_img_copy, answer_cnts, -1, (0, 0, 255), 1)
showImg("dst_copy", part_sheet_img_copy)

# 对所有轮廓找外接矩形,想过滤掉不合适的矩形
print("画矩形")
answer_filter_cnts = []
answer_circles = []
img_ = part_sheet_img.copy()
for cnt in answer_cnts:
x, y, w, h = cv2.boundingRect(cnt)
if 30<w<40 and 30<h<40:
print(x, y, w, h)
circle_x = int(x + w/2)
circle_y = int(y+h/2)
r = int((w+h)/4)
answer_circles.append((circle_x, circle_y, r))
answer_filter_cnts.append(cnt)

answer_filter_cnts = np.array(answer_filter_cnts)
cv2.drawContours(img_, answer_filter_cnts, -1, (0, 0, 255), 1)
# cv2.rectangle(img, (x, y), (x+w, y+h), (0,255,0), 2)
showImg("img_", img_)
print("geshu", len(answer_circles))


# 从answer_circles中取25个
mask_dict = {1:[],2:[], 3:[], 4:[],5:[]} # 一共不一定是25个圆,将圆按照题目行分类,
sorted_y_answer_circles = sorted(answer_circles, key=lambda circle: circle[1])
print("sorted_y_answer_circles", sorted_y_answer_circles)
set_num = 1
for index, circle in enumerate(sorted_y_answer_circles):
if index == 0:
mask_dict[1].append(circle)
else:
if circle[1] - sorted_y_answer_circles[index-1][1] > 30:
set_num += 1
mask_dict[set_num].append(circle)
else:
mask_dict[set_num].append(circle)

print("mask_dict", mask_dict)

for k, mask_circle_list in mask_dict.items(): # 对每一个题目,保留五个答案,多余的舍去
if len(mask_circle_list) == 5:
sorted_x_mask_circle_list = sorted(mask_circle_list, key=lambda x:x[0])
mask_dict[k]=sorted_x_mask_circle_list
else:
sorted_x_mask_circle_list = sorted(mask_circle_list, key=lambda x: x[0])
sorted_x_mask_circle_list_5 = []
for i, c in enumerate(sorted_x_mask_circle_list):
if i == 0:
sorted_x_mask_circle_list_5.append(c)
else:
if abs(c[0] - sorted_x_mask_circle_list[i-1][0]) < 10:
pass
else:
sorted_x_mask_circle_list_5.append(c)
mask_dict[k] = sorted_x_mask_circle_list_5

print("mask_dict", mask_dict)

# mask_dict 分好组的按照顺序的圈圈

# 做掩码
mask_img = np.zeros_like(part_sheet_img, dtype='uint8') # 全黑图
showImg("threshold_answer", threshold_answer)
threshold_answer = np.array(threshold_answer)
# mask_dict = sorted(mask_dict, key=lambda x: mask_dict.keys())
all_scores = [] # 所有答案处的评分
for exercise_num, circle_mask_list in mask_dict.items():
# 对于每一题
score_list = [] # 每一题的每个选项的评分,涂黑的为选择的,值越接近0, 评分较低
for circle_mask in circle_mask_list:
mask_img_copy = cv2.cvtColor(mask_img, cv2.COLOR_BGR2GRAY)
# 做一个当前圆的掩码:
cv2.circle(mask_img_copy, (circle_mask[0], circle_mask[1]), circle_mask[2], (255, 255, 255), -1)
print(threshold_answer.shape, mask_img_copy.shape)
mask_img_ = cv2.bitwise_and(threshold_answer, threshold_answer, mask=mask_img_copy)
score = mask_img_.sum()
score_list.append(score)
# showImg("mask_img_", mask_img_)
all_scores.append(score_list)


all_score_np = np.array(all_scores)
s = np.argmin(all_score_np, axis=1) # 找评分最低处即为选择项

answer_dict = {
0: "A",
1: "B",
2: "C",
3: "D",
4: "E"
}

for index, v in enumerate(s):
print("第%s题的答案是%s" %(index+1, answer_dict[v]))

t1图片

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

opencv实现答题卡识别 的相关文章

  • OpenCV Python 删除图像中的某些对象

    我正在使用带有 opencv 和 numpy 的 python 来检测天文中的星星 例如这个1 https i stack imgur com AKwEJ jpg图片 使用模板匹配 我可以用阈值检测星星 单击 2 2 https i sta
  • 使用 K 均值聚类 OpenCV 进行交通标志分割

    I used K Means Clustering to perform segmentation on this traffic sign as shown below 这些是我的代码 读取图像并模糊 img cv imread 000
  • 附加信息:OpenCV:使用 c# 的不同大小的对象

    目前 我的 EmguCV c 代码面临问题 我试图从数据库中识别我的图像 但它不起作用 一旦检测到我的脸 它就会崩溃 然后会出现此错误 附加信息 OpenCV 不同大小的对象 我尝试寻找这个错误 但我一无所知 这是我的代码 Action f
  • 用于 C++ 中图像分析的 OpenCV 二进制图像掩模

    我正在尝试分析一些图像 这些图像的外部周围有很多噪声 但内部有一个清晰的圆形中心 中心是我感兴趣的部分 但外部噪声正在影响我对图像的二进制阈值处理 为了忽略噪音 我尝试设置一个已知中心位置和半径的圆形蒙版 从而使该圆之外的所有像素都更改为黑
  • 从单应性估计 R/T

    我一直在尝试计算 2 个图像中的特征 然后将这些特征传递回CameraParams R没有运气 特征已成功计算并匹配 但是问题是将它们传递回R t 我明白你必须分解Homography为了使这一点成为可能 我已经使用如下方法完成了 http
  • OpenCV:视频录制太快

    我有一个简单的录像机 录制来自网络摄像头的视频 theVideoWriter open filename countAsString ext CV FOURCC X V I D 30 Size 1920 1080 true while re
  • 如何计算立体视觉的基本矩阵

    我正在尝试编写一些代码来计算基本矩阵以确定立体图像之间的关系 我从大多数人推荐的 Hartley 和 Zisserman 书开始 但它没有任何实际示例 并且示例代码是在 MATLAB 中 而我没有 然后我切换到这个比较实用 里面有实际例子
  • 如何使用 SimpleBlobDetector 获取 blob 的额外信息?

    robot sherrick 回答了我这个问题 https stackoverflow com a 13534094 1705967 这是他回答的后续问题 cv SimpleBlobDetectorOpencv 2 4 中的 看起来非常令人
  • 从 2 个摄像头捕获(OpenCV、Python)[重复]

    这个问题在这里已经有答案了 所以我试图从 openCV 中的两个摄像头 python 和 windows 7 进行捕获 我用一台相机拍摄的效果很好 你也会注意到我正在对图像做一些时髦的事情 但这并不重要 这是尝试使用两个的代码 import
  • OpenCV Android - 无法解析相应的JNI函数

    我正在尝试按照此处概述的本教程使用 Opencv 设置 Android Studio https www youtube com watch v OTw GIQNbD8 https www youtube com watch v OTw G
  • 基本的 Python OpenCV 裁剪和调整大小

    有人可以帮我一些裁剪算法吗 它的 openCV 我想弄清楚这一点 我知道方法是crop image y y1 x x1 如果我有一个带有 new dimensionXxnew dimensionY 像素的图像 并且我想将其裁剪为相同的宽度
  • 如何在 OpenCV 中将 Float Mat 写入文件

    我有一个矩阵 Mat B 480 640 CV 32FC1 包含浮点值 我想将此矩阵写入一个可以打开的文件Notepad https en wikipedia org wiki Windows Notepad or 微软Word https
  • 将向量 转换为大小为 (n x 3) 的 Mat,反之亦然

    我有 Point3d 向量 向量形式的点云 如果我使用 OpenCV 提供的转换 比如 cv Mat tmpMat cv Mat pts Here pts is vector
  • 如何使用Android opencv使图像的白色部分透明

    我无法链接超过 2 个网址 因此我将我的照片发布到此博客 请在这里查看我的问题 http blog naver com mail1001 220650041897 http blog naver com mail1001 220650041
  • OpenCV 中的 Gabor 内核参数

    我必须在我的应用程序中使用 Gabor 过滤器 但我不知道这个 OpenCV 方法参数值 我想对虹膜进行编码 启动 Gabor 过滤器并获取特征 我想对 12 组 Gabor 参数值执行此操作 然后我想计算 Hamming Dystans
  • 如何将 Opencv VideoWriter 与 GStreamer 结合使用?

    我正在尝试使用 Opencv VideoWriter 传输 h264 流 以使用 VideoCapture 将其传输到网络上的另一台电脑上 但是 我被困在 VideoWriter 上 执行此代码会返回错误 并且 out isOpened 始
  • 计数物体和更好的填充孔的方法

    我是 OpenCV 新手 正在尝试计算物体的数量在图像中 我在使用 MATLAB 图像处理工具箱之前已经完成了此操作 并在 OpenCV Android 中也采用了相同的方法 第一步是将图像转换为灰度 然后对其进行阈值计算 然后计算斑点的数
  • OpenCv 与 Android studio 1.3+ 使用新的 gradle - 未定义的参考

    我在使用原生 OpenCv 2 4 11 3 0 0 也可以 和 Android Studio 1 3 以及新的 ndk 支持时遇到问题 所有关于 mk 文件的教程 但我想将它与新的实验性 gradle 一起使用 使用 Kiran 答案An
  • 寻找两个框架之间的变换

    我有来自视频源的两个连续帧 并且我使用 FAST 算法检测这两个帧的关键点 我使用平方差之和法 SSD 来匹配关键点 所以基本上我已经匹配了两个框架之间的关键点 现在我想根据匹配的关键点集计算两个帧之间的仿射变换 缩放 旋转 平移 我知道如
  • 为什么opencv videowriter这么慢?

    你好 stackoverflow 社区 我有一个棘手的问题 我需要你的帮助来了解这里发生了什么 我的程序从视频采集卡 Blackmagic 捕获帧 到目前为止 它工作得很好 同时我用 opencv cv imshow 显示捕获的图像 它也工

随机推荐

  • STS(Spring Tool Suite)使用前准备

    好了 卖了两个月冰激凌 现在又回来做程序员了 发现好多东西已经忘了 所以拿csdn当个记事本 方便我也方便其他和我有同样问题的人 现在打算用spring mvc来做些东西 工具就用sts STS Spring Tool Suite 其实是个
  • mysql 字符集问题整理

    mysql 字符集问题整理 一直对mysql字符集没有明确的概念 mysql为了方便 设置了各种层级的字符集 最近在移植mat数据库时 顺便把这个问题整理清楚 供参考和学习 文章最后有word版本 有两张图片以及不同文字的颜色区分 首先是M
  • C# 的委托事件实现(含代码)

    参考代码 http www pudn com downloads74 sourcecode windows csharp detail271438 html 最近在看一个抛物线的代码 用C 写的 以前接触C 不多 从代码中可以看到与andr
  • 《Blurriness-guided Unsharp Masking》阅读笔记

    Unsharp Masking 反锐化掩模 将原图像通过反锐化掩模进行模糊预处理 相当于采用低通滤波 后与原图逐点做差值运算 然后乘上一个修正因子再与原图求和 以达到提高图像中高频成分 增强图像轮廓的目的 这篇文章提出了一个基于模糊作为导向
  • 【文文殿下】【SDOI2013】随机数生成器 题解

    题意 给你个随机数生成器 f x a f x 1 b mod p 给你初始信息 a b t p f 1 问你几次等于 t 如果不等于输出 1 题解 f n a f n 1 b f n c a n 1 frac b a n 1 a 1 tex
  • Linux系统服务权限维持

    usr lib systemd system linux How to remove systemd services Super User VirusTotal File 334e828a09bd64abb9a4f70256f4d2f8f
  • 创新生产力的新引擎

    随着科技的飞速发展 人工智能 AI 已成为当今时代的一大热点 近年来 生成式AI的崛起 特别是在自然语言处理 NLP 领域的突破 对传统搜索引擎 推荐系统 语言翻译等领域产生了深远的影响 CHAT GPT作为生成式AI的代表之一 更是引领了
  • java中的四种权限修饰符

    因为缺省情况下只能在同包中访问 所以缺省也叫包访问权限 要注意的是 当使用protected修饰父类的成员或者方法 在不同包下访问该父类的资源时 只有使用子类对象才可以去访问 声明一个父类的对象是无法访问该资源的
  • unity 3D获取当前物体得坐标

    unity 3D获取当前物体得坐标 与物体绑定好 public class location MonoBehaviour Start is called before the first frame update public GameOb
  • 2022年“网络安全”赛项驻马店市赛选拔赛 任务书

    2022年 网络安全 赛项驻马店市赛选拔赛 一 竞赛时间 共计3小时 二 竞赛阶段 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 第一阶段单兵模式系统渗透测试 任务一 Windows操作系统渗透测试 100分钟 100 任务二 Linux操
  • Linux 中如何使用 Aria2 下载文件

    Aria2是一个免费的开源轻量级多协议命令行实用程序 可以从Internet上下载文件 它支持各种协议 例如HTTP HTTPS FTP甚至BitTorrent Aria2可在Windows Linux和Mac OSX上运行 主要特征 以下
  • RBAC新解:基于资源的权限管理(Resource-Based Access Control)

    原文地址 转载地址 本文讨论以角色概念进行的权限管理策略及主要以基于角色的机制进行权限管理是远远不够的 同时我将讨论一种我认为更好的权限管理方式 什么是角色 当说到程序的权限管理时 人们往往想到角色这一概念 角色是代表一系列可执行的操作或责
  • Sqlilabs-25a

    本关卡和 25 关的区别在于连单引号都省去了 http sqlilabs Less 25a id 1 报错 http sqlilabs Less 25a id 1 正常 http sqlilabs Less 25a id 1 ordery
  • go学习———第二阶段

    go 第二阶段学习 一 函数 1 函数基本用法 函数的参数与返回值 不定参数的传递 2 函数类型 递归函数 回调函数 匿名函数 3 defer的用法 先入后出 4 闭包与匿名函数 二 指针变量 三 数组与切片 1 数组 2 切片 随机数 四
  • 安装tiny-cuda-nn时报错RuntimeError: Could not locate a supported Microsoft Visual C++ installation

    问题描述 按照官方教程安装nerf studio 运行命令pip install git https github com NVlabs tiny cuda nn subdirectory bindings torch安装tiny cuda
  • 为什么我们要进行博客营销

    首先我们要了解博客产生的背景 在一种web2 0时代 为了发表一些看法 分享知识和经验 同时增加创造性和自主性 而专门设计了很大类的博客 有很多知名的博客网 国内如新浪博客 网易博客 阿里巴巴博客等 而博客营销可以通过博客创作一些文章 或者
  • React 从零开始学习(八)—— 决出胜负

    有两个玩家参与之后 就需要判断胜负 以及游戏何时结束 在 Board js 文件中添加 calculateWinner 方法来计算判断游戏 传入 squares 是一个长度为 9 的数组 function calculateWinner s
  • Go 1.19.3 context原理简析

    Context context Context一般用作函数或方法的第一个参数 其作用为管控协程在用户侧 生命周期 它是线程安全的 在多个goroutine之间可以任意调用其方法 不需考虑锁的问题 原理简析 context的结构是一棵以Bac
  • scrapy mysql的同步插入与异步插入

    主要代码是在Pipeline中进行编写 上完整代码 同步插入代码 同步插入 class MysqlPipeline2 object 同步操作 def init self 建立连接 self conn pymysql connect loca
  • opencv实现答题卡识别

    识别答题卡 import cv2 import numpy as np def showImg img name img cv2 imshow img name img cv2 waitKey cv2 destroyAllWindows d