GameSentenceMiner 2.13.0__py3-none-any.whl → 2.13.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,7 +11,6 @@ import json
11
11
  import base64
12
12
  from urllib.parse import urlparse, parse_qs
13
13
 
14
- import jaconv
15
14
  import numpy as np
16
15
  import rapidfuzz.fuzz
17
16
  from PIL import Image
@@ -95,6 +94,7 @@ def empty_post_process(text):
95
94
 
96
95
 
97
96
  def post_process(text, keep_blank_lines=False):
97
+ import jaconv
98
98
  if keep_blank_lines:
99
99
  text = '\n'.join([''.join(i.split()) for i in text.splitlines()])
100
100
  else:
@@ -344,7 +344,6 @@ class GoogleLens:
344
344
  text = response_dict['objects_response']['text']
345
345
  skipped = []
346
346
  previous_line = None
347
- lines = []
348
347
  if 'text_layout' in text:
349
348
  for paragraph in text['text_layout']['paragraphs']:
350
349
  if previous_line:
@@ -360,38 +359,21 @@ class GoogleLens:
360
359
  if vertical_space > avg_height * 2:
361
360
  res += 'BLANK_LINE'
362
361
  for line in paragraph['lines']:
363
- # Build a list of word boxes for this line
364
- words_info = []
365
- for word in line['words']:
366
- word_info = {
367
- "word": word['plain_text'],
368
- "x1": int(word['geometry']['bounding_box']['center_x'] * img.width - (word['geometry']['bounding_box']['width'] * img.width) / 2),
369
- "y1": int(word['geometry']['bounding_box']['center_y'] * img.height - (word['geometry']['bounding_box']['height'] * img.height) / 2),
370
- "x2": int(word['geometry']['bounding_box']['center_x'] * img.width + (word['geometry']['bounding_box']['width'] * img.width) / 2),
371
- "y2": int(word['geometry']['bounding_box']['center_y'] * img.height + (word['geometry']['bounding_box']['height'] * img.height) / 2)
372
- }
373
- words_info.append(word_info)
374
-
375
- line_text = ''.join([w['word'] for w in words_info])
376
- line_box = {
377
- "sentence": line_text,
378
- "words": words_info
379
- }
380
-
381
- # Optionally apply furigana filter
382
362
  if furigana_filter_sensitivity:
383
- line_width = line['geometry']['bounding_box']['width'] * img.width
384
- line_height = line['geometry']['bounding_box']['height'] * img.height
385
- if furigana_filter_sensitivity < line_width and furigana_filter_sensitivity < line_height and self.regex.search(line_text):
386
- for w in words_info:
387
- res += w['word']
388
- else:
389
- skipped.extend([w['word'] for w in words_info])
390
- continue
363
+ for word in line['words']:
364
+ if 'geometry' not in word:
365
+ res += word['plain_text']
366
+ continue
367
+ word_width = word['geometry']['bounding_box']['width'] * img.width
368
+ word_height = word['geometry']['bounding_box']['height'] * img.height
369
+ if word_width > furigana_filter_sensitivity and word_height > furigana_filter_sensitivity:
370
+ res += word['plain_text']
371
+ else:
372
+ skipped.extend([word['plain_text'] for word in line['words']])
373
+ continue
391
374
  else:
392
- for w in words_info:
393
- res += w['word']
394
- lines.append(line_box)
375
+ for word in line['words']:
376
+ res += word['plain_text']
395
377
  previous_line = paragraph
396
378
  res += '\n'
397
379
  # logger.info(
@@ -436,10 +418,13 @@ class GoogleLens:
436
418
  # res += '\n'
437
419
 
438
420
  if return_coords:
439
- x = (True, res, lines)
421
+ x = (True, res, response_dict)
440
422
  else:
441
423
  x = (True, res)
442
424
 
425
+ if skipped:
426
+ logger.info(f"Skipped {len(skipped)} chars due to furigana filter sensitivity: {furigana_filter_sensitivity}")
427
+
443
428
  # img.close()
444
429
  return x
445
430
 
@@ -887,7 +872,28 @@ class OneOCR:
887
872
  except:
