GameSentenceMiner 2.13.1__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.
- GameSentenceMiner/obs.py +4 -0
- GameSentenceMiner/ocr/owocr_area_selector.py +32 -5
- GameSentenceMiner/owocr/owocr/ocr.py +16 -31
- GameSentenceMiner/owocr/owocr/run.py +44 -4
- GameSentenceMiner/wip/get_overlay_coords.py +2 -2
- {gamesentenceminer-2.13.1.dist-info → gamesentenceminer-2.13.2.dist-info}/METADATA +1 -1
- {gamesentenceminer-2.13.1.dist-info → gamesentenceminer-2.13.2.dist-info}/RECORD +11 -11
- {gamesentenceminer-2.13.1.dist-info → gamesentenceminer-2.13.2.dist-info}/WHEEL +0 -0
- {gamesentenceminer-2.13.1.dist-info → gamesentenceminer-2.13.2.dist-info}/entry_points.txt +0 -0
- {gamesentenceminer-2.13.1.dist-info → gamesentenceminer-2.13.2.dist-info}/licenses/LICENSE +0 -0
- {gamesentenceminer-2.13.1.dist-info → gamesentenceminer-2.13.2.dist-info}/top_level.txt +0 -0
GameSentenceMiner/obs.py
CHANGED
@@ -468,6 +468,10 @@ if __name__ == '__main__':
|
|
468
468
|
logging.basicConfig(level=logging.INFO)
|
469
469
|
# main()
|
470
470
|
connect_to_obs_sync()
|
471
|
+
|
472
|
+
while True:
|
473
|
+
print(get_active_source())
|
474
|
+
time.sleep(3)
|
471
475
|
# i = 100
|
472
476
|
# for i in range(1, 100):
|
473
477
|
# print(f"Getting screenshot {i}")
|
@@ -55,15 +55,13 @@ class ScreenSelector:
|
|
55
55
|
|
56
56
|
if self.use_obs_screenshot:
|
57
57
|
print("Using OBS screenshot as target.")
|
58
|
-
|
58
|
+
self.screenshot_img = obs.get_screenshot_PIL(compression=75)
|
59
59
|
# print(screenshot_base64)
|
60
|
-
if not
|
60
|
+
if not self.screenshot_img:
|
61
61
|
raise RuntimeError("Failed to get OBS screenshot.")
|
62
62
|
try:
|
63
|
-
img_data = base64.b64decode(screenshot_base64)
|
64
|
-
self.screenshot_img = Image.open(io.BytesIO(img_data))
|
65
63
|
# Scale image to 1280x720
|
66
|
-
self.screenshot_img = self.screenshot_img.resize((
|
64
|
+
self.screenshot_img = self.screenshot_img.resize(self.scale_down_width_height(self.screenshot_img.width, self.screenshot_img.height), Image.LANCZOS)
|
67
65
|
except Exception as e:
|
68
66
|
raise RuntimeError(f"Failed to decode or open OBS screenshot: {e}")
|
69
67
|
|
@@ -104,6 +102,35 @@ class ScreenSelector:
|
|
104
102
|
self.instructions_window_id = None
|
105
103
|
|
106
104
|
self.load_existing_rectangles()
|
105
|
+
|
106
|
+
def scale_down_width_height(self, width, height):
|
107
|
+
if width == 0 or height == 0:
|
108
|
+
return self.width, self.height
|
109
|
+
aspect_ratio = width / height
|
110
|
+
if aspect_ratio > 2.66:
|
111
|
+
# Ultra-wide (32:9) - use 1920x540
|
112
|
+
return 1920, 540
|
113
|
+
elif aspect_ratio > 2.33:
|
114
|
+
# 21:9 - use 1920x800
|
115
|
+
return 1920, 800
|
116
|
+
elif aspect_ratio > 1.77:
|
117
|
+
# 16:9 - use 1280x720
|
118
|
+
return 1280, 720
|
119
|
+
elif aspect_ratio > 1.6:
|
120
|
+
# 16:10 - use 1280x800
|
121
|
+
return 1280, 800
|
122
|
+
elif aspect_ratio > 1.33:
|
123
|
+
# 4:3 - use 960x720
|
124
|
+
return 960, 720
|
125
|
+
elif aspect_ratio > 1.25:
|
126
|
+
# 5:4 - use 900x720
|
127
|
+
return 900, 720
|
128
|
+
elif aspect_ratio > 1.5:
|
129
|
+
# 3:2 - use 1080x720
|
130
|
+
return 1080, 720
|
131
|
+
else:
|
132
|
+
# Default/fallback - use 1280x720
|
133
|
+
return 1280, 720
|
107
134
|
|
108
135
|
def _find_target_window(self):
|
109
136
|
try:
|
@@ -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
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
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
|
393
|
-
res +=
|
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(
|
@@ -440,6 +422,9 @@ class GoogleLens:
|
|
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
|
|
@@ -831,7 +831,7 @@ class OBSScreenshotThread(threading.Thread):
|
|
831
831
|
self.width = width
|
832
832
|
self.height = height
|
833
833
|
self.use_periodic_queue = not screen_capture_on_combo
|
834
|
-
|
834
|
+
|
835
835
|
def write_result(self, result):
|
836
836
|
if self.use_periodic_queue:
|
837
837
|
periodic_screenshot_queue.put(result)
|
@@ -841,18 +841,58 @@ class OBSScreenshotThread(threading.Thread):
|
|
841
841
|
def connect_obs(self):
|
842
842
|
import GameSentenceMiner.obs as obs
|
843
843
|
obs.connect_to_obs_sync()
|
844
|
-
|
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
|
845
882
|
|
846
883
|
def run(self):
|
847
884
|
global last_image
|
848
|
-
import base64
|
849
|
-
import io
|
850
885
|
from PIL import Image
|
851
886
|
import GameSentenceMiner.obs as obs
|
852
887
|
|
853
888
|
def init_config(source=None, scene=None):
|
854
889
|
obs.update_current_game()
|
855
890
|
self.current_source = source if source else obs.get_active_source()
|
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}")
|
856
896
|
self.current_source_name = self.current_source.get("sourceName") or None
|
857
897
|
self.current_scene = scene if scene else obs.get_current_game()
|
858
898
|
self.ocr_config = get_scene_ocr_config()
|
@@ -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
|
|
@@ -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=
|
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
|
@@ -21,15 +21,15 @@ GameSentenceMiner/locales/zh_cn.json,sha256=h-YRSz2XN_TkymjkAH1MQ9KqGLE9_7Ru-N4y
|
|
21
21
|
GameSentenceMiner/ocr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
22
22
|
GameSentenceMiner/ocr/gsm_ocr_config.py,sha256=Ezj-0k6Wo-una91FvYhMp6KGkRhWYihXzLAoh_Wu2xY,5329
|
23
23
|
GameSentenceMiner/ocr/ocrconfig.py,sha256=_tY8mjnzHMJrLS8E5pHqYXZjMuLoGKYgJwdhYgN-ny4,6466
|
24
|
-
GameSentenceMiner/ocr/owocr_area_selector.py,sha256=
|
24
|
+
GameSentenceMiner/ocr/owocr_area_selector.py,sha256=BgLsUTWIWXTiwApuj5BZtNu1_wpVdODOIy5GAw3G6jg,27223
|
25
25
|
GameSentenceMiner/ocr/owocr_helper.py,sha256=nyNCt6TtOFvcXddwaNXpkuYbCsfBG5Nvp6b8mU-6jlg,25236
|
26
26
|
GameSentenceMiner/ocr/ss_picker.py,sha256=0IhxUdaKruFpZyBL-8SpxWg7bPrlGpy3lhTcMMZ5rwo,5224
|
27
27
|
GameSentenceMiner/owocr/owocr/__init__.py,sha256=87hfN5u_PbL_onLfMACbc0F5j4KyIK9lKnRCj6oZgR0,49
|
28
28
|
GameSentenceMiner/owocr/owocr/__main__.py,sha256=XQaqZY99EKoCpU-gWQjNbTs7Kg17HvBVE7JY8LqIE0o,157
|
29
29
|
GameSentenceMiner/owocr/owocr/config.py,sha256=qM7kISHdUhuygGXOxmgU6Ef2nwBShrZtdqu4InDCViE,8103
|
30
30
|
GameSentenceMiner/owocr/owocr/lens_betterproto.py,sha256=oNoISsPilVVRBBPVDtb4-roJtAhp8ZAuFTci3TGXtMc,39141
|
31
|
-
GameSentenceMiner/owocr/owocr/ocr.py,sha256=
|
32
|
-
GameSentenceMiner/owocr/owocr/run.py,sha256=
|
31
|
+
GameSentenceMiner/owocr/owocr/ocr.py,sha256=Vi3s4WLEY_wxQSH7sE19_PXUM2BU_lv-OE7YmtLaBRQ,62042
|
32
|
+
GameSentenceMiner/owocr/owocr/run.py,sha256=We3832iAXXSoJnjlTrI72jhUuMoxRQ_lbaz4TTjtyBc,68132
|
33
33
|
GameSentenceMiner/owocr/owocr/screen_coordinate_picker.py,sha256=Na6XStbQBtpQUSdbN3QhEswtKuU1JjReFk_K8t5ezQE,3395
|
34
34
|
GameSentenceMiner/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
35
35
|
GameSentenceMiner/util/audio_offset_selector.py,sha256=8Stk3BP-XVIuzRv9nl9Eqd2D-1yD3JrgU-CamBywJmY,8542
|
@@ -66,10 +66,10 @@ GameSentenceMiner/web/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm
|
|
66
66
|
GameSentenceMiner/web/templates/index.html,sha256=Gv3CJvNnhAzIVV_QxhNq4OD-pXDt1vKCu9k6WdHSXuA,215343
|
67
67
|
GameSentenceMiner/web/templates/text_replacements.html,sha256=tV5c8mCaWSt_vKuUpbdbLAzXZ3ATZeDvQ9PnnAfqY0M,8598
|
68
68
|
GameSentenceMiner/web/templates/utility.html,sha256=3flZinKNqUJ7pvrZk6xu__v67z44rXnaK7UTZ303R-8,16946
|
69
|
-
GameSentenceMiner/wip/get_overlay_coords.py,sha256=
|
70
|
-
gamesentenceminer-2.13.
|
71
|
-
gamesentenceminer-2.13.
|
72
|
-
gamesentenceminer-2.13.
|
73
|
-
gamesentenceminer-2.13.
|
74
|
-
gamesentenceminer-2.13.
|
75
|
-
gamesentenceminer-2.13.
|
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,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|