Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]
questionCnts = []
# 对每一个轮廓进行循环处理
for c in cnts:
# 计算轮廓的边界框,然后利用边界框数据计算宽高比
(x, y, w, h) = cv2.boundingRect(c)
ar = w / float(h)
# 为了辨别一个轮廓是一个气泡,要求它的边界框不能太小,在这里边至少是20个像素,而且它的宽高比要近似于1
if w >= 20 and h >= 20 and ar >= 0.9 and ar <= 1.1:
questionCnts.append(c)
# 以从顶部到底部的方法将我们的气泡轮廓进行排序,然后初始化正确答案数的变量。
questionCnts = contours.sort_contours(questionCnts,
method="top-to-bottom")[0]
correct = 0
# 每个题目有5个选项,所以5个气泡一组循环处理
for (q, i) in enumerate(np.arange(0, len(questionCnts), 5)):
# 从左到右为当前题目的气泡轮廓排序,然后初始化被涂画的气泡变量
cnts = contours.sort_contours(questionCnts[i:i + 5])[0]
bubbled = None
# 对一行从左到右排列好的气泡轮廓进行遍历
for (j, c) in enumerate(cnts):
# 构造只有当前气泡轮廓区域的掩模图像
mask = np.zeros(thresh.shape, dtype="uint8")
cv2.drawContours(mask, [c], -1, 255, -1)
# 对二值图像应用掩模图像,然后就可以计算气泡区域内的非零像素点。
Grades a list of bubbles from the test box.
Args:
bubbles (list): A list of lists, where each list is a group of
bubble contours.
box (numpy.ndarray): An ndarray representing the test box.
"""
for (i, group) in enumerate(bubbles):
# Split a group of bubbles by question.
group = self.group_by_question(group, self.groups[i])
# Sort bubbles in each question based on box orientation then grade.
for (j, question) in enumerate(group, 1):
question_num = j + (i * len(group))
question, _ = cutils.sort_contours(question,
method=self.orientation)
self.grade_question(question, question_num, i, box)
digit_contours = []
# loop over the digit area candidates
for c in all_contours:
# compute the bounding box of the contour
(x, y, w, h) = cv2.boundingRect(c)
print("Found Contours x:{} y:{} w:{} h:{}".format(x, y, w, h))
# if the contour is sufficiently large, it must be a digit
if w >= 15 and h >= 50: # <= That's the tricky part
print("\tAdding Contours x:{} y:{} w:{} h:{}".format(x, y, w, h))
digit_contours.append(c)
print("Retained {}".format(len(digit_contours)))
# sort the contours from left-to-right, then initialize the
# actual digits themselves
digit_contours = contours.sort_contours(digit_contours,
method="left-to-right")[0]
# loop over each of the digits
idx = 0
padding = 10
for c in digit_contours:
idx += 1
# extract the digit ROI
(x, y, w, h) = cv2.boundingRect(c)
#
roi = thresh[y:y + h, x:x + w] # <= THIS is the image that will be processed (recognized) later on.
#
if show_all_steps:
cv2.imshow("Digit {}".format(idx), roi)
#
# cv2.rectangle(saved_image, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.rectangle(saved_image, (x - padding, y - padding), (x + w + (2 * padding), y + h + (2 * padding)),
cv2.CHAIN_APPROX_SIMPLE)
# Sort all the contours by top to bottom.
(vertical_contours, vertical_bounding_boxes) = sort_contours(vertical_contours, method="left-to-right")
filtered_vertical_bounding_boxes = list(filter(lambda x:vertical_boxes_filter(x,height), vertical_bounding_boxes))
# Morphological operation to detect horizontal lines from an image
img_temp2 = cv2.erode(thresholded, hori_kernel, iterations=3)
horizontal_lines_img = cv2.dilate(img_temp2, hori_kernel, iterations=3)
_, horizontal_contours, _ = cv2.findContours(horizontal_lines_img.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
horizontal_contours, horizontal_bounding_boxes = sort_contours(horizontal_contours, method="top-to-bottom")
filtered_horizontal_bounding_boxes = list(filter(lambda x:horizontal_boxes_filter(x,width), horizontal_bounding_boxes))
if DEBUG:
color_image = cv2.cvtColor(gray_image.copy(), cv2.COLOR_GRAY2BGR)
cv2.drawContours(color_image, vertical_contours, -1, (0, 255, 0), 2)
cv2.drawContours(color_image, horizontal_contours, -1, (255, 0, 0), 2)
# for filtered_horizontal_bounding_box in filtered_horizontal_bounding_boxes:
# x,y,w,h = filtered_horizontal_bounding_box
# cv2.rectangle(color_image,(x,y),(x+w,y+h),(0,255,255),2)
#
# for filtered_vertical_bounding_box in filtered_vertical_bounding_boxes:
# x,y,w,h = filtered_vertical_bounding_box
# cv2.rectangle(color_image,(x,y),(x+w,y+h),(0,255,255),2)
def read_numbers(x, y, w, h, max_digits=5):
""" Method to ocr numbers.
Returns int.
"""
text = []
crop = screen[y:y + h, x:x + w]
crop = cv2.resize(crop, None, fx=3, fy=3, interpolation=cv2.INTER_CUBIC)
thresh = cv2.threshold(crop, 0, 255, cv2.THRESH_OTSU)[1]
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnts = grab_contours(cnts)
cnts = contours.sort_contours(cnts, method="left-to-right")[0]
if len(cnts) > max_digits:
return 0
for c in cnts:
scores = []
(x, y, w, h) = cv2.boundingRect(c)
roi = thresh[y:y + h, x:x + w]
row, col = roi.shape[:2]
width = round(abs((50 - col)) / 2) + 5
height = round(abs((94 - row)) / 2) + 5
resized = cv2.copyMakeBorder(roi, top=height, bottom=height, left=width, right=width,
borderType=cv2.BORDER_CONSTANT, value=[0, 0, 0])
Args:
id_box (numpy.ndarray): An ndarray representing the id box in the
test image.
Returns:
list: A list containing the id, unsure columns, image slices, and
status
"""
# Get and grade bubbles in id box.
bubbles = self.get_id_bubbles(id_box)
bubbles, _ = cutils.sort_contours(bubbles, method="left-to-right")
# Each field has 10 possibilities so loop in batches of 10.
for (q, i) in enumerate(np.arange(0, len(bubbles), 10)):
contours, _ = cutils.sort_contours(bubbles[i:i + 10], method="top-to-bottom")
bubbled = None
max_count = -float("inf")
bounding_rects = []
# Calculate x and y boundaries of this column for image slicing.
for (j, c) in enumerate(contours):
bounding_rects.append(cv.boundingRect(c))
x_min = min(bounding_rects, key=lambda x: x[0])[0] + self.config['id_x']
x_max = max(bounding_rects, key=lambda x: x[0])[0] + self.config['id_x']
y_min = min(bounding_rects, key=lambda x: x[1])[1] + self.config['id_y']
y_max = max(bounding_rects, key=lambda x: x[1])[1] + self.config['id_y']
for (j, c) in enumerate(contours):
mask = np.zeros(id_box.shape, dtype="uint8")
cv.drawContours(mask, [c], -1, 255, -1)
def grade_answers(self, answer_box):
"""
Finds and grades bubbles within the answer box.
Args:
answer_box (numpy.ndarray): An ndarray representing the answer box
in the test image.
list: A list containing the answers, unsure questions, image slices, and
status
"""
# Get and grade bubbles in question box.
bubbles = self.get_answer_bubbles(answer_box)
bubbles, _ = cutils.sort_contours(bubbles, method="left-to-right")
column_1 = []
column_2 = []
column_3 = []
for bubble in bubbles:
(x, y, w, h) = cv.boundingRect(bubble)
x += self.config['answer_x']
if (x >= self.config['answer_x_min_1'] - self.config['x_error'] and
x <= self.config['answer_x_max_1'] + self.config['x_error']):
column_1.append(bubble)
elif (x >= self.config['answer_x_min_2'] - self.config['x_error'] and
x <= self.config['answer_x_max_2'] + self.config['x_error']):
column_2.append(bubble)
elif (x >= self.config['answer_x_min_3'] - self.config['x_error'] and
x <= self.config['answer_x_max_3'] + self.config['x_error']):