GameSentenceMiner 2.18.9__tar.gz → 2.18.11__tar.gz

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.
Files changed (139) hide show
  1. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/owocr/owocr/ocr.py +44 -15
  2. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/tools/furigana_filter_preview.py +101 -21
  3. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/ui/config_gui.py +53 -1
  4. gamesentenceminer-2.18.11/GameSentenceMiner/ui/furigana_filter_preview.py +410 -0
  5. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/util/configuration.py +16 -3
  6. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/util/get_overlay_coords.py +12 -5
  7. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/texthooking_page.py +3 -0
  8. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner.egg-info/PKG-INFO +1 -1
  9. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner.egg-info/SOURCES.txt +1 -0
  10. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/PKG-INFO +1 -1
  11. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/pyproject.toml +1 -1
  12. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/__init__.py +0 -0
  13. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/ai/__init__.py +0 -0
  14. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/ai/ai_prompting.py +0 -0
  15. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/anki.py +0 -0
  16. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/assets/__init__.py +0 -0
  17. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/assets/icon.png +0 -0
  18. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/assets/icon128.png +0 -0
  19. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/assets/icon256.png +0 -0
  20. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/assets/icon32.png +0 -0
  21. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/assets/icon512.png +0 -0
  22. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/assets/icon64.png +0 -0
  23. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/assets/pickaxe.png +0 -0
  24. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/gametext.py +0 -0
  25. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/gsm.py +0 -0
  26. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/locales/en_us.json +0 -0
  27. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/locales/ja_jp.json +0 -0
  28. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/locales/zh_cn.json +0 -0
  29. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/obs.py +0 -0
  30. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/ocr/__init__.py +0 -0
  31. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/ocr/gsm_ocr_config.py +0 -0
  32. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/ocr/ocrconfig.py +0 -0
  33. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/ocr/owocr_area_selector.py +0 -0
  34. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/ocr/owocr_helper.py +0 -0
  35. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/ocr/ss_picker.py +0 -0
  36. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/owocr/owocr/__init__.py +0 -0
  37. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/owocr/owocr/__main__.py +0 -0
  38. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/owocr/owocr/config.py +0 -0
  39. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/owocr/owocr/lens_betterproto.py +0 -0
  40. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/owocr/owocr/run.py +0 -0
  41. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/owocr/owocr/screen_coordinate_picker.py +0 -0
  42. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/tools/__init__.py +0 -0
  43. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/tools/audio_offset_selector.py +0 -0
  44. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/tools/ss_selector.py +0 -0
  45. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/tools/window_transparency.py +0 -0
  46. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/ui/__init__.py +0 -0
  47. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/ui/anki_confirmation.py +0 -0
  48. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/ui/screenshot_selector.py +0 -0
  49. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/util/__init__.py +0 -0
  50. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/util/audio_player.py +0 -0
  51. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/util/communication/__init__.py +0 -0
  52. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/util/communication/send.py +0 -0
  53. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/util/communication/websocket.py +0 -0
  54. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/util/db.py +0 -0
  55. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/util/downloader/Untitled_json.py +0 -0
  56. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/util/downloader/__init__.py +0 -0
  57. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/util/downloader/download_tools.py +0 -0
  58. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/util/downloader/oneocr_dl.py +0 -0
  59. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/util/electron_config.py +0 -0
  60. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/util/ffmpeg.py +0 -0
  61. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/util/gsm_utils.py +0 -0
  62. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/util/model.py +0 -0
  63. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/util/notification.py +0 -0
  64. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/util/text_log.py +0 -0
  65. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/util/win10toast/__init__.py +0 -0
  66. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/util/win10toast/__main__.py +0 -0
  67. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/vad.py +0 -0
  68. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/__init__.py +0 -0
  69. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/database_api.py +0 -0
  70. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/events.py +0 -0
  71. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/gsm_websocket.py +0 -0
  72. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/service.py +0 -0
  73. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/__init__.py +0 -0
  74. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/apple-touch-icon.png +0 -0
  75. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/css/dashboard-shared.css +0 -0
  76. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/css/kanji-grid.css +0 -0
  77. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/css/overview.css +0 -0
  78. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/css/popups-shared.css +0 -0
  79. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/css/search.css +0 -0
  80. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/css/shared.css +0 -0
  81. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/css/stats.css +0 -0
  82. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/favicon-96x96.png +0 -0
  83. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/favicon.ico +0 -0
  84. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/favicon.svg +0 -0
  85. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/js/anki_stats.js +0 -0
  86. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/js/database.js +0 -0
  87. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/js/goals.js +0 -0
  88. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/js/kanji-grid.js +0 -0
  89. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/js/overview.js +0 -0
  90. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/js/search.js +0 -0
  91. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/js/shared.js +0 -0
  92. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/js/stats.js +0 -0
  93. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/site.webmanifest +0 -0
  94. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/style.css +0 -0
  95. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/web-app-manifest-192x192.png +0 -0
  96. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/static/web-app-manifest-512x512.png +0 -0
  97. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/stats.py +0 -0
  98. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/anki_stats.html +0 -0
  99. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/basic_kanji_book_bkb_v1_v2.json +0 -0
  100. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/duolingo_kanji.json +0 -0
  101. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/grade.json +0 -0
  102. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/hk_primary_learning.json +0 -0
  103. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/hkscs2016.json +0 -0
  104. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/hsk_levels.json +0 -0
  105. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/humanum_frequency_list.json +0 -0
  106. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/jis_levels.json +0 -0
  107. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/jlpt_level.json +0 -0
  108. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/jpdb_kanji_frequency_list.json +0 -0
  109. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/jpdbv2_kanji_frequency_list.json +0 -0
  110. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/jun_das_modern_chinese_character_frequency_list.json +0 -0
  111. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/kanji_in_context_revised_edition.json +0 -0
  112. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/kanji_kentei_level.json +0 -0
  113. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/mainland_china_elementary_textbook_characters.json +0 -0
  114. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/moe_way_quiz.json +0 -0
  115. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/official_kanji.json +0 -0
  116. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/remembering_the_kanji.json +0 -0
  117. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/standard_form_of_national_characters.json +0 -0
  118. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/table_of_general_standard_chinese_characters.json +0 -0
  119. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/the_kodansha_kanji_learners_course_klc.json +0 -0
  120. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/thousand_character_classic.json +0 -0
  121. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/wanikani_levels.json +0 -0
  122. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/kanji_grid/words_hk_frequency_list.json +0 -0
  123. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/navigation.html +0 -0
  124. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/components/theme-styles.html +0 -0
  125. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/database.html +0 -0
  126. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/goals.html +0 -0
  127. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/index.html +0 -0
  128. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/overview.html +0 -0
  129. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/search.html +0 -0
  130. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/stats.html +0 -0
  131. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/web/templates/utility.html +0 -0
  132. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner/wip/__init___.py +0 -0
  133. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner.egg-info/dependency_links.txt +0 -0
  134. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner.egg-info/entry_points.txt +0 -0
  135. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner.egg-info/requires.txt +0 -0
  136. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/GameSentenceMiner.egg-info/top_level.txt +0 -0
  137. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/LICENSE +0 -0
  138. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/README.md +0 -0
  139. {gamesentenceminer-2.18.9 → gamesentenceminer-2.18.11}/setup.cfg +0 -0
