Development of the ocr part of AOI
Samo Penic
2018-11-17 fe2c1025b102bbf20c9afbc29eedf7a5f069410c
Ocr.py
@@ -1,16 +1,20 @@
from pyzbar.pyzbar import decode
from sid_process import getSID
import cv2
import numpy as np
import math
class Paper:
    def __init__(self, filename=None):
    def __init__(self, filename=None, sid_classifier=None, settings=None):
        self.filename = filename
        self.invalid = None
        self.QRData = None
        self.settings = {"answer_threshold": 0.25} if settings is None else settings
        self.errors = []
        self.warnings = []
        self.sid = None
        self.sid_classifier = sid_classifier
        if filename is not None:
            self.loadImage(filename)
            self.runOcr()
@@ -53,22 +57,30 @@
            self.data = None
            self.invalid = True
            return
        if(len(d)>1): #if there are multiple codes, get first ean or qr code available.
            for dd in d:
                if(dd.type=="EAN13" or dd.type=="QR"):
                    d[0]=dd
                    break
        self.QRDecode = d
        self.QRData = d[0].data
        xpos = d[0].rect.left
        ypos = d[0].rect.top
        # check if image is rotated wrongly
        if xpos > self.imgHeight / 2.0 and ypost > self.imgWidth / 2.0:
        if xpos > self.imgHeight / 2.0 and ypos > self.imgWidth / 2.0:
            self.rotateAngle(180)
    def rotateAngle(self, angle=0):
        # rot_mat = cv2.getRotationMatrix2D(
        #    (self.imgHeight / 2, self.imgWidth / 2), angle, 1.0
        # )
        rot_mat = cv2.getRotationMatrix2D(
            (self.imgHeight / 2, self.imgWidth / 2), angle, 1.0
            (self.imgWidth / 2, self.imgHeight / 2), angle, 1.0
        )
        result = cv2.warpAffine(
            self.img,
            rot_mat,
            (self.imgHeight, self.imgWidth),
            (self.imgWidth, self.imgHeight),
            flags=cv2.INTER_CUBIC,
            borderMode=cv2.BORDER_CONSTANT,
            borderValue=(255, 255, 255),
@@ -136,8 +148,8 @@
            loc_filtered_x, loc_filtered_y = zip(
                *sorted(zip(loc_filtered_x, loc_filtered_y))
            )
        # loc=[loc_filtered_y,loc_filtered_x]
        # remove duplicates
            # loc=[loc_filtered_y,loc_filtered_x]
            # remove duplicates
            a = np.diff(loc_filtered_x) > 40
            a = np.append(a, True)
            loc_filtered_x = np.array(loc_filtered_x)
@@ -210,3 +222,73 @@
                black = totpx - cv2.countNonZero(roi)
                oneline.append(black / totpx)
            self.answerMatrix.append(oneline)
    def get_enhanced_sid(self):
        if self.sid_classifier is None:
            return "x"
        if self.settings is not None:
            sid_mask = self.settings.get("sid_mask", None)
        es, err, warn = getSID(
            self.img[
                int(0.04 * self.imgHeight) : int(0.095 * self.imgHeight),
                int(0.7 * self.imgWidth) : int(0.99 * self.imgWidth),
            ],
            self.sid_classifier,
            sid_mask,
        )
        [self.errors.append(e) for e in err]
        [self.warnings.append(w) for w in warn]
        return es
    def get_code_data(self):
        if self.QRData is None:
            self.errors.append("Could not read QR or EAN code! Not an exam?")
            retval = {
                "exam_id": None,
                "page_no": None,
                "paper_id": None,
                "faculty_id": None,
                "sid": None,
            }
            return retval
        qrdata = bytes.decode(self.QRData, "utf8")
        if self.QRDecode[0].type == "EAN13":
            return {
                "exam_id": int(qrdata[0:7]),
                "page_no": int(qrdata[7]),
                "paper_id": int(qrdata[-5:-1]),
                "faculty_id": None,
                "sid": None,
            }
        else:
            data = qrdata.split(",")
            retval = {
                "exam_id": int(data[1]),
                "page_no": int(data[3]),
                "paper_id": int(data[2]),
                "faculty_id": int(data[0]),
            }
            if len(data) > 4:
                retval["sid"] = data[4]
            return retval
    def get_paper_ocr_data(self):
        data = self.get_code_data()
        data["qr"] = self.QRData
        data["errors"] = self.errors
        data["warnings"] = self.warnings
        data["up_position"] = (
            list(self.xMarkerLocations[1] / self.imgWidth),
            list(self.yMarkerLocations[1] / self.imgHeight),
        )
        data["right_position"] = (
            list(self.xMarkerLocations[1] / self.imgWidth),
            list(self.yMarkerLocations[1] / self.imgHeight),
        )
        data["ans_matrix"] = (
            (np.array(self.answerMatrix) > self.settings["answer_threshold"]) * 1
        ).tolist()
        if data["sid"] is None and data["page_no"] == 0:
            data["sid"] = self.get_enhanced_sid()
        return data