feat: Add File Test tab to Game Reader Test plugin

Added new 'File Test' tab that allows testing OCR on saved screenshot files.
This is useful when:
- The game is not currently running
- You want to test OCR on a specific saved screenshot
- You want to compare OCR results on the same image

Features:
- Browse button to select image files (PNG, JPG, BMP, TIFF)
- Backend selection (Auto/EasyOCR/Tesseract)
- Displays filename and processing stats
- Shows which backend was used and processing time

The original 'Quick Test' still captures the current screen.
The new 'File Test' lets you test on saved images.
This commit is contained in:
LemonNexus 2026-02-14 20:07:47 +00:00
parent 345ec865e1
commit a80a9ccd06
1 changed files with 186 additions and 1 deletions

View File

@ -149,7 +149,10 @@ class GameReaderTestPlugin(BasePlugin):
# Tab 1: Quick Test
tabs.addTab(self._create_quick_test_tab(), "Quick Test")
# Tab 2: Region Test
# Tab 2: File Test (NEW)
tabs.addTab(self._create_file_test_tab(), "File Test")
# Tab 3: Region Test
tabs.addTab(self._create_region_test_tab(), "Region Test")
# Tab 3: History
@ -270,6 +273,87 @@ class GameReaderTestPlugin(BasePlugin):
layout.addStretch()
return tab
def _create_file_test_tab(self):
"""Create file-based OCR test tab for testing with saved screenshots."""
tab = QWidget()
layout = QVBoxLayout(tab)
# Info
info = QLabel("Test OCR on an image file (PNG, JPG, BMP)")
info.setStyleSheet("color: #888;")
layout.addWidget(info)
# File selection
file_layout = QHBoxLayout()
self.file_path_label = QLabel("No file selected")
self.file_path_label.setStyleSheet("color: #aaa; padding: 8px; background-color: #1a1f2e; border-radius: 4px;")
file_layout.addWidget(self.file_path_label, 1)
browse_btn = QPushButton("Browse...")
browse_btn.setStyleSheet("""
QPushButton {
background-color: #4ecdc4;
color: #141f23;
font-weight: bold;
padding: 8px 16px;
}
""")
browse_btn.clicked.connect(self._browse_image_file)
file_layout.addWidget(browse_btn)
layout.addLayout(file_layout)
# Backend selection
backend_layout = QHBoxLayout()
backend_layout.addWidget(QLabel("OCR Backend:"))
self.file_backend_combo = QComboBox()
self.file_backend_combo.addItems(["Auto (try all)", "EasyOCR", "Tesseract", "PaddleOCR"])
backend_layout.addWidget(self.file_backend_combo)
backend_layout.addStretch()
layout.addLayout(backend_layout)
# Test button
file_test_btn = QPushButton("▶ Run OCR on File")
file_test_btn.setStyleSheet("""
QPushButton {
background-color: #ff8c42;
color: #141f23;
font-weight: bold;
padding: 12px;
font-size: 14px;
}
""")
file_test_btn.clicked.connect(self._run_file_test)
layout.addWidget(file_test_btn)
# Results
results_group = QGroupBox("OCR Results")
results_layout = QVBoxLayout(results_group)
self.file_results_text = QTextEdit()
self.file_results_text.setReadOnly(True)
self.file_results_text.setPlaceholderText("OCR results will appear here...")
self.file_results_text.setStyleSheet("""
QTextEdit {
background-color: #0d1117;
color: #c9d1d9;
font-family: Consolas, monospace;
font-size: 12px;
}
""")
results_layout.addWidget(self.file_results_text)
# Stats
self.file_stats_label = QLabel("File: - | Backend: - | Status: Waiting")
self.file_stats_label.setStyleSheet("color: #888;")
results_layout.addWidget(self.file_stats_label)
layout.addWidget(results_group, 1)
layout.addStretch()
return tab
def _create_region_test_tab(self):
"""Create region test tab."""
tab = QWidget()
@ -453,6 +537,107 @@ class GameReaderTestPlugin(BasePlugin):
self.w_input.setValue(w)
self.h_input.setValue(h)
def _browse_image_file(self):
"""Browse for an image file to test OCR on."""
file_path, _ = QFileDialog.getOpenFileName(
None,
"Select Image File",
"",
"Images (*.png *.jpg *.jpeg *.bmp *.tiff);;All Files (*)"
)
if file_path:
self.selected_file_path = file_path
self.file_path_label.setText(Path(file_path).name)
self.file_path_label.setStyleSheet("color: #4ecdc4; padding: 8px; background-color: #1a1f2e; border-radius: 4px;")
def _run_file_test(self):
"""Run OCR on the selected image file."""
if not hasattr(self, 'selected_file_path') or not self.selected_file_path:
QMessageBox.warning(None, "No File", "Please select an image file first!")
return
backend_map = {
0: 'auto',
1: 'easyocr',
2: 'tesseract',
3: 'paddle'
}
backend = backend_map.get(self.file_backend_combo.currentIndex(), 'auto')
self.file_results_text.setPlainText("Processing...")
self.file_stats_label.setText("Processing...")
# Run OCR in a thread
from threading import Thread
def process_file():
try:
from PIL import Image
import time
start_time = time.time()
# Load image
image = Image.open(self.selected_file_path)
# Try OCR backends
text = ""
backend_used = "none"
if backend in ('auto', 'easyocr'):
try:
import easyocr
reader = easyocr.Reader(['en'], gpu=False, verbose=False)
ocr_result = reader.readtext(
image,
detail=0,
paragraph=True
)
text = '\n'.join(ocr_result)
backend_used = "easyocr"
except Exception as e:
if backend == 'easyocr':
raise e
if not text and backend in ('auto', 'tesseract'):
try:
import pytesseract
text = pytesseract.image_to_string(image)
backend_used = "tesseract"
except Exception as e:
if backend == 'tesseract':
raise e
processing_time = time.time() - start_time
# Update UI (thread-safe via Qt signals would be better, but this works for simple case)
from PyQt6.QtCore import QMetaObject, Qt, Q_ARG
QMetaObject.invokeMethod(
self.file_results_text,
"setPlainText",
Qt.ConnectionType.QueuedConnection,
Q_ARG(str, text if text else "No text detected")
)
QMetaObject.invokeMethod(
self.file_stats_label,
"setText",
Qt.ConnectionType.QueuedConnection,
Q_ARG(str, f"File: {Path(self.selected_file_path).name} | Backend: {backend_used} | Time: {processing_time:.2f}s")
)
except Exception as e:
from PyQt6.QtCore import QMetaObject, Qt, Q_ARG
QMetaObject.invokeMethod(
self.file_results_text,
"setPlainText",
Qt.ConnectionType.QueuedConnection,
Q_ARG(str, f"Error: {str(e)}")
)
thread = Thread(target=process_file)
thread.daemon = True
thread.start()
def _run_quick_test(self):
"""Run quick OCR test."""
if self.ocr_thread and self.ocr_thread.isRunning():