diff --git a/zesje/images.py b/zesje/images.py index 0e2167f278b7d4e9e407d317c16cbd7eed00ee45..05acb9eb2b6e4edfb3b53467dce4eeb3226ce880 100644 --- a/zesje/images.py +++ b/zesje/images.py @@ -2,6 +2,7 @@ import numpy as np +from operator import sub, add def guess_dpi(image_array): h, *_ = image_array.shape @@ -36,6 +37,69 @@ def get_box(image_array, box, padding=0.3): return image_array[top:bottom, left:right] +def fix_corner_markers(corner_keypoints, image, image_format): + """ + Corrects the list of corner markers if only three corner markers are found. + This function raises if only two corner keypoints are detected. + + Params + ------ + corner_keypoints: list of corner marker locations as tuples + image: the image of the page with the corner markers + image_format: either A4 or US letter + + """ + + if len(corner_keypoints) == 4: + pass + + # TODO: raise runtime error here? + if len(corner_keypoints) < 3: + raise RuntimeError + + dpi = guess_dpi(image) + + # TODO: add support for US letter format + x_len = 210 + y_len = 297 + + x_sep = x_len / dpi * 25.4 + y_sep = y_len / dpi * 25.4 + + top_left = [(x, y) for x, y in corner_keypoints if x < x_sep and y < y_sep] + bottom_left = [(x, y) for x, y in corner_keypoints if x < x_sep and y > y_sep] + top_right = [(x, y) for x, y in corner_keypoints if x > x_sep and y < y_sep] + bottom_right = [(x, y) for x, y in corner_keypoints if x > x_sep and y > y_sep] + + if not top_left: + # Top left point is missing + (dx, dy) = tuple(map(sub, top_right[0], bottom_right[0])) + top_left = tuple(map(add, bottom_left[0], (dx, dy))) + + return corner_keypoints + top_left + + if not bottom_left: + # Bottom left point is missing + (dx, dy) = tuple(map(sub, top_right[0], bottom_right[0])) + bottom_left = tuple(map(sub, top_left[0], (dx, dy))) + + return corner_keypoints + bottom_left + + if not top_right: + # Top right point is missing + (dx, dy) = tuple(map(sub, top_left[0], bottom_left[0])) + top_right = tuple(map(add, bottom_right[0], (dx, dy))) + + return corner_keypoints + top_right + + if not bottom_right: + # bottom right + (dx, dy) = tuple(map(sub, top_left[0], bottom_left[0])) + bottom_right = tuple(map(sub, top_right[0], (dx, dy))) + + return corner_keypoints + bottom_right + + def box_is_filled(image_array, box_coords, padding=0.3, threshold=150, pixels=False): """ Determines if a box is filled diff --git a/zesje/pregrader.py b/zesje/pregrader.py index 03252aebd6c17e44b236cef058f648f65f80751d..eb90f3c9b206c81bcdb5cfe970c4b4fdd4499433 100644 --- a/zesje/pregrader.py +++ b/zesje/pregrader.py @@ -9,30 +9,15 @@ # coupled feedback cannot be deleted -from zesje.database import db, Exam, Submission, Solution, Problem -from zesje.scans import find_corner_marker_keypoints -import numpy as np -from zesje.images import guess_dpi, get_box -import cv2 -from PIL import Image - - -def pregrade(exam_token, image): - # get image - image = None - exam = Exam.query.get(exam_token=exam_token) - - problems = exam.problems - - mc_options = [problem.mc_options for problem in problems] - - coords = [(cb.x, cb.y) for cb in mc_options] +import cv2 +import numpy as np - pass +from zesje.database import db, Solution, Problem +from zesje.images import guess_dpi, get_box -def add_feedback_to_solution(submission, page, page_img, corner_keypoints): +def add_feedback_to_solution(page, page_img, corner_keypoints): """ Adds the multiple choice options that are identified as marked as a feedback option to a solution @@ -45,10 +30,10 @@ def add_feedback_to_solution(submission, page, page_img, corner_keypoints): for problem in problems_on_page: for mc_option in problem.mc_options: - box = (mc_option.x, mc_option.y) - sol = Solution.query.filter(Solution.problem_id == problem.id).one_or_none() + box = (mc_option.x, mc_option.y) + # check if box is filled if box_is_filled(box, page_img, corner_keypoints): sol.feedback.append(mc_option.feedback) @@ -154,5 +139,9 @@ def box_is_filled(box, page_img, corner_keypoints, marker_margin=72/2.54, thresh return (np.average(res_rect) < 225) +def box_is_filled(box, page_img, marker_position, marker_margin=72/2.54): + pass + + def _locate_checkbox(): pass diff --git a/zesje/scans.py b/zesje/scans.py index c3f55ca49657edb1fca296d3a6af1c9cfa96cb1f..e4f93a57e287f17962323375141d6c1da58d6975 100644 --- a/zesje/scans.py +++ b/zesje/scans.py @@ -240,8 +240,8 @@ def process_page(image_data, exam_config, output_dir=None, strict=False): else: return True, "Testing, image not saved and database not updated." - submission, exam = update_database(image_path, barcode) - add_feedback_to_solution(submission, exam, barcode.page, image_array, corner_keypoints) + update_database(image_path, barcode) + add_feedback_to_solution(barcode.page, image_array, corner_keypoints) if barcode.page == 0: description = guess_student(