Files
openclaw-qqlobster-skills/skills/super-ocr/scripts/engine/macvision.py
T

153 lines
5.3 KiB
Python

#!/usr/bin/env python3
"""
MacVisionOCR - macOS Vision Text Recognition via Swift script
Uses Apple's Vision Framework via Swift script (confirmed working).
Requirements:
- macOS 10.15+ (Catalina)
- Swift (built-in on macOS)
"""
import subprocess
import sys
from pathlib import Path
from typing import Dict, List
# Path to Swift script
SWIFT_SCRIPT_PATH = Path(__file__).parent / "macvision_swift.swift"
class MacVisionOCR:
"""macOS Vision OCR wrapper using Swift script"""
def __init__(self, verbose: bool = False):
"""Initialize MacVisionOCR processor."""
self.verbose = verbose
if sys.platform != 'darwin':
raise RuntimeError("MacVisionOCR only works on macOS")
if self.verbose:
print("[INFO] MacVisionOCR initialized (via Swift)")
def _estimate_confidence(self, text: str) -> float:
"""Estimate OCR confidence from text quality."""
if not text:
return 0.0
printable = sum(1 for c in text if c.isprintable() or c in '\n\r\t')
length_factor = min(1.0, len(text) / 100)
quality = printable / max(len(text), 1)
confidence = 0.85 + (0.15 * quality * length_factor)
return round(min(confidence, 1.0), 4)
def extract(self, image_path: str) -> Dict:
"""Extract text from image using Mac Vision OCR via Swift."""
from time import time
if sys.platform != 'darwin':
return {
'text': '',
'confidence': 0.0,
'error': 'MacVisionOCR only works on macOS',
'processing_time_ms': 0
}
start_time = time()
try:
# Run Swift script with image path as argument
result = subprocess.run(
['swift', str(SWIFT_SCRIPT_PATH), image_path],
capture_output=True,
text=True,
timeout=60
)
if result.returncode != 0:
return {
'text': '',
'confidence': 0.0,
'error': result.stderr.strip(),
'processing_time_ms': (time() - start_time) * 1000
}
# Parse Chinese output
lines = result.stdout.strip().split('\n')
text_lines = []
all_confidences = []
current_text = None
for line in lines:
if line.startswith('文本:'):
current_text = line[3:].strip()
elif line.startswith('置信度:') and current_text:
try:
conf_str = line[4:].strip()
# Swift returns confidence as percentage (0-100)
# Output format: "置信度:50.00%" -> need to divide by 100
numeric_part = conf_str.rstrip('%').strip()
confidence = float(numeric_part) / 100.0
text_lines.append(current_text)
all_confidences.append(confidence)
current_text = None
except (ValueError, IndexError):
pass
full_text = '\n'.join(text_lines)
processing_time = (time() - start_time) * 1000
avg_confidence = sum(all_confidences) / len(all_confidences) if all_confidences else 0.0
return {
'text': full_text.strip(),
'confidence': round(avg_confidence, 4),
'line_count': len(text_lines),
'processing_time_ms': round(processing_time, 2)
}
except subprocess.TimeoutExpired:
return {
'text': '',
'confidence': 0.0,
'error': 'MacVisionOCR timeout',
'processing_time_ms': 60000
}
except Exception as e:
processing_time = (time() - start_time) * 1000
return {
'text': '',
'confidence': 0.0,
'error': f"MacVision error: {str(e)}",
'processing_time_ms': round(processing_time, 2)
}
def batch_extract(self, image_paths: List[str]) -> List[Dict]:
"""Process multiple images"""
return [self.extract(path) for path in image_paths]
if __name__ == '__main__':
import argparse
if sys.platform != 'darwin':
print("[ERROR] MacVisionOCR only works on macOS")
sys.exit(1)
if not SWIFT_SCRIPT_PATH.exists():
print(f"[ERROR] Swift script not found: {SWIFT_SCRIPT_PATH}")
sys.exit(1)
parser = argparse.ArgumentParser(description='macOS Vision OCR via Swift')
parser.add_argument('image', help='Image file to process')
parser.add_argument('--verbose', '-v', action='store_true')
args = parser.parse_args()
processor = MacVisionOCR(verbose=args.verbose)
result = processor.extract(args.image)
print(f"\nText:\n{result['text']}")
print(f"\nConfidence: {result['confidence']:.4f}")
print(f"Lines: {result.get('line_count', 0)}")
print(f"Time: {result.get('processing_time_ms', 0):.2f}ms")