def handle(self, request: NormcapData) -> NormcapData:
        """Execute chain of optimizations.

        Arguments:
            AbstractHandler {class} -- self
            request {NormcapData} -- NormCap's session data

        Returns:
            NormcapData -- NormCap's session data with optimized image
        """
        self._logger.info("Applying enhancements to image...")

        # Currently, the image is only enlarged
        # for other strategies see: https://stackoverflow.com/a/50762612
        if request.image:
            request.image = self._enlarge_dpi(request.image)
            # request.image = self._grayscale(request.image)
            # request.image = self._denoise(request.image)
            # request.image = self._threshold(request.image)
            # request.image = self._add_padding(request.image)
            # request.image = self._strech_contrast(request.image)

        if self._next_handler:
            return super().handle(request)
        else:
            return request
def test_capture_handler():
    """Test if screenshots are added to data object."""
    data = NormcapData()
    capture = CaptureHandler()
    result = capture.handle(data)
    assert (len(result.shots) > 0) and (
        isinstance(result.shots[0]["image"], Image.Image)
    )
Exemple #3
0
    def handle(self, request: NormcapData) -> NormcapData:
        """Load magics, calculate score, execture magic with highest score.

        Arguments:
            AbstractHandler {class} -- self
            request {NormcapData} -- NormCap's session data

        Returns:
            NormcapData -- Enriched NormCap's session data
        """
        if request.mode != "raw":  # Skip all magics, if raw mode enabled
            # Import magics here (to only load, when needed)!
            from normcap.magics.single_line_magic import SingleLineMagic
            from normcap.magics.multi_line_magic import MultiLineMagic
            from normcap.magics.paragraph_magic import ParagraphMagic
            from normcap.magics.email_magic import EmailMagic
            from normcap.magics.url_magic import UrlMagic

            # Load Magics
            magics_classes = [
                SingleLineMagic,
                MultiLineMagic,
                ParagraphMagic,
                EmailMagic,
                UrlMagic,
            ]

            for magic in magics_classes:
                self._magics[magic.name] = magic()

            # Calculate scores
            scores = self._calc_scores(request)
            request.scores = scores

            # Select winning magic
            best_magic_name = self._get_best_magic(scores)

            # Transform with best magic
            best_magic = self._magics[best_magic_name]
            request.best_magic = best_magic_name
            request.transformed = best_magic.transform(request)

        if self._next_handler:
            return super().handle(request)
        else:
            return request
Exemple #4
0
def test_data():
    """Create NormcapData instance for testing."""
    data = NormcapData()
    data.top = 0
    data.bottom = 10
    data.left = 0
    data.right = 20
    data.words = [
        {
            "line_num": 1,
            "block_num": 1,
            "par_num": 1,
            "text": "one"
        },
        {
            "line_num": 2,
            "block_num": 1,
            "par_num": 1,
            "text": "two"
        },
        {
            "line_num": 2,
            "block_num": 1,
            "par_num": 2,
            "text": "three"
        },
        {
            "line_num": 3,
            "block_num": 1,
            "par_num": 2,
            "text": "four"
        },
    ]
    return data
    def _select_region_with_gui(self, request: NormcapData) -> NormcapData:
        """Show window(s) with screenshots and select region.

        Arguments:
            request {NormcapData} -- NormCap's session data

        Returns:
            dict -- Selected region {"bottom": <int>,
                                     "top": <int>,
                                     "left": <int>,
                                     "right": <int>,
                                     "monitor": <int>,
                                     "mode": <int>}
        """
        # Create dummy window plus one for every monitor
        root = _RootWindow(request.cli_args, request.platform)
        for shot in request.shots:
            _CropWindow(root, shot)
        root.mainloop()

        # Store result in request class
        result = root.props.crop_result
        if result:
            request.bottom = result["lower"]
            request.top = result["upper"]
            request.left = result["left"]
            request.right = result["right"]
            request.monitor = result["monitor"]
            request.mode = result["mode"]
        else:
            self._logger.info("Exiting. No selection done.")
            sys.exit(0)

        return request
Exemple #6
0
    def _select_region(self, request: NormcapData) -> NormcapData:
        """Show window(s) with screenshots and select region.

        Arguments:
            request {NormcapData} -- NormCap's session data

        Returns:
            dict -- Selected region {"bottom": <int>,
                                     "top": <int>,
                                     "left": <int>,
                                     "right": <int>,
                                     "monitor": <int>,
                                     "mode": <int>}
        """
        # Create dummy window plus one for every monitor
        # root = _RootWindow(request.cli_args, request.platform)
        # for shot in request.shots:
        # _CropWindow(root, shot)
        # root.mainloop()

        # Store result in request class
        # result = root.props.crop_result

        request.bottom = self.lower
        request.top = self.upper
        request.left = self.left
        request.right = self.right
        request.monitor = 0
        request.mode = 'parse'

        return request