888
873
  logger.warning('Error reading URL from config, OneOCR will not work!')
889
874
 
890
- def __call__(self, img, furigana_filter_sensitivity=0, sentence_to_check=None, return_coords=False):
875
+ def get_regex(self, lang):
876
+ if lang == "ja":
877
+ self.regex = re.compile(r'[\u3041-\u3096\u30A1-\u30FA\u4E00-\u9FFF]')
878
+ elif lang == "zh":
879
+ self.regex = re.compile(r'[\u4E00-\u9FFF]')
880
+ elif lang == "ko":
881
+ self.regex = re.compile(r'[\uAC00-\uD7AF]')
882
+ elif lang == "ar":
883
+ self.regex = re.compile(r'[\u0600-\u06FF\u0750-\u077F\u08A0-\u08FF\uFB50-\uFDFF\uFE70-\uFEFF]')
884
+ elif lang == "ru":
885
+ self.regex = re.compile(r'[\u0400-\u04FF\u0500-\u052F\u2DE0-\u2DFF\uA640-\uA69F\u1C80-\u1C8F]')
886
+ elif lang == "el":
887
+ self.regex = re.compile(r'[\u0370-\u03FF\u1F00-\u1FFF]')
888
+ elif lang == "he":
889
+ self.regex = re.compile(r'[\u0590-\u05FF\uFB1D-\uFB4F]')
890
+ elif lang == "th":
891
+ self.regex = re.compile(r'[\u0E00-\u0E7F]')
892
+ else:
893
+ self.regex = re.compile(
894
+ r'[a-zA-Z\u00C0-\u00FF\u0100-\u017F\u0180-\u024F\u0250-\u02AF\u1D00-\u1D7F\u1D80-\u1DBF\u1E00-\u1EFF\u2C60-\u2C7F\uA720-\uA7FF\uAB30-\uAB6F]')
895
+
896
+ def __call__(self, img, furigana_filter_sensitivity=0, return_coords=False):
891
897
  lang = get_ocr_language()
892
898
  if lang != self.initial_lang:
893
899
  self.initial_lang = lang
@@ -911,6 +917,10 @@ class OneOCR:
911
917
  json.dump(ocr_resp, f, indent=4, ensure_ascii=False)
912
918
  # print(json.dumps(ocr_resp))
913
919
  filtered_lines = [line for line in ocr_resp['lines'] if self.regex.search(line['text'])]
920
+ x_coords = [line['bounding_rect'][f'x{i}'] for line in filtered_lines for i in range(1, 5)]
921
+ y_coords = [line['bounding_rect'][f'y{i}'] for line in filtered_lines for i in range(1, 5)]
922
+ if x_coords and y_coords:
923
+ crop_coords = (min(x_coords) - 5, min(y_coords) - 5, max(x_coords) + 5, max(y_coords) + 5)
914
924
  # logger.info(filtered_lines)
915
925
  res = ''
916
926
  skipped = []
@@ -964,30 +974,6 @@ class OneOCR:
964
974
  # else:
965
975
  # continue
966
976
  # res += '\n'
967
- elif sentence_to_check:
968
- lines_to_build_area = []
969
- widths = []
970
- heights = []
971
- for line in ocr_resp['lines']:
972
- print(line['text'])
973
- if sentence_to_check in line['text'] or line['text'] in sentence_to_check or rapidfuzz.fuzz.partial_ratio(sentence_to_check, line['text']) > 50:
974
- lines_to_build_area.append(line)
975
- res += line['text']
976
- for word in line['words']:
977
- widths.append(word['bounding_rect']['x2'] - word['bounding_rect']['x1'])
978
- heights.append(word['bounding_rect']['y3'] - word['bounding_rect']['y1'])
979
-
980
- x_coords = [line['bounding_rect'][f'x{i}'] for line in lines_to_build_area for i in
981
- range(1, 5)]
982
- y_coords = [line['bounding_rect'][f'y{i}'] for line in lines_to_build_area for i in
983
- range(1, 5)]
984
- if widths:
985
- avg_width = sum(widths) / len(widths)
986
- if heights:
987
- avg_height = sum(heights) / len(heights)
988
- if x_coords and y_coords:
989
- crop_coords = (
990
- min(x_coords) - 5, min(y_coords) - 5, max(x_coords) + 5, max(y_coords) + 5)
991
977
  elif return_coords:
