From 49da268324ea1eeee6b60f4a4aeab4a8811f5792 Mon Sep 17 00:00:00 2001
From: Ruben Young On <r.d.youngon@student.tudelft.nl>
Date: Fri, 24 May 2019 12:40:19 +0200
Subject: [PATCH] Added corner marker correction for 3 corner markers, cleaned
 up pregrader

---
 zesje/images.py    | 64 ++++++++++++++++++++++++++++++++++++++++++++++
 zesje/pregrader.py | 33 ++++++++----------------
 zesje/scans.py     |  4 +--
 3 files changed, 77 insertions(+), 24 deletions(-)

diff --git a/zesje/images.py b/zesje/images.py
index 0e2167f2..05acb9eb 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 03252aeb..eb90f3c9 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 c3f55ca4..e4f93a57 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(
-- 
GitLab