@@ -277,11 +277,12 @@ class GoogleLens:
277
277
  key = 'l'
278
278
  available = False
279
279
 
280
- def __init__(self, lang='ja'):
280
+ def __init__(self, lang='ja', get_furigana_sens_from_file=True):
281
281
  import regex
282
282
  self.regex = get_regex(lang)
283
283
  self.initial_lang = lang
284
284
  self.punctuation_regex = regex.compile(r'[\p{P}\p{S}]')
285
+ self.get_furigana_sens_from_file = get_furigana_sens_from_file
285
286
  if 'betterproto' not in sys.modules:
286
287
  logger.warning('betterproto not available, Google Lens will not work!')
287
288
  else:
@@ -289,10 +290,10 @@ class GoogleLens:
289
290
  logger.info('Google Lens ready')
290
291
 
291
292
  def __call__(self, img, furigana_filter_sensitivity=0, return_coords=False):
292
- if furigana_filter_sensitivity != None:
293
+ if self.get_furigana_sens_from_file:
293
294
  furigana_filter_sensitivity = get_furigana_filter_sensitivity()
294
295
  else:
295
- furigana_filter_sensitivity = 0
296
+ furigana_filter_sensitivity = furigana_filter_sensitivity
296
297
  lang = get_ocr_language()
297
298
  img, is_path = input_to_pil_image(img)