992
978
  for line in filtered_lines:
993
979
  for word in line['words']:
@@ -998,10 +984,6 @@ class OneOCR:
998
984
  boxes.append(box)
999
985
  res = ocr_resp['text']
1000
986
  else:
1001
- x_coords = [line['bounding_rect'][f'x{i}'] for line in filtered_lines for i in range(1, 5)]
1002
- y_coords = [line['bounding_rect'][f'y{i}'] for line in filtered_lines for i in range(1, 5)]
1003
- if x_coords and y_coords:
1004
- crop_coords = (min(x_coords) - 5, min(y_coords) - 5, max(x_coords) + 5, max(y_coords) + 5)
1005
987
  res = ocr_resp['text']
1006
988
 
1007
989
  except RuntimeError as e:
@@ -1019,7 +1001,7 @@ class OneOCR:
1019
1001
 
1020
1002
  res = res.json()['text']
1021
1003
  if return_coords:
1022
- x = (True, res, boxes)
1004
+ x = (True, res, filtered_lines)
1023
1005
  else:
1024
1006
  x = (True, res, crop_coords)
1025
1007
  if is_path:
@@ -44,7 +44,6 @@ import queue
44
44
  from datetime import datetime
45
45
  from PIL import Image, ImageDraw, UnidentifiedImageError
46
46
  from loguru import logger
47
- from pynput import keyboard
48
47
  from desktop_notifier import DesktopNotifierSync
49
48
  import psutil
50
49
 
@@ -384,6 +383,7 @@ class TextFiltering:
384
383
  block_filtered = self.latin_extended_regex.findall(block)
385
384
  else:
386
385
  block_filtered = self.latin_extended_regex.findall(block)
386
+
387
387
  if block_filtered:
388
388
  orig_text_filtered.append(''.join(block_filtered))
389
389
  else:
@@ -547,39 +547,6 @@ class ScreenshotThread(threading.Thread):
547
547
  else:
548
548
  raise ValueError('Window capture is only currently supported on Windows and macOS')
549
549
 
550
- def __del__(self):
551
- if self.macos_window_tracker_instance:
552
- self.macos_window_tracker_instance.join()
553
- elif self.windows_window_tracker_instance:
554
- self.windows_window_tracker_instance.join()
555
-
556
- def setup_persistent_windows_window_tracker(self):
557
- global window_open
558
- window_open = False
559
- def setup_tracker():
560
- global window_open
561
- self.window_handle, window_title = self.get_windows_window_handle(self.screen_capture_window)
562
-
563
- if not self.window_handle:
564
- # print(f"Window '{screen_capture_window}' not found.")
565
- return
566
-
567
- set_dpi_awareness()
568
- window_open = True
569
- self.windows_window_tracker_instance = threading.Thread(target=self.windows_window_tracker)
570
- self.windows_window_tracker_instance.start()
571
- logger.opt(ansi=True).info(f'Selected window: {window_title}')
572
-
573
- while not terminated:
574
- if not window_open:
575
- try:
576
- setup_tracker()
577
- except ValueError as e:
578
- logger.error(f"Error setting up persistent windows window tracker: {e}")
579
- break
580
- time.sleep(5)
581
-
582
-
583
550
  def get_windows_window_handle(self, window_title):
584
551
  def callback(hwnd, window_title_part):
585
552
  window_title = win32gui.GetWindowText(hwnd)
@@ -602,7 +569,7 @@ class ScreenshotThread(threading.Thread):
602
569
 
603
570
  def windows_window_tracker(self):
604
571
  found = True
605
- while not terminated or window_open:
572
+ while not terminated:
606
573
  found = win32gui.IsWindow(self.window_handle)
607
574
  if not found:
608
575
  break
@@ -864,7 +831,7 @@ class OBSScreenshotThread(threading.Thread):
864
831
  self.width = width
865
832
  self.height = height
