diff --git a/eve_rock_watcher.py b/eve_rock_watcher.py index 26d81d8..33c1465 100644 --- a/eve_rock_watcher.py +++ b/eve_rock_watcher.py @@ -90,50 +90,33 @@ def save_rock_region(cp, l, t, wd, ht, mode="survey"): def detect_selected_region(cp): - """Find the Selected Item panel by locating its 'Quantity N Units' line.""" - import mss + """Find the Selected Item 'Quantity N Units' line WITHIN the EVE window capture + (clean, occlusion-proof). Returns a WINDOW-RELATIVE tight [l,t,w,h] or None.""" import pytesseract - from PIL import Image tcmd = cp.get("ocr", "tesseract_cmd", fallback="").strip() if tcmd: pytesseract.pytesseract.tesseract_cmd = tcmd - # CROP to the center band (where EVE sits on a big multi-monitor desktop) THEN - # upscale — full-screen OCR is too coarse to read the small panel text. This is the - # exact approach that successfully located 'Quantity 43,975 Units' on Brock's screen. - S = 2 - try: - with mss.mss() as sct: - mon = sct.monitors[0] - raw = sct.grab(mon) - img = Image.frombytes("RGB", raw.size, raw.bgra, "raw", "BGRX") - W, Hh = img.size - cx0, cy0 = int(W * 0.22), 0 - crop = img.crop((cx0, cy0, int(W * 0.82), int(Hh * 0.97))) - up = crop.resize((crop.width * S, crop.height * S)) - data = pytesseract.image_to_data(up, output_type=pytesseract.Output.DICT) - except Exception as e: - print(f"[rock] detect error: {e}") + img = w.capture_window() + if img is None: return None - lines = {} - for i in range(len(data["text"])): - if not data["text"][i].strip(): + S = 2 + d = pytesseract.image_to_data(img.resize((img.width*S, img.height*S)), + output_type=pytesseract.Output.DICT) + n = len(d["text"]) + for i in range(n): + if "unit" not in d["text"][i].strip().lower(): continue - k = (data["block_num"][i], data["par_num"][i], data["line_num"][i]) - lines.setdefault(k, []).append(i) - for idxs in lines.values(): - joined = " ".join(data["text"][i] for i in idxs) - # the 'Quantity N Units' line: contains 'unit' + a digit (tolerant to OCR) - if "unit" in joined.lower() and re.search(r"\d", joined): - xs = [data["left"][i] // S for i in idxs] # 2x -> crop space - ys = [data["top"][i] // S for i in idxs] - rs = [(data["left"][i] + data["width"][i]) // S for i in idxs] - bs = [(data["top"][i] + data["height"][i]) // S for i in idxs] - padx = 180 # extend LEFT to capture the number - region = [mon["left"] + cx0 + min(xs) - padx, mon["top"] + cy0 + min(ys) - 8, - (max(rs) - min(xs)) + padx + 30, (max(bs) - min(ys)) + 16] - save_rock_region(cp, *region, mode="selected") - print(f"[rock] auto-detected Selected-Item quantity -> {region}") - return region + uy, uh, ux, ur = d["top"][i], d["height"][i], d["left"][i], d["left"][i] + d["width"][i] + # the number is the word(s) just LEFT of "Units" on the same line + nums = [j for j in range(n) if d["text"][j].strip() and abs(d["top"][j] - uy) < uh + and 0 < (ux - d["left"][j]) < 340 * S and re.search(r"\d", d["text"][j])] + if not nums: + continue + l = min(d["left"][j] for j in nums) // S + reg = [max(0, l - 20), max(0, uy // S - 6), (ur // S - l) + 45, uh // S + 12] + save_rock_region(cp, *reg, mode="selected") + print(f"[rock] Selected-Item quantity region (window-relative) -> {reg}") + return reg return None @@ -231,13 +214,13 @@ def get_region(cp): rs = cp.get("rock", "region", fallback="").strip() if rs: return [int(x) for x in rs.split(",")], cp.get("rock", "mode", fallback="survey") - print("[rock] no saved region — looking for a Survey Scanner window, else Selected Item...") - r = detect_survey_region(cp) - if r: - return r, "survey" - r = detect_selected_region(cp) + print("[rock] no saved region — locating the Selected-Item Quantity line...") + r = detect_selected_region(cp) # primary: the rock you have selected if r: return r, "selected" + r = detect_survey_region(cp) # fallback: a Survey Scanner window + if r: + return r, "survey" return None, None