publish eve_rock_watcher.py

This commit is contained in:
brockdarnold 2026-06-15 02:56:14 +00:00
parent 3476f9a4a3
commit 3f583492a1

View file

@ -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