赞
踩
代码所用图片:
直接上代码:
datika.py
# @time: 2022/2/17 18:20 # @Author: wangshubo # @File: datika.py # @description: # @author_email: '971490321@qq.com' import cv2 import numpy as np from myutils import sort_contours from utilsW.utils import cvSHow, CalDistance # 正确答案: BEADB ANSWER_KEY = {0: 1, 1: 4, 2: 0, 3: 3, 4: 1} def four_point_transform(image, pts): # rect = order_points(pts) rect = pts.squeeze().astype(np.float32) (tl, tr, bl, br) = rect[1], rect[2], rect[0], rect[3], # 计算输入的w和h值 widthA = CalDistance(tl, tr) widthB = CalDistance(bl, br) maxWidth = max(int(widthA), int(widthB)) heightA = CalDistance(tl, bl) heightB = CalDistance(tr, br) maxHeight = max(int(heightA), int(heightB)) # 变换后对应坐标位置 dst = np.array([ [0, 0], [maxWidth - 1, 0], [maxWidth - 1, maxHeight - 1], [0, maxHeight - 1]], dtype="float32") src_points = np.array([bl, br, tr, tl]) # 计算变换矩阵 M = cv2.getPerspectiveTransform(src_points, dst) warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight)) # 返回变换后结果 return warped if __name__ == '__main__': src = cv2.imread("D:/images/datika.png") cvSHow("src", src) gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) blur_img = cv2.GaussianBlur(gray, (5, 5), 0) cvSHow("blur_img", blur_img) edge_img = cv2.Canny(blur_img, 75, 200) cvSHow("edge_img", edge_img) cnts = cv2.findContours(edge_img.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0] cv2.drawContours(src, cnts, -1, (0, 0, 255), 2) cvSHow("draw", src) docCnt = None if len(cnts) > 0: cnts = sorted(cnts, key=cv2.contourArea, reverse=True) # reverse为TRUE则为降序,FALSE则为升序 for c in cnts: peri = cv2.arcLength(c, True) approx = cv2.approxPolyDP(c, 0.02 * peri, True) # 主要功能是把一个连续光滑曲线折线化 if len(approx) == 4: docCnt = approx break #透视变换 warped = four_point_transform(gray, docCnt.reshape(4, 2)) cvSHow("warped", warped) thresh = cv2.threshold(warped, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1] cvSHow("thresh", thresh) thresh_Contours = thresh.copy() cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0] cv2.drawContours(warped, cnts, -1, (0,0,255),2) cvSHow("thresh_Contours", warped) questionCnts = [] for c in cnts: (x, y, w, h) = cv2.boundingRect(c) ar = w / float(h) if w >=20 and h >= 20 and ar >=0.9 and ar <= 1.1: questionCnts.append(c) questionCnts = sort_contours(questionCnts, method="top-to-bottom")[0] correct = 0 for (q, i) in enumerate(np.arange(0, len(questionCnts), 5)): # 排序 cnts = sort_contours(questionCnts[i:i + 5])[0] bubbled = None # 遍历每一个结果 for (j, c) in enumerate(cnts): # 使用mask来判断结果 mask = np.zeros(thresh.shape, dtype="uint8") cv2.drawContours(mask, [c], -1, 255, -1) # -1表示填充 cvSHow('mask', mask) # 通过计算非零点数量来算是否选择这个答案 mask = cv2.bitwise_and(thresh, thresh, mask=mask) cvSHow("mask1",mask) total = cv2.countNonZero(mask) # 通过阈值判断 if bubbled is None or total > bubbled[0]: bubbled = (total, j) # 对比正确答案 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", src) cv2.imshow("Exam", warped) cv2.waitKey(0)
引用文件
myutils.py
# @time: 2022/1/17 16:22 # @Author: wangshubo # @File: myutils.py # @description: # @author_email: '971490321@qq.com' import cv2 def sort_contours(cnts, method="left-to-right"): reverse = False i = 0 if method == "right-to-left" or method == "bottom-to-top": reverse = True if method == "top-to-bottom" or method == "bottom-to-top": i = 1 boundingBoxes = [cv2.boundingRect(c) for c in cnts] #用一个最小的矩形,把找到的形状包起来x,y,h,w (cnts, boundingBoxes) = zip(*sorted(zip(cnts, boundingBoxes), key=lambda b: b[1][i], reverse=reverse)) return cnts, boundingBoxes def resize(image, width=None, height=None, inter=cv2.INTER_AREA): dim = None (h, w) = image.shape[:2] if width is None and height is None: return image if width is None: r = height / float(h) dim = (int(w * r), height) else: r = width / float(w) dim = (width, int(h * r)) resized = cv2.resize(image, dim, interpolation=inter) return resized
utils.py
# @time: 2022/1/6 11:06 # @Author: wangshubo # @File: utilsW.py # @description: 封装的工具函数 # @author_email: '971490321@qq.com' import cv2 as cv import numpy as np def cvSHow(name, img): cv.imshow(name, img) cv.waitKey(0) cv.destroyAllWindows() #计算两点距离之和 def CalDistance(pt1, pt2): x1, y1, x2, y2 = pt1[0], pt1[1], pt2[0], pt2[1] distance = np.sqrt(((y2 - y1) ** 2) + ((x2 - x1) ** 2)) return distance # 计算列表中元素之和 def listSum(list): total = 0 ele = 0 while (ele < len(list)): total = total + list[ele] ele += 1 return total
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。