298
299
  if lang != self.initial_lang:
@@ -362,6 +363,12 @@ class GoogleLens:
362
363
  text = response_dict['objects_response']['text']
363
364
  skipped = []
364
365
  previous_line = None
366
+ filtered_response_dict = response_dict
367
+ if furigana_filter_sensitivity:
368
+ import copy
369
+ filtered_response_dict = copy.deepcopy(response_dict)
370
+ filtered_paragraphs = []
371
+
365
372
  if 'text_layout' in text:
366
373
  for paragraph in text['text_layout']['paragraphs']:
367
374
  if previous_line:
@@ -376,25 +383,40 @@ class GoogleLens:
376
383
  # logger.info(avg_height * 2)
377
384
  if vertical_space > avg_height * 2:
378
385
  res += 'BLANK_LINE\n'
386
+ passed_furigana_filter_lines = []
379
387
  for line in paragraph['lines']:
380
388
  if furigana_filter_sensitivity:
381
389
  line_width = line['geometry']['bounding_box']['width'] * img.width
382
390
  line_height = line['geometry']['bounding_box']['height'] * img.height
391
+ passes = False
383
392
  for word in line['words']:
384
393
  if self.punctuation_regex.findall(word['plain_text']):
385
394
  res += word['plain_text'] + word['text_separator']
386
395
  continue
387
396
  if line_width > furigana_filter_sensitivity and line_height > furigana_filter_sensitivity:
388
397
  res += word['plain_text'] + word['text_separator']
398
+ passes = True
389
399
  else:
390
400
  skipped.extend(word['plain_text'])
391
401
  continue
402
+ if passes:
403
+ passed_furigana_filter_lines.append(line)
392
404
  else:
393
405
  for word in line['words']:
394
406
  res += word['plain_text'] + word['text_separator']
395
407
  res += '\n'
396
408
 
409
+ if furigana_filter_sensitivity and passed_furigana_filter_lines:
410
+ # Create a filtered paragraph with only the passing lines
411
+ filtered_paragraph = paragraph.copy()
412
+ filtered_paragraph['lines'] = passed_furigana_filter_lines
413
+ filtered_paragraphs.append(filtered_paragraph)
414
+
397
415
  previous_line = paragraph
416
+
417
+ if furigana_filter_sensitivity:
418
+ filtered_response_dict['objects_response']['text']['text_layout']['paragraphs'] = filtered_paragraphs
419
+
398
420
  res += '\n'
399
421
  # logger.info(
400
422
  # f"Skipped {len(skipped)} chars due to furigana filter sensitivity: {furigana_filter_sensitivity}")
@@ -438,7 +460,7 @@ class GoogleLens:
438
460
  # res += '\n'
439
461
 
440
462
  if return_coords:
441
- x = (True, res, response_dict)
463
+ x = (True, res, filtered_response_dict)
442
464
  else:
443
465
  x = (True, res)
444
466
 
@@ -869,11 +891,12 @@ class OneOCR:
869
891
  key = 'z'
870
892
  available = False
871
893
 
872
- def __init__(self, config={}, lang='ja'):
894
+ def __init__(self, config={}, lang='ja', get_furigana_sens_from_file=True):
873
895
  import regex
874
896
  self.initial_lang = lang
875
897
  self.regex = get_regex(lang)
876
898
  self.punctuation_regex = regex.compile(r'[\p{P}\p{S}]')
899
+ self.get_furigana_sens_from_file = get_furigana_sens_from_file
877
900
  if sys.platform == 'win32':
878
901
  if int(platform.release()) < 10:
879
902
  logger.warning('OneOCR is not supported on Windows older than 10!')
@@ -921,10 +944,10 @@ class OneOCR:
921
944
 
922
945
  def __call__(self, img, furigana_filter_sensitivity=0, return_coords=False, multiple_crop_coords=False, return_one_box=True, return_dict=False):
923
946
  lang = get_ocr_language()
924
- if furigana_filter_sensitivity != None:
947
+ if self.get_furigana_sens_from_file:
925
948
  furigana_filter_sensitivity = get_furigana_filter_sensitivity()
926
949
  else:
927
- furigana_filter_sensitivity = 0
950
+ furigana_filter_sensitivity = furigana_filter_sensitivity
928
951
  if lang != self.initial_lang:
