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) )
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
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
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
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
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
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