866
833
  self.use_periodic_queue = not screen_capture_on_combo
867
-
834
+
868
835
  def write_result(self, result):
869
836
  if self.use_periodic_queue:
870
837
  periodic_screenshot_queue.put(result)
@@ -872,32 +839,66 @@ class OBSScreenshotThread(threading.Thread):
872
839
  image_queue.put((result, True))
873
840
 
874
841
  def connect_obs(self):
875
- try:
876
- import obsws_python as obs
877
- self.obs_client = obs.ReqClient(
878
- host=get_config().obs.host,
879
- port=get_config().obs.port,
880
- password=get_config().obs.password,
881
- timeout=10
882
- )
883
- logger.info("Connected to OBS WebSocket.")
884
- except Exception as e:
885
- logger.error(f"Failed to connect to OBS: {e}")
886
- self.obs_client = None
842
+ import GameSentenceMiner.obs as obs
843
+ obs.connect_to_obs_sync()
844
+
845
+ def scale_down_width_height(self, width, height):
846
+ if width == 0 or height == 0:
847
+ return self.width, self.height
848
+ aspect_ratio = width / height
849
+ logger.info(f"Scaling down OBS source dimensions: {width}x{height} (Aspect Ratio: {aspect_ratio})")
850
+ if aspect_ratio > 2.66:
851
+ # Ultra-wide (32:9) - use 1920x540
852
+ logger.info("Using ultra-wide aspect ratio scaling (32:9).")
853
+ return 1920, 540
854
+ elif aspect_ratio > 2.33:
855
+ # 21:9 - use 1920x800
856
+ logger.info("Using ultra-wide aspect ratio scaling (21:9).")
857
+ return 1920, 800
858
+ elif aspect_ratio > 1.77:
859
+ # 16:9 - use 1280x720
860
+ logger.info("Using standard aspect ratio scaling (16:9).")
861
+ return 1280, 720
862
+ elif aspect_ratio > 1.6:
863
+ # 16:10 - use 1280x800
864
+ logger.info("Using standard aspect ratio scaling (16:10).")
865
+ return 1280, 800
866
+ elif aspect_ratio > 1.33:
867
+ # 4:3 - use 960x720
868
+ logger.info("Using standard aspect ratio scaling (4:3).")
869
+ return 960, 720
870
+ elif aspect_ratio > 1.25:
871
+ # 5:4 - use 900x720
872
+ logger.info("Using standard aspect ratio scaling (5:4).")
873
+ return 900, 720
874
+ elif aspect_ratio > 1.5:
875
+ # 3:2 - use 1080x720
876
+ logger.info("Using standard aspect ratio scaling (3:2).")
877
+ return 1080, 720
878
+ else:
879
+ # Default/fallback - use 1280x720
880
+ logger.info("Using default aspect ratio scaling (1280x720).")
881
+ return 1280, 720
887
882
 
888
883
  def run(self):
889
884
  global last_image
890
- import base64
891
- import io
892
885
  from PIL import Image
893
886
  import GameSentenceMiner.obs as obs
894
887
 
895
888
  def init_config(source=None, scene=None):
896
889
  obs.update_current_game()
897
890
  self.current_source = source if source else obs.get_active_source()
898
- self.current_source_name = self.current_source.get('sourceName') if isinstance(self.current_source, dict) else None
891
+ self.source_width = self.current_source.get("sceneItemTransform").get("sourceWidth") or self.width
892
+ self.source_height = self.current_source.get("sceneItemTransform").get("sourceHeight") or self.height
893
+ if self.source_width and self.source_height:
894
+ self.width, self.height = self.scale_down_width_height(self.source_width, self.source_height)
895
+ logger.info(f"Using OBS source dimensions: {self.width}x{self.height}")
896
+ self.current_source_name = self.current_source.get("sourceName") or None
899
897
  self.current_scene = scene if scene else obs.get_current_game()
900
898
  self.ocr_config = get_scene_ocr_config()
899
+ if not self.ocr_config:
900
+ logger.error("No OCR config found for the current scene.")
901
+ return
901
902
  self.ocr_config.scale_to_custom_size(self.width, self.height)