929
952
  self.initial_lang = lang
930
953
  self.regex = get_regex(lang)
@@ -958,6 +981,7 @@ class OneOCR:
958
981
  skipped = []
959
982
  boxes = []
960
983
  if furigana_filter_sensitivity > 0:
984
+ passing_lines = []
961
985
  for line in filtered_lines:
962
986
  line_x1, line_x2, line_x3, line_x4 = line['bounding_rect']['x1'], line['bounding_rect']['x2'], \
963
987
  line['bounding_rect']['x3'], line['bounding_rect']['x4']
@@ -965,16 +989,20 @@ class OneOCR:
965
989
  line['bounding_rect']['y3'], line['bounding_rect']['y4']
966
990
  line_width = max(line_x2 - line_x1, line_x3 - line_x4)
967
991
  line_height = max(line_y3 - line_y1, line_y4 - line_y2)
968
- for char in line['words']:
969
- if self.punctuation_regex.findall(char['text']):
992
+
993
+ # Check if the line passes the size filter
994
+ if line_width > furigana_filter_sensitivity and line_height > furigana_filter_sensitivity:
995
+ # Line passes - include all its text and add to passing_lines
996
+ for char in line['words']:
970
997
  res += char['text']
971
- continue
972
- if line_width > furigana_filter_sensitivity and line_height > furigana_filter_sensitivity:
973
- res += char['text']
974
- else:
998
+ passing_lines.append(line)
999
+ else:
1000
+ # Line fails - only include punctuation, skip the rest
1001
+ for char in line['words']:
975
1002
  skipped.extend(char for char in line['text'])
976
- continue
977
1003
  res += '\n'
1004
+ filtered_lines = passing_lines
1005
+ return_resp = {'text': res, 'text_angle': ocr_resp['text_angle'], 'lines': passing_lines}
978
1006
  # logger.info(
979
1007
  # f"Skipped {len(skipped)} chars due to furigana filter sensitivity: {furigana_filter_sensitivity}")
980
1008
  # widths, heights = [], []
@@ -1012,6 +1040,7 @@ class OneOCR:
1012
1040
  # res += '\n'
1013
1041
  else:
1014
1042
  res = ocr_resp['text']
1043
+ return_resp = ocr_resp
1015
1044
 
1016
1045
  if multiple_crop_coords:
1017
1046
  for line in filtered_lines:
@@ -1042,7 +1071,7 @@ class OneOCR:
1042
1071
  if return_one_box:
1043
1072
  x.append(crop_coords)
1044
1073
  if return_dict:
1045
- x.append(ocr_resp)
1074
+ x.append(return_resp)
1046
1075
  if is_path:
1047
1076
  img.close()
1048
1077
  return x
@@ -6,9 +6,42 @@ import threading
6
6
  import regex
7
7
 
8
8
  from GameSentenceMiner import obs
9
- from GameSentenceMiner.util.configuration import logger
9
+ from GameSentenceMiner.util.configuration import logger, get_overlay_config
10
10
  from GameSentenceMiner.owocr.owocr.ocr import GoogleLens, OneOCR
11
11
 
12
+ def get_overlay_screenshot() -> Image.Image:
13
+ """
14
+ Captures a screenshot from the configured overlay monitor using mss.
15
+
16
+ Returns:
17
+ A PIL Image object of the screenshot from the overlay monitor.
18
+ """
19
+ try:
20
+ import mss
21
+ overlay_config = get_overlay_config()
22
+ monitor_index = overlay_config.monitor_to_capture
23
+
24
+ with mss.mss() as sct:
25
+ # mss.monitors[0] is all monitors combined, mss.monitors[1] is the first monitor
26
+ # So we need to add 1 to the monitor_index to get the correct monitor
27
+ monitor = sct.monitors[monitor_index + 1]
28
+ screenshot = sct.grab(monitor)
29
+
30
+ # Convert to PIL Image
31
+ img = Image.frombytes("RGB", screenshot.size, screenshot.bgra, "raw", "BGRX")
32
+ logger.info(f"Screenshot captured from monitor {monitor_index + 1} ({img.width}x{img.height})")
33
+ return img
34
+
35
+ except ImportError:
36
+ logger.error("mss library not found. Please install it to use overlay functionality.")
37
+ raise
38
+ except IndexError:
39
+ logger.error(f"Monitor index {monitor_index + 1} not found. Available monitors: {len(sct.monitors) - 1}")
40
+ raise
41
+ except Exception as e:
42
+ logger.error(f"Failed to capture overlay screenshot: {e}")
43
+ raise
44
+
12
45
  def get_ocr_results_from_image(image_obj: Image.Image) -> tuple:
13
46
  """
14
47
  This is the function where you will plug in your OCR logic.
@@ -34,7 +67,8 @@ class FuriganaFilterVisualizer:
34
67
  self.ocr1_result = None
35
68
  self.ocr2_result = None
36
69
  self.current_ocr = 1
37
- self.master.title("Furigana Filter Visualizer - Lens")
70
+ self.title_prefix = "Furigana Filter Visualizer"
71
+ self.master.title(f"{self.title_prefix} - Lens")
38
72
 
39
73
  self.words_data = []
40
74
  self.lines_data = []
@@ -84,6 +118,12 @@ class FuriganaFilterVisualizer:
84
118
 
85
119
  self.punctuation_regex = regex.compile(r'[\p{P}\p{S}]')
86
120
  self.master.protocol("WM_DELETE_WINDOW", self.on_ok)
121
+
122
+ def set_title_prefix(self, prefix: str):
123
+ """Set the title prefix and update the current title."""
124
+ self.title_prefix = prefix
125
+ ocr_name = "Lens" if self.current_ocr == 1 else "OneOCR"
126
+ self.master.title(f"{self.title_prefix} - {ocr_name}")
87
127
 
88
128
  def update_with_ocr_data(self, ocr1_result, ocr2_result):
89
129
  """Called by the background thread to populate the GUI with OCR data."""
@@ -123,10 +163,10 @@ class FuriganaFilterVisualizer:
123
163
  # Change to oneocr or lens, in title too
124
164
  if self.current_ocr == 1:
125
165
  self.swap_button.config(text="Switch to OneOCR")
126
- self.master.title("Furigana Filter Visualizer - Lens")
166
+ self.master.title(f"{self.title_prefix} - Lens")
127
167
  else:
128
168
  self.swap_button.config(text="Switch to Lens")
129
- self.master.title("Furigana Filter Visualizer - OneOCR")
169
+ self.master.title(f"{self.title_prefix} - OneOCR")
130
170
  self.pre_process_word_geometries()
131
171
  self.update_filter_visualization(self.slider.get())
132
172
 
@@ -243,17 +283,22 @@ class FuriganaFilterVisualizer:
243
283
  for words that pass the sensitivity filter.
244
284
  """
245
285
  sensitivity = float(slider_value)
246
- self.slider_value_label.config(text=f"{sensitivity:.0f} px")
286
+ # Only update the label if it exists (GUI is fully initialized)
287
+ if hasattr(self, 'slider_value_label'):
288
+ self.slider_value_label.config(text=f"{sensitivity:.0f} px")
247
289
 
248
290
  for rect_id in self.drawn_rects:
249
291
  self.canvas.delete(rect_id)
250
292
  self.drawn_rects.clear()
251
293
 
294
+ # Set color based on current OCR: green for Lens (OCR 1), blue for OneOCR (OCR 2)
295
+ outline_color = 'green' if self.current_ocr == 1 else 'blue'
296
+
252
297
  for line_data in self.lines_data:
253
298
  if line_data['px_w'] > sensitivity and line_data['px_h'] > sensitivity:
254
299
  x1, y1, x2, y2 = line_data['coords']
255
300
  rect_id = self.canvas.create_rectangle(
256
- x1, y1, x2, y2, outline='blue', width=2
301
+ x1, y1, x2, y2, outline=outline_color, width=2
257
302
  )
258
303
  self.drawn_rects.append(rect_id)
259
304
 
@@ -289,29 +334,64 @@ def scale_down_width_height(width, height):
289
334
 
290
335
  def main():
291
336
  import sys