Exemple #7
0
def main(test_data: NormcapData = None):
    """Main program logic."""

    # Init Logger
    logger = init_logging(logging.INFO, to_file=False)
    logger.info("Starting NormCap v%s ...", __version__)

    # Init Normcap Data
    if test_data and test_data.test_mode:
        logger.info("Running in test mode...")
        args = test_data.cli_args
        normcap_data = test_data
    else:
        arg_parser = create_argparser()
        args = vars(arg_parser.parse_args())
        normcap_data = NormcapData(cli_args=args)

    # Set adjust loglevel
    if args["verbose"]:
        logging.getLogger().setLevel(logging.DEBUG)
    else:
        logging.getLogger().setLevel(logging.WARN)

    # Define Handlers
    capture = CaptureHandler()
    crop = CropHandler(int(args['left']), int(args['upper']),
                       int(args['right']), int(args['bottom']))
    enhance_img = EnhanceImgHandler()
    store = StoreHandler()
    ocr = OcrHandler()
    magics = MagicHandler()
    clipboard = ClipboardHandler()
    notification = NotificationHandler()

    # Define Chain of Responsibilities
    # fmt: off
    capture.set_next(crop) \
           .set_next(enhance_img) \
           .set_next(store) \
           .set_next(ocr) \
           .set_next(magics) \
           .set_next(clipboard)
    #    .set_next(notification)
    # fmt: on

    # Run chain
    normcap_data = client_code(capture, normcap_data)

    logger.debug("Final data object:%s", normcap_data)

    return normcap_data
    def _crop_image(request: NormcapData) -> NormcapData:
        """Crop monitor's image and append to session data.

        Arguments:
            request {NormcapData} -- NormCap's session data

        Returns:
            NormcapData -- Enriched NormCap's session data
        """
        img = request.shots[request.monitor]
        cropped_img = img["image"].crop(
            (request.left, request.top, request.right, request.bottom))
        request.image = cropped_img
        return request
    def handle(self, request: NormcapData) -> NormcapData:
        """Apply OCR on selected image section.

        Arguments:
            AbstractHandler {class} -- self
            request {NormcapData} -- NormCap's session data

        Returns:
            NormcapData -- Enriched NormCap's session data
        """
        self._logger.info("Applying OCR...")

        request.cli_args["lang"] = self.get_language(request.cli_args["lang"])

        # Actual OCR & transformation
        request.words = self.img_to_dict(request.image,
                                         request.cli_args["lang"])

        self._logger.debug("Dataclass after OCR:%s", request)

        if self._next_handler:
            return super().handle(request)

        return request
Exemple #10
0
    def _select_region_with_gui(self, request: NormcapData) -> NormcapData:
        """Show window(s) with screenshots and select region.

        Arguments:
            request {NormcapData} -- NormCap's session data

        Returns:
            dict -- Selected region {"bottom": <int>,
                                     "top": <int>,
                                     "left": <int>,
                                     "right": <int>,
                                     "monitor": <int>,
                                     "mode": <int>}
        """
        # Create window for every monitor
        root = tkinter.Tk()
        for idx, shot in enumerate(request.shots):
            if idx == 0:
                _CropWindow(root, root, shot, request.cli_args)
            else:
                top = tkinter.Toplevel()
                _CropWindow(root, top, shot, request.cli_args)
        root.mainloop()

        # Store result in request class
        result = root.result
        if result:
            request.bottom = result["lower"]
            request.top = result["upper"]
            request.left = result["left"]
            request.right = result["right"]
            request.monitor = result["monitor"]
            request.mode = result["mode"]
        else:
            self._logger.info("Exiting. No selection done.")
            sys.exit(0)

        return request
def data_test_image(test_params):
    """Create NormcapData instance for testing."""
    data = NormcapData()
    data.test_mode = True
    data.cli_args = test_params["cli_args"]
    data.top = test_params["position"]["top"]
    data.bottom = test_params["position"]["bottom"]
    data.left = test_params["position"]["left"]
    data.right = test_params["position"]["right"]
    data.mode = test_params["cli_args"]["mode"]

    # Prep images
    test_img_folder = os.path.dirname(os.path.abspath(__file__)) + "/images/"
    img = Image.open(test_img_folder + test_params["filename"])
    data.shots = [{"monitor": 0, "image": img}]

    # Set tempfolder for storing
    data.cli_args["path"] = tempfile.gettempdir()

    return data
Exemple #12
0
def test_data():
    """Create NormcapData instance for testing."""
    data = NormcapData()
    data.cli_args = {
        "verbose": True,
        "mode": "parse",
        "lang": "eng+deu",
        "color": "#FF0000",
        "path": None,
    }
    data.test_mode = True
    data.top = 0
    data.bottom = 10
    data.left = 0
    data.right = 20
    data.words = [
        {"line_num": 1, "text": "one"},
        {"line_num": 2, "text": "two"},
        {"line_num": 2, "text": "three"},
        {"line_num": 3, "text": "four"},
    ]  # Space to check trimming

    test_img_folder = os.path.dirname(os.path.abspath(__file__)) + "/images/"
    img = Image.open(test_img_folder + "test_email_magic_1.jpg")
    data.shots = [{"monitor": 0, "image": img}]
    data.image = img

    return data