902
903
 
903
904
  # Register a scene switch callback in obsws
@@ -925,22 +926,23 @@ class OBSScreenshotThread(threading.Thread):
925
926
  continue
926
927
 
927
928
  if not self.ocr_config:
929
+ logger.info("No OCR config found for the current scene. Waiting for scene switch.")
928
930
  time.sleep(1)
929
931
  continue
932
+
933
+ if not self.current_source_name:
934
+ obs.update_current_game()
935
+ self.current_source = obs.get_active_source()
936
+ self.current_source_name = self.current_source.get("sourceName") or None
930
937
 
931
938
  try:
932
- response = self.obs_client.get_source_screenshot(
933
- name=self.current_source_name,
934
- img_format='png',
935
- quality=75,
936
- width=self.width,
937
- height=self.height,
938
- )
939
+ if not self.current_source_name:
940
+ logger.error("No active source found in the current scene.")
941
+ time.sleep(1)
942
+ continue
943
+ img = obs.get_screenshot_PIL(source_name=self.current_source_name, width=self.width, height=self.height, img_format='png', compression=80)
939
944
 
940
- if response.image_data:
941
- image_data = base64.b64decode(response.image_data.split(",")[1])
942
- img = Image.open(io.BytesIO(image_data)).convert("RGBA")
943
-
945
+ if img is not None:
944
946
  if not img.getbbox():
945
947
  logger.info("OBS Not Capturing anything, sleeping.")
946
948
  time.sleep(1)
@@ -1118,11 +1120,10 @@ def signal_handler(sig, frame):
1118
1120
 
1119
1121
 
1120
1122
  def on_window_closed(alive):
1121
- global terminated, window_open
1123
+ global terminated
1122
1124
  if not (alive or terminated):
1123
1125
  logger.info('Window closed or error occurred, terminated!')
1124
- window_open = False
1125
- # terminated = True
1126
+ terminated = True
1126
1127
 
1127
1128
 
1128
1129
  def on_screenshot_combo():