292
- current_furigana_sensitivity = int(sys.argv[1]) if len(sys.argv) > 1 else 0
337
+
338
+ # Parse command line arguments
339
+ current_furigana_sensitivity = 0
340
+ use_overlay = False
341
+
342
+ if len(sys.argv) > 1:
343
+ # Check if any argument is "overlay" or "--overlay"
344
+ args = sys.argv[1:]
345
+ if "overlay" in args or "--overlay" in args:
346
+ use_overlay = True
347
+ # Remove overlay flags and use remaining numeric argument as sensitivity
348
+ numeric_args = [arg for arg in args if arg not in ["overlay", "--overlay"] and arg.isdigit()]
349
+ if numeric_args:
350
+ current_furigana_sensitivity = int(numeric_args[0])
351
+ else:
352
+ # Assume first argument is sensitivity
353
+ try:
354
+ current_furigana_sensitivity = int(args[0])
355
+ except ValueError:
356
+ logger.warning(f"Invalid sensitivity value: {args[0]}. Using default value 0.")
293
357
 
294
358
  """Main execution function."""
295
- try:
296
- logger.info("Connecting to OBS...")
297
- obs.connect_to_obs_sync()
298
- except Exception as e:
299
- logger.error(f"Failed to connect to OBS. Please ensure OBS is running and the WebSocket server is enabled. Error: {e}")
300
- return
301
-
302
- logger.info("Taking OBS screenshot...")
303
- screenshot_img = obs.get_screenshot_PIL(compression=90, img_format='jpg')
359
+ if use_overlay:
360
+ logger.info("Using overlay mode - capturing from configured monitor...")
361
+ try:
362
+ screenshot_img = get_overlay_screenshot()
363
+ except Exception as e:
364
+ logger.error(f"Failed to get overlay screenshot: {e}")
365
+ return
366
+ else:
367
+ try:
368
+ logger.info("Connecting to OBS...")
369
+ obs.connect_to_obs_sync()
370
+ except Exception as e:
371
+ logger.error(f"Failed to connect to OBS. Please ensure OBS is running and the WebSocket server is enabled. Error: {e}")
372
+ return
304
373
 
305
- screenshot_img = screenshot_img.resize(scale_down_width_height(screenshot_img.width, screenshot_img.height), Image.LANCZOS)
374
+ logger.info("Taking OBS screenshot...")
375
+ screenshot_img = obs.get_screenshot_PIL(compression=90, img_format='jpg')
306
376
 
307
- if not screenshot_img:
308
- logger.error("Failed to get screenshot from OBS.")
309
- return
377
+ if not screenshot_img:
378
+ logger.error("Failed to get screenshot from OBS.")
379
+ return
310
380
 
311
- logger.info(f"Screenshot received ({screenshot_img.width}x{screenshot_img.height}).")
381
+ # Scale down the image for performance
382
+ screenshot_img = screenshot_img.resize(scale_down_width_height(screenshot_img.width, screenshot_img.height), Image.LANCZOS)
383
+
384
+ source_type = "overlay monitor" if use_overlay else "OBS"
385
+ logger.info(f"Screenshot received from {source_type} ({screenshot_img.width}x{screenshot_img.height}).")
312
386
 
313
387
  root = tk.Tk()
314
388
  app = FuriganaFilterVisualizer(root, screenshot_img, current_furigana_sensitivity)
389
+
390
+ # Update window title to reflect source
391
+ if use_overlay:
392
+ overlay_config = get_overlay_config()
393
+ monitor_num = overlay_config.monitor_to_capture + 1
394
+ app.set_title_prefix(f"Furigana Filter Visualizer - Overlay Monitor {monitor_num}")
315
395
 
316
396
  def ocr_worker():
317
397
  logger.info("Starting OCR process in background thread...")
@@ -5,6 +5,7 @@ import os
5
5
  import subprocess
6
6
  import sys
7
7
  import time
8
+ import re
8
9
  import tkinter as tk
9
10
  from tkinter import filedialog, messagebox, simpledialog, scrolledtext, font
10
11
  from PIL import Image, ImageTk
@@ -318,7 +319,39 @@ class ConfigApp:
318
319
 
319
320
  print(dialog.selected_path)
320
321
  return dialog.selected_path
