Improve screen capture logic
This commit is contained in:
247
owocr/run.py
247
owocr/run.py
@@ -676,7 +676,10 @@ class TextFiltering:
|
|||||||
return changed_lines
|
return changed_lines
|
||||||
|
|
||||||
def _standalone_furigana_filter(self, result, result_ocr):
|
def _standalone_furigana_filter(self, result, result_ocr):
|
||||||
return self._find_changed_lines_text_impl(result, result_ocr, None, [], None, False, 0)
|
result = self._find_changed_lines_text_impl(result, result_ocr, None, [], None, False, 0)
|
||||||
|
if result == None:
|
||||||
|
result = []
|
||||||
|
return result
|
||||||
|
|
||||||
def _find_overlap(self, previous_text, current_text):
|
def _find_overlap(self, previous_text, current_text):
|
||||||
min_overlap_length = 3
|
min_overlap_length = 3
|
||||||
@@ -826,8 +829,11 @@ class ScreenshotThread(threading.Thread):
|
|||||||
self.coordinate_selector_combo_enabled = config.get_general('coordinate_selector_combo') != ''
|
self.coordinate_selector_combo_enabled = config.get_general('coordinate_selector_combo') != ''
|
||||||
self.macos_window_tracker_instance = None
|
self.macos_window_tracker_instance = None
|
||||||
self.windows_window_tracker_instance = None
|
self.windows_window_tracker_instance = None
|
||||||
self.screencapture_window_active = True
|
self.window_active = True
|
||||||
self.screencapture_window_visible = True
|
self.window_visible = True
|
||||||
|
self.window_closed = False
|
||||||
|
self.window_size = None
|
||||||
|
|
||||||
if screen_capture_area == '':
|
if screen_capture_area == '':
|
||||||
self.screencapture_mode = 0
|
self.screencapture_mode = 0
|
||||||
elif screen_capture_area.startswith('screen_'):
|
elif screen_capture_area.startswith('screen_'):
|
||||||
@@ -875,6 +881,7 @@ class ScreenshotThread(threading.Thread):
|
|||||||
self.old_macos_screenshot_api = True
|
self.old_macos_screenshot_api = True
|
||||||
else:
|
else:
|
||||||
self.old_macos_screenshot_api = False
|
self.old_macos_screenshot_api = False
|
||||||
|
self.window_stream_configuration = None
|
||||||
self.screencapturekit_queue = queue.Queue()
|
self.screencapturekit_queue = queue.Queue()
|
||||||
CGMainDisplayID()
|
CGMainDisplayID()
|
||||||
window_list = CGWindowListCopyWindowInfo(kCGWindowListExcludeDesktopElements, kCGNullWindowID)
|
window_list = CGWindowListCopyWindowInfo(kCGWindowListExcludeDesktopElements, kCGNullWindowID)
|
||||||
@@ -913,7 +920,11 @@ class ScreenshotThread(threading.Thread):
|
|||||||
logger.error(area_invalid_error)
|
logger.error(area_invalid_error)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
ctypes.windll.shcore.SetProcessDpiAwareness(1)
|
ctypes.windll.shcore.SetProcessDpiAwareness(2)
|
||||||
|
self.window_visible = not win32gui.IsIconic(self.window_handle)
|
||||||
|
self.windows_window_mfc_dc = None
|
||||||
|
self.windows_window_save_dc = None
|
||||||
|
self.windows_window_save_bitmap = None
|
||||||
|
|
||||||
self.windows_window_tracker_instance = threading.Thread(target=self.windows_window_tracker)
|
self.windows_window_tracker_instance = threading.Thread(target=self.windows_window_tracker)
|
||||||
self.windows_window_tracker_instance.start()
|
self.windows_window_tracker_instance.start()
|
||||||
@@ -927,8 +938,7 @@ class ScreenshotThread(threading.Thread):
|
|||||||
if len(screen_capture_window_area.split(',')) == 4:
|
if len(screen_capture_window_area.split(',')) == 4:
|
||||||
x, y, x2, y2 = [int(c.strip()) for c in screen_capture_window_area.split(',')]
|
x, y, x2, y2 = [int(c.strip()) for c in screen_capture_window_area.split(',')]
|
||||||
logger.info(f'Selected window coordinates: {x},{y},{x2},{y2}')
|
logger.info(f'Selected window coordinates: {x},{y},{x2},{y2}')
|
||||||
img = self.take_screenshot()
|
self.window_area_coordinates = (x, y, x2, y2)
|
||||||
self.window_area_coordinates = (img.size, (x, y, x2, y2))
|
|
||||||
elif screen_capture_window_area == '':
|
elif screen_capture_window_area == '':
|
||||||
self.launch_coordinate_picker(False, False)
|
self.launch_coordinate_picker(False, False)
|
||||||
else:
|
else:
|
||||||
@@ -962,12 +972,11 @@ class ScreenshotThread(threading.Thread):
|
|||||||
if not found:
|
if not found:
|
||||||
break
|
break
|
||||||
if self.screen_capture_only_active_windows:
|
if self.screen_capture_only_active_windows:
|
||||||
self.screencapture_window_active = self.window_handle == win32gui.GetForegroundWindow()
|
self.window_active = self.window_handle == win32gui.GetForegroundWindow()
|
||||||
else:
|
self.window_visible = not win32gui.IsIconic(self.window_handle)
|
||||||
self.screencapture_window_visible = not win32gui.IsIconic(self.window_handle)
|
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
if not found:
|
if not found:
|
||||||
on_window_closed(False)
|
self.window_closed = True
|
||||||
|
|
||||||
def capture_macos_window_screenshot(self, window_id):
|
def capture_macos_window_screenshot(self, window_id):
|
||||||
def shareable_content_completion_handler(shareable_content, error):
|
def shareable_content_completion_handler(shareable_content, error):
|
||||||
@@ -985,22 +994,26 @@ class ScreenshotThread(threading.Thread):
|
|||||||
self.screencapturekit_queue.put(None)
|
self.screencapturekit_queue.put(None)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if not self.window_stream_configuration:
|
||||||
|
self.window_stream_configuration = SCStreamConfiguration.alloc().init()
|
||||||
|
self.window_stream_configuration.setShowsCursor_(False)
|
||||||
|
self.window_stream_configuration.setCaptureResolution_(SCCaptureResolutionNominal)
|
||||||
|
self.window_stream_configuration.setIgnoreGlobalClipSingleWindow_(True)
|
||||||
|
|
||||||
with objc.autorelease_pool():
|
with objc.autorelease_pool():
|
||||||
content_filter = SCContentFilter.alloc().initWithDesktopIndependentWindow_(target_window)
|
content_filter = SCContentFilter.alloc().initWithDesktopIndependentWindow_(target_window)
|
||||||
|
|
||||||
frame = content_filter.contentRect()
|
frame = content_filter.contentRect()
|
||||||
width = frame.size.width
|
width = frame.size.width
|
||||||
height = frame.size.height
|
height = frame.size.height
|
||||||
configuration = SCStreamConfiguration.alloc().init()
|
current_size = (width, height)
|
||||||
configuration.setSourceRect_(CGRectMake(0, 0, width, height))
|
|
||||||
configuration.setWidth_(width)
|
if current_size != self.window_size:
|
||||||
configuration.setHeight_(height)
|
self.window_stream_configuration.setSourceRect_(CGRectMake(0, 0, width, height))
|
||||||
configuration.setShowsCursor_(False)
|
self.window_stream_configuration.setWidth_(width)
|
||||||
configuration.setCaptureResolution_(SCCaptureResolutionNominal)
|
self.window_stream_configuration.setHeight_(height)
|
||||||
configuration.setIgnoreGlobalClipSingleWindow_(True)
|
|
||||||
|
|
||||||
SCScreenshotManager.captureImageWithFilter_configuration_completionHandler_(
|
SCScreenshotManager.captureImageWithFilter_configuration_completionHandler_(
|
||||||
content_filter, configuration, capture_image_completion_handler
|
content_filter, self.window_stream_configuration, capture_image_completion_handler
|
||||||
)
|
)
|
||||||
|
|
||||||
def capture_image_completion_handler(image, error):
|
def capture_image_completion_handler(image, error):
|
||||||
@@ -1013,6 +1026,10 @@ class ScreenshotThread(threading.Thread):
|
|||||||
SCShareableContent.getShareableContentWithCompletionHandler_(
|
SCShareableContent.getShareableContentWithCompletionHandler_(
|
||||||
shareable_content_completion_handler
|
shareable_content_completion_handler
|
||||||
)
|
)
|
||||||
|
try:
|
||||||
|
return self.screencapturekit_queue.get(timeout=5)
|
||||||
|
except queue.Empty:
|
||||||
|
return None
|
||||||
|
|
||||||
def macos_window_tracker(self):
|
def macos_window_tracker(self):
|
||||||
found = True
|
found = True
|
||||||
@@ -1035,29 +1052,38 @@ class ScreenshotThread(threading.Thread):
|
|||||||
if len(window_list) > 0:
|
if len(window_list) > 0:
|
||||||
found = True
|
found = True
|
||||||
if found:
|
if found:
|
||||||
self.screencapture_window_active = is_active
|
self.window_active = is_active
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
if not found:
|
if not found:
|
||||||
on_window_closed(False)
|
self.window_closed = True
|
||||||
|
|
||||||
def take_screenshot(self):
|
def take_screenshot(self, ignore_active_status):
|
||||||
if self.screencapture_mode == 2:
|
if self.screencapture_mode == 2:
|
||||||
|
if self.window_closed:
|
||||||
|
return False
|
||||||
|
if not ignore_active_status and not self.window_active:
|
||||||
|
return None
|
||||||
|
if not self.window_visible:
|
||||||
|
return None
|
||||||
|
|
||||||
|
self.window_size_changed = False
|
||||||
if sys.platform == 'darwin':
|
if sys.platform == 'darwin':
|
||||||
with objc.autorelease_pool():
|
with objc.autorelease_pool():
|
||||||
if self.old_macos_screenshot_api:
|
if self.old_macos_screenshot_api:
|
||||||
cg_image = CGWindowListCreateImageFromArray(CGRectNull, [self.window_id], kCGWindowImageBoundsIgnoreFraming | kCGWindowImageNominalResolution)
|
cg_image = CGWindowListCreateImageFromArray(CGRectNull, [self.window_id], kCGWindowImageBoundsIgnoreFraming | kCGWindowImageNominalResolution)
|
||||||
else:
|
else:
|
||||||
self.capture_macos_window_screenshot(self.window_id)
|
cg_image = self.capture_macos_window_screenshot(self.window_id)
|
||||||
try:
|
|
||||||
cg_image = self.screencapturekit_queue.get(timeout=0.5)
|
|
||||||
except queue.Empty:
|
|
||||||
cg_image = None
|
|
||||||
if not cg_image:
|
if not cg_image:
|
||||||
return None
|
return False
|
||||||
width = CGImageGetWidth(cg_image)
|
width = CGImageGetWidth(cg_image)
|
||||||
height = CGImageGetHeight(cg_image)
|
height = CGImageGetHeight(cg_image)
|
||||||
raw_data = CGDataProviderCopyData(CGImageGetDataProvider(cg_image))
|
raw_data = CGDataProviderCopyData(CGImageGetDataProvider(cg_image))
|
||||||
bpr = CGImageGetBytesPerRow(cg_image)
|
bpr = CGImageGetBytesPerRow(cg_image)
|
||||||
|
current_size = (width, height)
|
||||||
|
if self.window_size != current_size:
|
||||||
|
if self.window_size:
|
||||||
|
self.window_size_changed = True
|
||||||
|
self.window_size = current_size
|
||||||
img = Image.frombuffer('RGBA', (width, height), raw_data, 'raw', 'BGRA', bpr, 1)
|
img = Image.frombuffer('RGBA', (width, height), raw_data, 'raw', 'BGRA', bpr, 1)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
@@ -1065,49 +1091,69 @@ class ScreenshotThread(threading.Thread):
|
|||||||
coord_width = right - coord_left
|
coord_width = right - coord_left
|
||||||
coord_height = bottom - coord_top
|
coord_height = bottom - coord_top
|
||||||
|
|
||||||
|
current_size = (coord_width, coord_height)
|
||||||
|
if self.window_size != current_size:
|
||||||
|
if self.window_size:
|
||||||
|
window_size_changed = True
|
||||||
|
self.reset_windows_window()
|
||||||
|
|
||||||
hwnd_dc = win32gui.GetWindowDC(self.window_handle)
|
hwnd_dc = win32gui.GetWindowDC(self.window_handle)
|
||||||
mfc_dc = win32ui.CreateDCFromHandle(hwnd_dc)
|
self.windows_window_mfc_dc = win32ui.CreateDCFromHandle(hwnd_dc)
|
||||||
save_dc = mfc_dc.CreateCompatibleDC()
|
self.windows_window_save_dc = self.windows_window_mfc_dc.CreateCompatibleDC()
|
||||||
|
self.windows_window_save_bitmap = win32ui.CreateBitmap()
|
||||||
|
self.windows_window_save_bitmap.CreateCompatibleBitmap(self.windows_window_mfc_dc, coord_width, coord_height)
|
||||||
|
self.windows_window_save_dc.SelectObject(self.windows_window_save_bitmap)
|
||||||
|
|
||||||
save_bitmap = win32ui.CreateBitmap()
|
self.window_size = current_size
|
||||||
save_bitmap.CreateCompatibleBitmap(mfc_dc, coord_width, coord_height)
|
win32gui.ReleaseDC(self.window_handle, hwnd_dc)
|
||||||
save_dc.SelectObject(save_bitmap)
|
|
||||||
|
|
||||||
result = ctypes.windll.user32.PrintWindow(self.window_handle, save_dc.GetSafeHdc(), 2)
|
result = ctypes.windll.user32.PrintWindow(self.window_handle, self.windows_window_save_dc.GetSafeHdc(), 2)
|
||||||
|
|
||||||
bmpinfo = save_bitmap.GetInfo()
|
bmpinfo = self.windows_window_save_bitmap.GetInfo()
|
||||||
bmpstr = save_bitmap.GetBitmapBits(True)
|
bmpstr = self.windows_window_save_bitmap.GetBitmapBits(True)
|
||||||
|
|
||||||
|
img = Image.frombuffer('RGB', (bmpinfo['bmWidth'], bmpinfo['bmHeight']), bmpstr, 'raw', 'BGRX', 0, 1)
|
||||||
|
return img
|
||||||
except pywintypes.error:
|
except pywintypes.error:
|
||||||
return None
|
return None
|
||||||
img = Image.frombuffer('RGB', (bmpinfo['bmWidth'], bmpinfo['bmHeight']), bmpstr, 'raw', 'BGRX', 0, 1)
|
|
||||||
try:
|
|
||||||
win32gui.DeleteObject(save_bitmap.GetHandle())
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
save_dc.DeleteDC()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
mfc_dc.DeleteDC()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
win32gui.ReleaseDC(self.window_handle, hwnd_dc)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
if self.window_area_coordinates:
|
if self.window_area_coordinates:
|
||||||
if img.size != self.window_area_coordinates[0]:
|
if self.window_size_changed:
|
||||||
self.window_area_coordinates = None
|
self.window_area_coordinates = None
|
||||||
logger.warning('Window size changed, discarding area selection')
|
logger.warning('Window size changed, discarding area selection')
|
||||||
else:
|
else:
|
||||||
img = img.crop(self.window_area_coordinates[1])
|
img = img.crop(self.window_area_coordinates)
|
||||||
else:
|
else:
|
||||||
sct_img = self.sct.grab(self.sct_params)
|
sct_img = self.sct.grab(self.sct_params)
|
||||||
img = Image.frombytes('RGB', sct_img.size, sct_img.bgra, 'raw', 'BGRX')
|
img = Image.frombytes('RGB', sct_img.size, sct_img.bgra, 'raw', 'BGRX')
|
||||||
|
|
||||||
return img
|
return img
|
||||||
|
|
||||||
|
def cleanup_window_screen_capture(self):
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
try:
|
||||||
|
if self.windows_window_save_bitmap:
|
||||||
|
win32gui.DeleteObject(self.windows_window_save_bitmap.GetHandle())
|
||||||
|
self.windows_window_save_bitmap = None
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
if self.windows_window_save_dc:
|
||||||
|
self.windows_window_save_dc.DeleteDC()
|
||||||
|
self.windows_window_save_dc = None
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
if self.windows_window_mfc_dc:
|
||||||
|
self.windows_window_mfc_dc.DeleteDC()
|
||||||
|
self.windows_window_mfc_dc = None
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
elif not self.old_macos_screenshot_api:
|
||||||
|
if self.window_stream_configuration:
|
||||||
|
self.window_stream_configuration.dealloc()
|
||||||
|
self.window_stream_configuration = None
|
||||||
|
|
||||||
def write_result(self, result, is_combo):
|
def write_result(self, result, is_combo):
|
||||||
if is_combo:
|
if is_combo:
|
||||||
image_queue.put((result, True))
|
image_queue.put((result, True))
|
||||||
@@ -1144,8 +1190,11 @@ class ScreenshotThread(threading.Thread):
|
|||||||
logger.info(f'Selected coordinates: {coord_left},{coord_top},{coord_width},{coord_height}')
|
logger.info(f'Selected coordinates: {coord_left},{coord_top},{coord_width},{coord_height}')
|
||||||
else:
|
else:
|
||||||
self.window_area_coordinates = None
|
self.window_area_coordinates = None
|
||||||
img = self.take_screenshot()
|
|
||||||
logger.info('Launching window coordinate picker')
|
logger.info('Launching window coordinate picker')
|
||||||
|
img = self.take_screenshot(True)
|
||||||
|
if not img:
|
||||||
|
window_selection = False
|
||||||
|
else:
|
||||||
window_selection = get_screen_selection(img, self.coordinate_selector_combo_enabled)
|
window_selection = get_screen_selection(img, self.coordinate_selector_combo_enabled)
|
||||||
if not window_selection:
|
if not window_selection:
|
||||||
logger.warning('Picker window was closed or an error occurred, selecting whole window')
|
logger.warning('Picker window was closed or an error occurred, selecting whole window')
|
||||||
@@ -1155,7 +1204,7 @@ class ScreenshotThread(threading.Thread):
|
|||||||
x2 = x + coord_width
|
x2 = x + coord_width
|
||||||
y2 = y + coord_height
|
y2 = y + coord_height
|
||||||
logger.info(f'Selected window coordinates: {x},{y},{x2},{y2}')
|
logger.info(f'Selected window coordinates: {x},{y},{x2},{y2}')
|
||||||
self.window_area_coordinates = (img.size, (x, y, x2, y2))
|
self.window_area_coordinates = (x, y, x2, y2)
|
||||||
else:
|
else:
|
||||||
logger.info('Selection is empty, selecting whole window')
|
logger.info('Selection is empty, selecting whole window')
|
||||||
|
|
||||||
@@ -1172,13 +1221,14 @@ class ScreenshotThread(threading.Thread):
|
|||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
img = self.take_screenshot()
|
img = self.take_screenshot(False)
|
||||||
if not img:
|
|
||||||
self.write_result(0, is_combo)
|
|
||||||
break
|
|
||||||
|
|
||||||
self.write_result(img, is_combo)
|
self.write_result(img, is_combo)
|
||||||
|
|
||||||
|
if img == False:
|
||||||
|
break
|
||||||
|
|
||||||
|
if self.screencapture_mode == 2:
|
||||||
|
self.cleanup_window_screen_capture()
|
||||||
if self.macos_window_tracker_instance:
|
if self.macos_window_tracker_instance:
|
||||||
self.macos_window_tracker_instance.join()
|
self.macos_window_tracker_instance.join()
|
||||||
elif self.windows_window_tracker_instance:
|
elif self.windows_window_tracker_instance:
|
||||||
@@ -1280,6 +1330,11 @@ class SecondPassThread:
|
|||||||
class OutputResult:
|
class OutputResult:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.screen_capture_periodic = config.get_general('screen_capture_delay_secs') != -1
|
self.screen_capture_periodic = config.get_general('screen_capture_delay_secs') != -1
|
||||||
|
self.output_format = config.get_general('output_format')
|
||||||
|
self.engine_color = config.get_general('engine_color')
|
||||||
|
self.verbosity = config.get_general('verbosity')
|
||||||
|
self.notifications = config.get_general('notifications')
|
||||||
|
self.write_to = config.get_general('write_to')
|
||||||
self.filtering = TextFiltering()
|
self.filtering = TextFiltering()
|
||||||
self.second_pass_thread = SecondPassThread()
|
self.second_pass_thread = SecondPassThread()
|
||||||
|
|
||||||
@@ -1305,8 +1360,6 @@ class OutputResult:
|
|||||||
|
|
||||||
def __call__(self, img_or_path, filter_text, auto_pause, notify):
|
def __call__(self, img_or_path, filter_text, auto_pause, notify):
|
||||||
engine_index_local = engine_index
|
engine_index_local = engine_index
|
||||||
output_format = config.get_general('output_format')
|
|
||||||
engine_color = config.get_general('engine_color')
|
|
||||||
engine_instance = engine_instances[engine_index]
|
engine_instance = engine_instances[engine_index]
|
||||||
two_pass_processing_active = False
|
two_pass_processing_active = False
|
||||||
result_data = None
|
result_data = None
|
||||||
@@ -1320,14 +1373,15 @@ class OutputResult:
|
|||||||
end_time = time.time()
|
end_time = time.time()
|
||||||
|
|
||||||
if not res2:
|
if not res2:
|
||||||
logger.opt(colors=True).warning(f'<{engine_color}>{engine_instance_2.readable_name}</{engine_color}> reported an error after {end_time - start_time:0.03f}s: {result_data_2}')
|
logger.opt(colors=True).warning(f'<{self.engine_color}>{engine_instance_2.readable_name}</{self.engine_color}> reported an error after {end_time - start_time:0.03f}s: {result_data_2}')
|
||||||
else:
|
else:
|
||||||
changed_lines_count, recovered_lines_count, changed_regions_image = self.filtering._find_changed_lines(img_or_path, result_data_2)
|
changed_lines_count, recovered_lines_count, changed_regions_image = self.filtering._find_changed_lines(img_or_path, result_data_2)
|
||||||
|
|
||||||
if changed_lines_count or recovered_lines_count:
|
if changed_lines_count or recovered_lines_count:
|
||||||
logger.opt(colors=True).info(f"<{engine_color}>{engine_instance_2.readable_name}</{engine_color}> found {changed_lines_count + recovered_lines_count} changed line(s) in {end_time - start_time:0.03f}s, re-OCRing with <{engine_color}>{engine_instance.readable_name}</{engine_color}>")
|
if self.verbosity != 0:
|
||||||
|
logger.opt(colors=True).info(f"<{self.engine_color}>{engine_instance_2.readable_name}</{self.engine_color}> found {changed_lines_count + recovered_lines_count} changed line(s) in {end_time - start_time:0.03f}s, re-OCRing with <{self.engine_color}>{engine_instance.readable_name}</{self.engine_color}>")
|
||||||
|
|
||||||
if output_format != 'json':
|
if self.output_format != 'json':
|
||||||
if changed_regions_image:
|
if changed_regions_image:
|
||||||
img_or_path = changed_regions_image
|
img_or_path = changed_regions_image
|
||||||
|
|
||||||
@@ -1356,10 +1410,9 @@ class OutputResult:
|
|||||||
if not res:
|
if not res:
|
||||||
if auto_pause_handler and auto_pause:
|
if auto_pause_handler and auto_pause:
|
||||||
auto_pause_handler.stop_timer()
|
auto_pause_handler.stop_timer()
|
||||||
logger.opt(colors=True).warning(f'<{engine_color}>{engine_name}</{engine_color}> reported an error after {processing_time:0.03f}s: {result_data}')
|
logger.opt(colors=True).warning(f'<{self.engine_color}>{engine_name}</{self.engine_color}> reported an error after {processing_time:0.03f}s: {result_data}')
|
||||||
return
|
return
|
||||||
|
|
||||||
verbosity = config.get_general('verbosity')
|
|
||||||
output_string = ''
|
output_string = ''
|
||||||
log_message = ''
|
log_message = ''
|
||||||
result_data_text = None
|
result_data_text = None
|
||||||
@@ -1367,7 +1420,7 @@ class OutputResult:
|
|||||||
if isinstance(result_data, OcrResult):
|
if isinstance(result_data, OcrResult):
|
||||||
unprocessed_text = self._extract_lines_from_result(result_data)
|
unprocessed_text = self._extract_lines_from_result(result_data)
|
||||||
|
|
||||||
if output_format == 'json':
|
if self.output_format == 'json':
|
||||||
result_dict = asdict(result_data)
|
result_dict = asdict(result_data)
|
||||||
output_string = json.dumps(result_dict, ensure_ascii=False)
|
output_string = json.dumps(result_dict, ensure_ascii=False)
|
||||||
log_message = self._post_process(unprocessed_text, False)
|
log_message = self._post_process(unprocessed_text, False)
|
||||||
@@ -1390,26 +1443,25 @@ class OutputResult:
|
|||||||
output_string = self._post_process(result_data_text, False)
|
output_string = self._post_process(result_data_text, False)
|
||||||
log_message = output_string
|
log_message = output_string
|
||||||
|
|
||||||
if verbosity != 0:
|
if self.verbosity != 0:
|
||||||
if verbosity < -1:
|
if self.verbosity < -1:
|
||||||
log_message_terminal = ': ' + log_message
|
log_message_terminal = ': ' + log_message
|
||||||
elif verbosity == -1:
|
elif self.verbosity == -1:
|
||||||
log_message_terminal = ''
|
log_message_terminal = ''
|
||||||
else:
|
else:
|
||||||
log_message_terminal = ': ' + (log_message if len(log_message) <= verbosity else log_message[:verbosity] + '[...]')
|
log_message_terminal = ': ' + (log_message if len(log_message) <= self.verbosity else log_message[:self.verbosity] + '[...]')
|
||||||
|
|
||||||
logger.opt(colors=True).info(f'Text recognized in {processing_time:0.03f}s using <{engine_color}>{engine_name}</{engine_color}>{log_message_terminal}')
|
logger.opt(colors=True).info(f'Text recognized in {processing_time:0.03f}s using <{self.engine_color}>{engine_name}</{self.engine_color}>{log_message_terminal}')
|
||||||
|
|
||||||
if notify and config.get_general('notifications'):
|
if notify and self.notifications:
|
||||||
notifier.send(title='owocr', message='Text recognized: ' + log_message, urgency=get_notification_urgency())
|
notifier.send(title='owocr', message='Text recognized: ' + log_message, urgency=get_notification_urgency())
|
||||||
|
|
||||||
write_to = config.get_general('write_to')
|
if self.write_to == 'websocket':
|
||||||
if write_to == 'websocket':
|
|
||||||
websocket_server_thread.send_text(output_string)
|
websocket_server_thread.send_text(output_string)
|
||||||
elif write_to == 'clipboard':
|
elif self.write_to == 'clipboard':
|
||||||
pyperclipfix.copy(output_string)
|
pyperclipfix.copy(output_string)
|
||||||
else:
|
else:
|
||||||
with Path(write_to).open('a', encoding='utf-8') as f:
|
with Path(self.write_to).open('a', encoding='utf-8') as f:
|
||||||
f.write(output_string + '\n')
|
f.write(output_string + '\n')
|
||||||
|
|
||||||
if auto_pause_handler and auto_pause:
|
if auto_pause_handler and auto_pause:
|
||||||
@@ -1456,12 +1508,13 @@ def engine_change_handler(user_input='s', is_combo=True):
|
|||||||
logger.opt(colors=True).info(f'Switched to <{engine_color}>{new_engine_name}</{engine_color}>!')
|
logger.opt(colors=True).info(f'Switched to <{engine_color}>{new_engine_name}</{engine_color}>!')
|
||||||
|
|
||||||
|
|
||||||
def user_input_thread_run():
|
def terminate_handler(sig=None, frame=None):
|
||||||
def _terminate_handler():
|
|
||||||
global terminated
|
global terminated
|
||||||
logger.info('Terminated!')
|
logger.info('Terminated!')
|
||||||
terminated.set()
|
terminated.set()
|
||||||
|
|
||||||
|
|
||||||
|
def user_input_thread_run():
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
import msvcrt
|
import msvcrt
|
||||||
while not terminated.is_set():
|
while not terminated.is_set():
|
||||||
@@ -1473,7 +1526,7 @@ def user_input_thread_run():
|
|||||||
user_input_bytes = msvcrt.getch()
|
user_input_bytes = msvcrt.getch()
|
||||||
user_input = user_input_bytes.decode()
|
user_input = user_input_bytes.decode()
|
||||||
if user_input.lower() in 'tq':
|
if user_input.lower() in 'tq':
|
||||||
_terminate_handler()
|
terminate_handler()
|
||||||
elif user_input.lower() == 'p':
|
elif user_input.lower() == 'p':
|
||||||
pause_handler(False)
|
pause_handler(False)
|
||||||
else:
|
else:
|
||||||
@@ -1502,7 +1555,7 @@ def user_input_thread_run():
|
|||||||
if rlist:
|
if rlist:
|
||||||
user_input = sys.stdin.read(1)
|
user_input = sys.stdin.read(1)
|
||||||
if user_input.lower() in 'tq':
|
if user_input.lower() in 'tq':
|
||||||
_terminate_handler()
|
terminate_handler()
|
||||||
elif user_input.lower() == 'p':
|
elif user_input.lower() == 'p':
|
||||||
pause_handler(False)
|
pause_handler(False)
|
||||||
else:
|
else:
|
||||||
@@ -1511,19 +1564,6 @@ def user_input_thread_run():
|
|||||||
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
|
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
|
||||||
|
|
||||||
|
|
||||||
def signal_handler(sig, frame):
|
|
||||||
global terminated
|
|
||||||
logger.info('Terminated!')
|
|
||||||
terminated.set()
|
|
||||||
|
|
||||||
|
|
||||||
def on_window_closed(alive):
|
|
||||||
global terminated
|
|
||||||
if not (alive or terminated):
|
|
||||||
logger.info('Window closed or error occurred, terminated!')
|
|
||||||
terminated.set()
|
|
||||||
|
|
||||||
|
|
||||||
def on_screenshot_combo():
|
def on_screenshot_combo():
|
||||||
screenshot_request_queue.put(True)
|
screenshot_request_queue.put(True)
|
||||||
|
|
||||||
@@ -1701,7 +1741,7 @@ def run():
|
|||||||
write_to_readable = f'file {write_to}'
|
write_to_readable = f'file {write_to}'
|
||||||
|
|
||||||
process_queue = (any(i in ('clipboard', 'websocket', 'unixsocket') for i in (read_from, read_from_secondary)) or read_from_path or screen_capture_on_combo)
|
process_queue = (any(i in ('clipboard', 'websocket', 'unixsocket') for i in (read_from, read_from_secondary)) or read_from_path or screen_capture_on_combo)
|
||||||
signal.signal(signal.SIGINT, signal_handler)
|
signal.signal(signal.SIGINT, terminate_handler)
|
||||||
if auto_pause != 0:
|
if auto_pause != 0:
|
||||||
auto_pause_handler = AutopauseTimer()
|
auto_pause_handler = AutopauseTimer()
|
||||||
user_input_thread = threading.Thread(target=user_input_thread_run, daemon=True)
|
user_input_thread = threading.Thread(target=user_input_thread_run, daemon=True)
|
||||||
@@ -1727,8 +1767,8 @@ def run():
|
|||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if (not img) and screen_capture_periodic:
|
if img == None and screen_capture_periodic:
|
||||||
if (not paused.is_set()) and screenshot_thread.screencapture_window_active and screenshot_thread.screencapture_window_visible and (time.time() - last_screenshot_time) > screen_capture_delay_secs:
|
if (not paused.is_set()) and (time.time() - last_screenshot_time) > screen_capture_delay_secs:
|
||||||
if periodic_screenshot_queue.empty() and screenshot_request_queue.empty():
|
if periodic_screenshot_queue.empty() and screenshot_request_queue.empty():
|
||||||
screenshot_request_queue.put(False)
|
screenshot_request_queue.put(False)
|
||||||
try:
|
try:
|
||||||
@@ -1739,8 +1779,8 @@ def run():
|
|||||||
skip_waiting = True
|
skip_waiting = True
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if img == 0:
|
if img == False:
|
||||||
on_window_closed(False)
|
logger.info('The window was closed or an error occurred, terminated!')
|
||||||
terminated.set()
|
terminated.set()
|
||||||
break
|
break
|
||||||
elif img:
|
elif img:
|
||||||
@@ -1753,8 +1793,9 @@ def run():
|
|||||||
|
|
||||||
terminate_selector_if_running()
|
terminate_selector_if_running()
|
||||||
user_input_thread.join()
|
user_input_thread.join()
|
||||||
auto_pause_handler.stop()
|
|
||||||
output_result.second_pass_thread.stop()
|
output_result.second_pass_thread.stop()
|
||||||
|
if auto_pause_handler:
|
||||||
|
auto_pause_handler.stop()
|
||||||
if websocket_server_thread:
|
if websocket_server_thread:
|
||||||
websocket_server_thread.stop_server()
|
websocket_server_thread.stop_server()
|
||||||
websocket_server_thread.join()
|
websocket_server_thread.join()
|
||||||
|
|||||||
Reference in New Issue
Block a user