@@ -1464,8 +1465,12 @@ def run(read_from=None,
1464
1465
  read_from_readable.append(f'directory {read_from_path}')
1465
1466
 
1466
1467
  if len(key_combos) > 0:
1467
- key_combo_listener = keyboard.GlobalHotKeys(key_combos)
1468
- key_combo_listener.start()
1468
+ try:
1469
+ from pynput import keyboard
1470
+ key_combo_listener = keyboard.GlobalHotKeys(key_combos)
1471
+ key_combo_listener.start()
1472
+ except ImportError:
1473
+ pass
1469
1474
 
1470
1475
  if write_to in ('clipboard', 'websocket', 'callback'):
1471
1476
  write_to_readable = write_to
@@ -1513,6 +1518,7 @@ def run(read_from=None,
1513
1518
  filter_img = True
1514
1519
  notify = False
1515
1520
  last_screenshot_time = time.time()
1521
+ ocr_start_time = datetime.now()
1516
1522
 
1517
1523
  if img == 0:
1518
1524
  on_window_closed(False)
@@ -168,8 +168,8 @@ def extract_text_with_pixel_boxes(
168
168
 
169
169
 
170
170
  for word in line.get("words", []):
171
- if not regex.search(word.get("plain_text", "")):
172
- continue
171
+ # if not regex.search(word.get("plain_text", "")):
172
+ # continue
173
173
  word_text = word.get("plain_text", "")
174
174
  line_text_parts.append(word_text)
175
175
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: GameSentenceMiner
3
- Version: 2.13.0
3
+ Version: 2.13.2
4
4
  Summary: A tool for mining sentences from games. Update: Overlay?
5
5
  Author-email: Beangate <bpwhelan95@gmail.com>
6
6
  License: MIT License
@@ -3,7 +3,7 @@ GameSentenceMiner/anki.py,sha256=FUwcWO0-arzfQjejQmDKP7pNNakhboo8InQ4s_jv6AY,190
3
3
  GameSentenceMiner/config_gui.py,sha256=x8H3HXoRlnfgiFczAoCe1wiCoQDP8MWV0v7am36q3Co,126479
4
4
  GameSentenceMiner/gametext.py,sha256=qR32LhXAo1_a4r01zd7Pm2Yj4ByYCw58u78JdFkSxh4,10939
5
5
  GameSentenceMiner/gsm.py,sha256=fG_3z-l6ADtx8Au2b6u514_kCWPdwYE03_U7IVLiE3Y,26649
6
- GameSentenceMiner/obs.py,sha256=hpFa33TSQnbOpzfucgnxp6vKqQ9AaQyLWQsdbuNYy1M,18741
6
+ GameSentenceMiner/obs.py,sha256=alh8G-0vEWxV46WqgVsgNU5_PC5JNzyXJdmVetjiGRo,18819
7
7
  GameSentenceMiner/vad.py,sha256=-Q1KtDJnT8zRFeEc4LLyAECf07YOUM15UDRrnWkuDgo,18817
8
8
  GameSentenceMiner/ai/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  GameSentenceMiner/ai/ai_prompting.py,sha256=iHkEx2pQJ-tEyejOgYy4G0DcZc8qvBugVL6-CQpPSME,26089
@@ -15,18 +15,21 @@ GameSentenceMiner/assets/icon32.png,sha256=Kww0hU_qke9_22wBuO_Nq0Dv2SfnOLwMhCyGg
15
15
  GameSentenceMiner/assets/icon512.png,sha256=HxUj2GHjyQsk8NV433256UxU9phPhtjCY-YB_7W4sqs,192487
16
16
  GameSentenceMiner/assets/icon64.png,sha256=N8xgdZXvhqVQP9QUK3wX5iqxX9LxHljD7c-Bmgim6tM,9301
17
17
  GameSentenceMiner/assets/pickaxe.png,sha256=VfIGyXyIZdzEnVcc4PmG3wszPMO1W4KCT7Q_nFK6eSE,1403829
18
+ GameSentenceMiner/locales/en_us.json,sha256=zv7qfr23G-os29yXfIE61_tYsTOwUjxF8ADH2YyJ0NA,24881
19
+ GameSentenceMiner/locales/ja_jp.json,sha256=PgAkkN7qmbtuRj5a3jHd9R9FNztamhmhRZysY6TwETU,26283
20
+ GameSentenceMiner/locales/zh_cn.json,sha256=h-YRSz2XN_TkymjkAH1MQ9KqGLE9_7Ru-N4yTqpm8_8,23615
18
21
  GameSentenceMiner/ocr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
22
  GameSentenceMiner/ocr/gsm_ocr_config.py,sha256=Ezj-0k6Wo-una91FvYhMp6KGkRhWYihXzLAoh_Wu2xY,5329
20
23
  GameSentenceMiner/ocr/ocrconfig.py,sha256=_tY8mjnzHMJrLS8E5pHqYXZjMuLoGKYgJwdhYgN-ny4,6466
21
- GameSentenceMiner/ocr/owocr_area_selector.py,sha256=seTO8kUCTW445qAUo4c7mvLtiv1SWeElpSUpP9DPDOA,26331
24
+ GameSentenceMiner/ocr/owocr_area_selector.py,sha256=BgLsUTWIWXTiwApuj5BZtNu1_wpVdODOIy5GAw3G6jg,27223
22
25
  GameSentenceMiner/ocr/owocr_helper.py,sha256=nyNCt6TtOFvcXddwaNXpkuYbCsfBG5Nvp6b8mU-6jlg,25236
23
26
  GameSentenceMiner/ocr/ss_picker.py,sha256=0IhxUdaKruFpZyBL-8SpxWg7bPrlGpy3lhTcMMZ5rwo,5224
24
27
  GameSentenceMiner/owocr/owocr/__init__.py,sha256=87hfN5u_PbL_onLfMACbc0F5j4KyIK9lKnRCj6oZgR0,49
25
28
  GameSentenceMiner/owocr/owocr/__main__.py,sha256=XQaqZY99EKoCpU-gWQjNbTs7Kg17HvBVE7JY8LqIE0o,157
26
29
  GameSentenceMiner/owocr/owocr/config.py,sha256=qM7kISHdUhuygGXOxmgU6Ef2nwBShrZtdqu4InDCViE,8103
27
30
  GameSentenceMiner/owocr/owocr/lens_betterproto.py,sha256=oNoISsPilVVRBBPVDtb4-roJtAhp8ZAuFTci3TGXtMc,39141
28
- GameSentenceMiner/owocr/owocr/ocr.py,sha256=6ArGr0xd-Fhkw9uPn4MH3urxbLBwZ-UmxfwoKUUgxio,63459
29
- GameSentenceMiner/owocr/owocr/run.py,sha256=nkDpXICJCTKgJTS4MYRnaz-GYqAS-GskcSg1ZkGIRuE,67285
31
+ GameSentenceMiner/owocr/owocr/ocr.py,sha256=Vi3s4WLEY_wxQSH7sE19_PXUM2BU_lv-OE7YmtLaBRQ,62042
32
+ GameSentenceMiner/owocr/owocr/run.py,sha256=We3832iAXXSoJnjlTrI72jhUuMoxRQ_lbaz4TTjtyBc,68132
30
33
  GameSentenceMiner/owocr/owocr/screen_coordinate_picker.py,sha256=Na6XStbQBtpQUSdbN3QhEswtKuU1JjReFk_K8t5ezQE,3395
31
34
  GameSentenceMiner/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
35
  GameSentenceMiner/util/audio_offset_selector.py,sha256=8Stk3BP-XVIuzRv9nl9Eqd2D-1yD3JrgU-CamBywJmY,8542
@@ -63,10 +66,10 @@ GameSentenceMiner/web/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm
63
66
  GameSentenceMiner/web/templates/index.html,sha256=Gv3CJvNnhAzIVV_QxhNq4OD-pXDt1vKCu9k6WdHSXuA,215343
64
67
  GameSentenceMiner/web/templates/text_replacements.html,sha256=tV5c8mCaWSt_vKuUpbdbLAzXZ3ATZeDvQ9PnnAfqY0M,8598
65
68
  GameSentenceMiner/web/templates/utility.html,sha256=3flZinKNqUJ7pvrZk6xu__v67z44rXnaK7UTZ303R-8,16946
66
- GameSentenceMiner/wip/get_overlay_coords.py,sha256=pxTuOicSsMMmOLRQH0-3FPoQqsolbncvIMgX2q8ArHc,19787
67
- gamesentenceminer-2.13.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
68
- gamesentenceminer-2.13.0.dist-info/METADATA,sha256=vstCSpe07K_nuP8m0Ur3Zn4Dbfgk8ttM2xxjsTtmVd4,1463
69
- gamesentenceminer-2.13.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
70
- gamesentenceminer-2.13.0.dist-info/entry_points.txt,sha256=2APEP25DbfjSxGeHtwBstMH8mulVhLkqF_b9bqzU6vQ,65
71
- gamesentenceminer-2.13.0.dist-info/top_level.txt,sha256=V1hUY6xVSyUEohb0uDoN4UIE6rUZ_JYx8yMyPGX4PgQ,18
72
- gamesentenceminer-2.13.0.dist-info/RECORD,,
69
+ GameSentenceMiner/wip/get_overlay_coords.py,sha256=nJRytHJwUBToXeAIkf45HP7Yv42YO-ILbP5h8GVeE2Q,19791
70
+ gamesentenceminer-2.13.2.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
71
+ gamesentenceminer-2.13.2.dist-info/METADATA,sha256=-Po12aXrmiAHnlwBIjjwRVzClV-FxfyTY-V7ZLCGzqs,1463
72
+ gamesentenceminer-2.13.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
73
+ gamesentenceminer-2.13.2.dist-info/entry_points.txt,sha256=2APEP25DbfjSxGeHtwBstMH8mulVhLkqF_b9bqzU6vQ,65
74
+ gamesentenceminer-2.13.2.dist-info/top_level.txt,sha256=V1hUY6xVSyUEohb0uDoN4UIE6rUZ_JYx8yMyPGX4PgQ,18
75
+ gamesentenceminer-2.13.2.dist-info/RECORD,,