321
-
322
+
323
+
324
+ # IMPLEMENT LATER,FOR NOW JUST RUN THE FILE
325
+ # def show_furigana_filter_selector(self, current_sensitivity):
326
+ # """
327
+ # Displays a modal dialog for the user to select the furigana filter sensitivity.
328
+
329
+ # Args:
330
+ # current_sensitivity (int): The current sensitivity setting.
331
+ # Returns: int: The selected sensitivity setting, or None if canceled.
332
+ # """
333
+ # dialog = FuriganaFilterSelectorDialog(self.window,
334
+ # self,
335
+ # current_sensitivity=current_sensitivity)
336
+ # return dialog.selected_sensitivity
337
+
338
+ def show_minimum_character_size_selector(self, current_size):
339
+ """
340
+ Opens an external tool for selecting the minimum character size.
341
+
342
+ Args:
343
+ current_sensitivity (int): The current sensitivity setting.
344
+ Returns: int: The selected sensitivity setting, or None if canceled.
345
+ """
346
+ # Run the file directly with the current python interpreter and get stdout
347
+ result = subprocess.run([sys.executable, '-m', 'GameSentenceMiner.tools.furigana_filter_preview', str(current_size), 'overlay'], capture_output=True, text=True)
348
+ if result.returncode == 0:
349
+ # Parse the output for RESULT:[value]
350
+ match = re.search(r"RESULT:\[(\d+)\]", result.stdout)
351
+ if match:
352
+ return int(match.group(1))
353
+ return None
354
+
322
355
  def create_vars(self):
323
356
  """
324
357
  Initializes all the tkinter variables used in the configuration GUI.
@@ -462,6 +495,7 @@ class ConfigApp:
462
495
  self.periodic_value = tk.BooleanVar(value=self.settings.overlay.periodic)
463
496
  self.periodic_interval_value = tk.StringVar(value=str(self.settings.overlay.periodic_interval))
464
497
  self.scan_delay_value = tk.StringVar(value=str(self.settings.overlay.scan_delay))
498
+ self.overlay_minimum_character_size_value = tk.StringVar(value=str(self.settings.overlay.minimum_character_size))
465
499
 
466
500
  # Master Config Settings
467
501
  self.switch_to_default_if_not_found_value = tk.BooleanVar(value=self.master_config.switch_to_default_if_not_found)
@@ -703,6 +737,7 @@ class ConfigApp:
703
737
  scan_delay=float(self.scan_delay_value.get()),
704
738
  periodic=float(self.periodic_value.get()),
705
739
  periodic_interval=float(self.periodic_interval_value.get()),
740
+ minimum_character_size=int(self.overlay_minimum_character_size_value.get()),
706
741
  )
707
742
  # wip=WIP(
708
743
  # overlay_websocket_port=int(self.overlay_websocket_port_value.get()),
@@ -2387,6 +2422,19 @@ class ConfigApp:
2387
2422
  ttk.Entry(overlay_frame, textvariable=self.periodic_interval_value).grid(row=self.current_row, column=1, sticky='EW', pady=2)
2388
2423
  self.current_row += 1
2389
2424
 
2425
+ # Minimum Character Size
2426
+ minimum_character_size_i18n = overlay_i18n.get('minimum_character_size', {})
2427
+ HoverInfoLabelWidget(overlay_frame, text=minimum_character_size_i18n.get('label', 'Minimum Character Size:'),
2428
+ tooltip=minimum_character_size_i18n.get('tooltip', 'Minimum size of characters to be detected.'),
2429
+ row=self.current_row, column=0)
2430
+ ttk.Entry(overlay_frame, textvariable=self.overlay_minimum_character_size_value).grid(row=self.current_row, column=1, sticky='EW', pady=2)
2431
+ # button to open minimum character size Finder
2432
+ ttk.Button(overlay_frame, text=overlay_i18n.get('minimum_character_size_finder_button',
2433
+ 'Minimum Character Size Finder'),
2434
+ command=lambda: self.open_minimum_character_size_selector(self.overlay_minimum_character_size_value.get()), bootstyle="outline").grid(row=self.current_row, column=2, padx=5, pady=2)
2435
+
2436
+ self.current_row += 1
2437
+
2390
2438
  if self.monitors:
2391
2439
  # Ensure the index is valid
2392
2440
  monitor_index = self.settings.overlay.monitor_to_capture
@@ -2397,6 +2445,10 @@ class ConfigApp:
2397
2445
 
2398
2446
  self.add_reset_button(overlay_frame, "overlay", self.current_row, 0, self.create_overlay_tab)
2399
2447
 
2448
+ def open_minimum_character_size_selector(self, size):
2449
+ new_size = self.show_minimum_character_size_selector(size)
2450
+ self.overlay_minimum_character_size_value.set(new_size)
2451
+
2400
2452
  @new_tab
2401
2453
  def create_wip_tab(self):
2402
2454
  if self.wip_tab is None: