Add Gemini OCR and fix VRC log world handling
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import os
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
os.environ["FLAGS_enable_pir_api"] = "0"
|
||||
@@ -33,9 +34,9 @@ def getOcrEngine():
|
||||
log("INFO", "PaddleOCR initializing")
|
||||
config = loadOcrConfig()
|
||||
options = {
|
||||
"lang": "japan",
|
||||
"lang": config["lang"],
|
||||
"use_angle_cls": config["use_angle_cls"],
|
||||
"show_log": False,
|
||||
"show_log": config["show_log"],
|
||||
}
|
||||
|
||||
try:
|
||||
@@ -47,6 +48,27 @@ def getOcrEngine():
|
||||
return _ocr_engine
|
||||
|
||||
|
||||
_gemini_client = None
|
||||
|
||||
|
||||
def getGeminiClient(api_key):
|
||||
global _gemini_client
|
||||
|
||||
if _gemini_client is not None:
|
||||
return _gemini_client
|
||||
|
||||
if not api_key:
|
||||
raise RuntimeError("Gemini API key is not set in secrets.toml [ai]")
|
||||
|
||||
try:
|
||||
from google import genai
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"Gemini SDK is missing detail={e}")
|
||||
|
||||
_gemini_client = genai.Client(api_key=api_key)
|
||||
return _gemini_client
|
||||
|
||||
|
||||
def saveOcrText(image_path, text):
|
||||
return appendRuntimeLog(
|
||||
"OCR TEXT",
|
||||
@@ -149,18 +171,69 @@ def runPaddleOcr(engine, image_path):
|
||||
return engine.ocr(str(image_path))
|
||||
|
||||
|
||||
def runOcrFromImage(image_path, show_result=True):
|
||||
log("ACTION", f"PaddleOCR start image={image_path}")
|
||||
def runGeminiOcr(image_path):
|
||||
config = loadOcrConfig()
|
||||
model_name = config["model_name"] or "gemini-2.5-flash"
|
||||
prompt = (
|
||||
"Extract every readable text fragment from this image with maximum accuracy. "
|
||||
"Do not summarize, explain, translate, or guess. "
|
||||
"Return only the text exactly as it appears, preserving line breaks and order."
|
||||
)
|
||||
|
||||
try:
|
||||
image_path = preprocessOcrImage(image_path)
|
||||
engine = getOcrEngine()
|
||||
result = runPaddleOcr(engine, image_path)
|
||||
from google.genai import types
|
||||
except Exception as e:
|
||||
log("ERROR", f"PaddleOCR failed detail={e}")
|
||||
return None
|
||||
raise RuntimeError(f"Gemini types import failed detail={e}")
|
||||
|
||||
client = getGeminiClient(config["api_key"])
|
||||
mime_type = "image/png"
|
||||
suffix = str(image_path).lower()
|
||||
if suffix.endswith(".jpg") or suffix.endswith(".jpeg"):
|
||||
mime_type = "image/jpeg"
|
||||
elif suffix.endswith(".webp"):
|
||||
mime_type = "image/webp"
|
||||
|
||||
image_bytes = image_path.read_bytes()
|
||||
image_part = types.Part.from_bytes(data=image_bytes, mime_type=mime_type)
|
||||
response = client.models.generate_content(
|
||||
model=model_name,
|
||||
contents=[prompt, image_part],
|
||||
)
|
||||
text = (response.text or "").strip()
|
||||
return text
|
||||
|
||||
|
||||
def runOcrFromImage(image_path, show_result=True):
|
||||
try:
|
||||
image_path = preprocessOcrImage(image_path)
|
||||
config = loadOcrConfig()
|
||||
provider = config["provider"]
|
||||
log("ACTION", f"OCR start provider={provider} image={image_path}")
|
||||
|
||||
if provider == "gemini":
|
||||
text = runGeminiOcr(image_path)
|
||||
else:
|
||||
engine = getOcrEngine()
|
||||
result = runPaddleOcr(engine, image_path)
|
||||
text = extractTextFromAny(result)
|
||||
|
||||
if not text:
|
||||
raise RuntimeError("OCR text is empty")
|
||||
except Exception as e:
|
||||
log("ERROR", f"OCR failed detail={e}")
|
||||
|
||||
if config.get("provider") == "gemini":
|
||||
log("INFO", "Falling back to PaddleOCR")
|
||||
try:
|
||||
engine = getOcrEngine()
|
||||
result = runPaddleOcr(engine, image_path)
|
||||
text = extractTextFromAny(result)
|
||||
except Exception as fallback_error:
|
||||
log("ERROR", f"PaddleOCR fallback failed detail={fallback_error}")
|
||||
return None
|
||||
else:
|
||||
return None
|
||||
|
||||
text = extractTextFromAny(result)
|
||||
text_path = saveOcrText(image_path, text)
|
||||
|
||||
try:
|
||||
@@ -183,4 +256,8 @@ def runOcrFromImage(image_path, show_result=True):
|
||||
def runOcrFromScreen():
|
||||
log("ACTION", "runOcrFromScreen called")
|
||||
image_path = captureOcrRegion()
|
||||
delay_seconds = max(0.0, loadOcrConfig().get("delay_seconds", 1.0))
|
||||
if delay_seconds:
|
||||
log("INFO", f"OCR delayed seconds={delay_seconds}")
|
||||
time.sleep(delay_seconds)
|
||||
return runOcrFromImage(image_path, show_result=True)
|
||||
|
||||
Reference in New Issue
Block a user