#################################################################
【纸上得来终觉浅,绝知此事要躬行】
B站视频
新课件:https://pan.baidu.com/s/1frWHqCVGR2VTn5QBtW4lPA 提取码:xh02
老课件:https://pan.baidu.com/s/1Wi31FxSPBqWiuJX9quX-jA 提取码:bbfg
################################################################
答题卡识别效果
【大致思路】:先进行仿射变换去除背景(只留试卷部分),二值化,圆形轮廓检测,遍历每一行选项,统计非零像素,记录填充选项(即非零像素最多的轮廓区域),与正确答案进行比对,正确则correct数+1,得到总成绩
1-4 基础操作+透视变换
1-4是基础操作, 3是做近似变换, 取最大的那个轮廓,最有可能是图像最大外围的轮廓
3的近似变换 和 4的透视变换原理 可以参考我的 OCR文档扫描实战博客
# 1.预处理
image = cv2.imread(args["image"])
contours_img = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
cv_show('blurred',blurred)
edged = cv2.Canny(blurred, 75, 200)
cv_show('edged',edged)
# 2.轮廓检测
cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)[1]
cv2.drawContours(contours_img,cnts,-1,(0,0,255),3)
cv_show('contours_img',contours_img)
docCnt = None
# 3.确保检测到了
if len(cnts) > 0:
# 根据轮廓大小进行排序
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
# 遍历每一个轮廓
for c in cnts:
# 近似
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.02 * peri, True)
# 准备做透视变换
if len(approx) == 4:
docCnt = approx
break
# 4.执行透视变换
warped = four_point_transform(gray, docCnt.reshape(4, 2))
cv_show('warped',warped)
5-6 阈值处理+轮廓检测
5.Otsu’s 阈值处理
THRESH_OTSU会自动寻找合适的阈值,适合双峰,需把阈值参数设置为0
在我的信用卡数字识别案例中出现也有应用(第三、五部分)
6.然后怎么区分涂和没涂的圆?
这里不用霍夫变换,因为有些涂完后 会突出边界,如下
# 5.Otsu's 阈值处理
thresh = cv2.threshold(warped, 0, 255,
cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
cv_show('thresh',thresh)
thresh_Contours = thresh.copy()
# 6.找到每一个圆圈轮廓
cnts = cv2.find