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:
parent
345ec865e1
commit
a80a9ccd06
|
|
@ -149,7 +149,10 @@ class GameReaderTestPlugin(BasePlugin):
|
||||||
# Tab 1: Quick Test
|
# Tab 1: Quick Test
|
||||||
tabs.addTab(self._create_quick_test_tab(), "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")
|
tabs.addTab(self._create_region_test_tab(), "Region Test")
|
||||||
|
|
||||||
# Tab 3: History
|
# Tab 3: History
|
||||||
|
|
@ -270,6 +273,87 @@ class GameReaderTestPlugin(BasePlugin):
|
||||||
layout.addStretch()
|
layout.addStretch()
|
||||||
return tab
|
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):
|
def _create_region_test_tab(self):
|
||||||
"""Create region test tab."""
|
"""Create region test tab."""
|
||||||
tab = QWidget()
|
tab = QWidget()
|
||||||
|
|
@ -453,6 +537,107 @@ class GameReaderTestPlugin(BasePlugin):
|
||||||
self.w_input.setValue(w)
|
self.w_input.setValue(w)
|
||||||
self.h_input.setValue(h)
|
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):
|
def _run_quick_test(self):
|
||||||
"""Run quick OCR test."""
|
"""Run quick OCR test."""
|
||||||
if self.ocr_thread and self.ocr_thread.isRunning():
|
if self.ocr_thread and self.ocr_thread.isRunning():
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue