646 lines
24 KiB
Python
646 lines
24 KiB
Python
"""
|
|
Lemontropia Suite - Vision Settings Dialog
|
|
Settings panel for configuring Game Vision AI.
|
|
"""
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
from PyQt6.QtWidgets import (
|
|
QDialog, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit,
|
|
QPushButton, QComboBox, QCheckBox, QGroupBox, QFormLayout,
|
|
QMessageBox, QSpinBox, QDoubleSpinBox, QTabWidget,
|
|
QFileDialog, QTextEdit, QProgressBar, QWidget, QSlider
|
|
)
|
|
from PyQt6.QtCore import Qt, QSettings, QThread, pyqtSignal
|
|
from PyQt6.QtGui import QFont, QPixmap
|
|
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class GPUInfoThread(QThread):
|
|
"""Thread to gather GPU information."""
|
|
|
|
info_ready = pyqtSignal(dict)
|
|
error_occurred = pyqtSignal(str)
|
|
|
|
def run(self):
|
|
try:
|
|
from modules.game_vision_ai import GPUDetector
|
|
info = GPUDetector.get_gpu_info()
|
|
self.info_ready.emit(info)
|
|
except Exception as e:
|
|
self.error_occurred.emit(str(e))
|
|
|
|
|
|
class VisionSettingsDialog(QDialog):
|
|
"""
|
|
Settings dialog for Game Vision AI configuration.
|
|
"""
|
|
|
|
settings_saved = pyqtSignal()
|
|
|
|
def __init__(self, parent=None):
|
|
super().__init__(parent)
|
|
self.setWindowTitle("Game Vision Settings")
|
|
self.setMinimumSize(600, 500)
|
|
|
|
self.settings = QSettings("Lemontropia", "GameVision")
|
|
self.gpu_info = {}
|
|
|
|
self.setup_ui()
|
|
self.load_settings()
|
|
self.refresh_gpu_info()
|
|
|
|
def setup_ui(self):
|
|
"""Setup the dialog UI."""
|
|
layout = QVBoxLayout(self)
|
|
layout.setSpacing(15)
|
|
|
|
# Title
|
|
title_label = QLabel("🎮 Game Vision AI Settings")
|
|
title_font = QFont()
|
|
title_font.setPointSize(14)
|
|
title_font.setBold(True)
|
|
title_label.setFont(title_font)
|
|
layout.addWidget(title_label)
|
|
|
|
# Description
|
|
desc_label = QLabel(
|
|
"Configure AI-powered computer vision for automatic game UI analysis."
|
|
)
|
|
desc_label.setWordWrap(True)
|
|
layout.addWidget(desc_label)
|
|
|
|
# Tabs
|
|
self.tabs = QTabWidget()
|
|
layout.addWidget(self.tabs)
|
|
|
|
# General tab
|
|
self.tabs.addTab(self._create_general_tab(), "General")
|
|
|
|
# GPU tab
|
|
self.tabs.addTab(self._create_gpu_tab(), "GPU & Performance")
|
|
|
|
# OCR tab
|
|
self.tabs.addTab(self._create_ocr_tab(), "OCR Settings")
|
|
|
|
# Icon Detection tab
|
|
self.tabs.addTab(self._create_icon_tab(), "Icon Detection")
|
|
|
|
# Buttons
|
|
button_layout = QHBoxLayout()
|
|
button_layout.addStretch()
|
|
|
|
self.reset_btn = QPushButton("Reset to Defaults")
|
|
self.reset_btn.clicked.connect(self.reset_settings)
|
|
button_layout.addWidget(self.reset_btn)
|
|
|
|
self.test_btn = QPushButton("Test Vision...")
|
|
self.test_btn.clicked.connect(self.open_test_dialog)
|
|
button_layout.addWidget(self.test_btn)
|
|
|
|
self.save_btn = QPushButton("Save")
|
|
self.save_btn.clicked.connect(self.save_settings)
|
|
self.save_btn.setDefault(True)
|
|
button_layout.addWidget(self.save_btn)
|
|
|
|
self.cancel_btn = QPushButton("Cancel")
|
|
self.cancel_btn.clicked.connect(self.reject)
|
|
button_layout.addWidget(self.cancel_btn)
|
|
|
|
layout.addLayout(button_layout)
|
|
|
|
def _create_general_tab(self) -> QWidget:
|
|
"""Create general settings tab."""
|
|
tab = QWidget()
|
|
layout = QVBoxLayout(tab)
|
|
layout.setSpacing(15)
|
|
|
|
# Enable Vision
|
|
self.enable_vision_cb = QCheckBox("Enable Game Vision AI")
|
|
self.enable_vision_cb.setToolTip(
|
|
"Enable automatic screenshot analysis using AI"
|
|
)
|
|
layout.addWidget(self.enable_vision_cb)
|
|
|
|
# Auto Processing
|
|
self.auto_process_cb = QCheckBox("Auto-process screenshots")
|
|
self.auto_process_cb.setToolTip(
|
|
"Automatically analyze screenshots when captured"
|
|
)
|
|
layout.addWidget(self.auto_process_cb)
|
|
|
|
# Data Directory
|
|
dir_group = QGroupBox("Data Directories")
|
|
dir_layout = QFormLayout(dir_group)
|
|
|
|
# Extracted icons directory
|
|
icons_dir_layout = QHBoxLayout()
|
|
self.icons_dir_input = QLineEdit()
|
|
self.icons_dir_input.setReadOnly(True)
|
|
icons_dir_layout.addWidget(self.icons_dir_input)
|
|
|
|
self.icons_dir_btn = QPushButton("Browse...")
|
|
self.icons_dir_btn.clicked.connect(self.browse_icons_dir)
|
|
icons_dir_layout.addWidget(self.icons_dir_btn)
|
|
|
|
dir_layout.addRow("Extracted Icons:", icons_dir_layout)
|
|
|
|
# Icon database directory
|
|
db_dir_layout = QHBoxLayout()
|
|
self.db_dir_input = QLineEdit()
|
|
self.db_dir_input.setReadOnly(True)
|
|
db_dir_layout.addWidget(self.db_dir_input)
|
|
|
|
self.db_dir_btn = QPushButton("Browse...")
|
|
self.db_dir_btn.clicked.connect(self.browse_db_dir)
|
|
db_dir_layout.addWidget(self.db_dir_btn)
|
|
|
|
dir_layout.addRow("Icon Database:", db_dir_layout)
|
|
|
|
layout.addWidget(dir_group)
|
|
|
|
# Processing Options
|
|
options_group = QGroupBox("Processing Options")
|
|
options_layout = QFormLayout(options_group)
|
|
|
|
self.extract_text_cb = QCheckBox("Extract text (OCR)")
|
|
self.extract_text_cb.setChecked(True)
|
|
options_layout.addRow(self.extract_text_cb)
|
|
|
|
self.extract_icons_cb = QCheckBox("Extract icons")
|
|
self.extract_icons_cb.setChecked(True)
|
|
options_layout.addRow(self.extract_icons_cb)
|
|
|
|
self.save_icons_cb = QCheckBox("Save extracted icons to disk")
|
|
self.save_icons_cb.setChecked(True)
|
|
options_layout.addRow(self.save_icons_cb)
|
|
|
|
self.match_icons_cb = QCheckBox("Match icons to database")
|
|
self.match_icons_cb.setChecked(True)
|
|
options_layout.addRow(self.match_icons_cb)
|
|
|
|
layout.addWidget(options_group)
|
|
layout.addStretch()
|
|
|
|
return tab
|
|
|
|
def _create_gpu_tab(self) -> QWidget:
|
|
"""Create GPU settings tab."""
|
|
tab = QWidget()
|
|
layout = QVBoxLayout(tab)
|
|
layout.setSpacing(15)
|
|
|
|
# GPU Info Group
|
|
gpu_group = QGroupBox("GPU Information")
|
|
gpu_layout = QVBoxLayout(gpu_group)
|
|
|
|
self.gpu_info_label = QLabel("Detecting GPU...")
|
|
self.gpu_info_label.setWordWrap(True)
|
|
gpu_layout.addWidget(self.gpu_info_label)
|
|
|
|
self.gpu_details = QTextEdit()
|
|
self.gpu_details.setReadOnly(True)
|
|
self.gpu_details.setMaximumHeight(100)
|
|
gpu_layout.addWidget(self.gpu_details)
|
|
|
|
self.refresh_gpu_btn = QPushButton("Refresh GPU Info")
|
|
self.refresh_gpu_btn.clicked.connect(self.refresh_gpu_info)
|
|
gpu_layout.addWidget(self.refresh_gpu_btn)
|
|
|
|
layout.addWidget(gpu_group)
|
|
|
|
# GPU Settings
|
|
settings_group = QGroupBox("GPU Acceleration")
|
|
settings_layout = QFormLayout(settings_group)
|
|
|
|
self.use_gpu_cb = QCheckBox("Use GPU acceleration")
|
|
self.use_gpu_cb.setToolTip(
|
|
"Enable GPU acceleration for OCR and vision processing"
|
|
)
|
|
settings_layout.addRow(self.use_gpu_cb)
|
|
|
|
# GPU Backend selection
|
|
self.backend_combo = QComboBox()
|
|
self.backend_combo.addItem("Auto-detect", "auto")
|
|
self.backend_combo.addItem("CUDA (NVIDIA)", "cuda")
|
|
self.backend_combo.addItem("MPS (Apple Silicon)", "mps")
|
|
self.backend_combo.addItem("DirectML (Windows)", "directml")
|
|
self.backend_combo.addItem("CPU only", "cpu")
|
|
settings_layout.addRow("Preferred Backend:", self.backend_combo)
|
|
|
|
layout.addWidget(settings_group)
|
|
|
|
# Performance Settings
|
|
perf_group = QGroupBox("Performance")
|
|
perf_layout = QFormLayout(perf_group)
|
|
|
|
self.batch_size_spin = QSpinBox()
|
|
self.batch_size_spin.setRange(1, 16)
|
|
self.batch_size_spin.setValue(1)
|
|
self.batch_size_spin.setToolTip(
|
|
"Number of images to process in parallel (higher = faster but more VRAM)"
|
|
)
|
|
perf_layout.addRow("Batch Size:", self.batch_size_spin)
|
|
|
|
self.threads_spin = QSpinBox()
|
|
self.threads_spin.setRange(1, 8)
|
|
self.threads_spin.setValue(2)
|
|
perf_layout.addRow("Processing Threads:", self.threads_spin)
|
|
|
|
layout.addWidget(perf_group)
|
|
layout.addStretch()
|
|
|
|
return tab
|
|
|
|
def _create_ocr_tab(self) -> QWidget:
|
|
"""Create OCR settings tab."""
|
|
tab = QWidget()
|
|
layout = QVBoxLayout(tab)
|
|
layout.setSpacing(15)
|
|
|
|
# Language Settings
|
|
lang_group = QGroupBox("Language Settings")
|
|
lang_layout = QFormLayout(lang_group)
|
|
|
|
self.ocr_lang_combo = QComboBox()
|
|
self.ocr_lang_combo.addItem("English", "en")
|
|
self.ocr_lang_combo.addItem("Swedish", "sv")
|
|
self.ocr_lang_combo.addItem("Latin Script (Generic)", "latin")
|
|
lang_layout.addRow("OCR Language:", self.ocr_lang_combo)
|
|
|
|
self.multi_lang_cb = QCheckBox("Enable multi-language detection")
|
|
lang_layout.addRow(self.multi_lang_cb)
|
|
|
|
layout.addWidget(lang_group)
|
|
|
|
# OCR Parameters
|
|
params_group = QGroupBox("OCR Parameters")
|
|
params_layout = QFormLayout(params_group)
|
|
|
|
self.det_thresh_spin = QDoubleSpinBox()
|
|
self.det_thresh_spin.setRange(0.1, 0.9)
|
|
self.det_thresh_spin.setValue(0.3)
|
|
self.det_thresh_spin.setSingleStep(0.05)
|
|
self.det_thresh_spin.setToolTip(
|
|
"Text detection threshold (lower = more sensitive)"
|
|
)
|
|
params_layout.addRow("Detection Threshold:", self.det_thresh_spin)
|
|
|
|
self.rec_thresh_spin = QDoubleSpinBox()
|
|
self.rec_thresh_spin.setRange(0.1, 0.9)
|
|
self.rec_thresh_spin.setValue(0.5)
|
|
self.rec_thresh_spin.setSingleStep(0.05)
|
|
self.rec_thresh_spin.setToolTip(
|
|
"Text recognition confidence threshold"
|
|
)
|
|
params_layout.addRow("Recognition Threshold:", self.rec_thresh_spin)
|
|
|
|
self.use_angle_cls_cb = QCheckBox("Use angle classifier")
|
|
self.use_angle_cls_cb.setChecked(True)
|
|
self.use_angle_cls_cb.setToolTip(
|
|
"Detect and correct rotated text (slower but more accurate)"
|
|
)
|
|
params_layout.addRow(self.use_angle_cls_cb)
|
|
|
|
layout.addWidget(params_group)
|
|
|
|
# Preprocessing
|
|
preprocess_group = QGroupBox("Preprocessing")
|
|
preprocess_layout = QFormLayout(preprocess_group)
|
|
|
|
self.denoise_cb = QCheckBox("Apply denoising")
|
|
self.denoise_cb.setChecked(True)
|
|
preprocess_layout.addRow(self.denoise_cb)
|
|
|
|
self.contrast_enhance_cb = QCheckBox("Enhance contrast")
|
|
self.contrast_enhance_cb.setChecked(True)
|
|
preprocess_layout.addRow(self.contrast_enhance_cb)
|
|
|
|
layout.addWidget(preprocess_group)
|
|
layout.addStretch()
|
|
|
|
return tab
|
|
|
|
def _create_icon_tab(self) -> QWidget:
|
|
"""Create icon detection settings tab."""
|
|
tab = QWidget()
|
|
layout = QVBoxLayout(tab)
|
|
layout.setSpacing(15)
|
|
|
|
# Detection Settings
|
|
detect_group = QGroupBox("Detection Settings")
|
|
detect_layout = QFormLayout(detect_group)
|
|
|
|
self.auto_detect_window_cb = QCheckBox("Auto-detect loot windows")
|
|
self.auto_detect_window_cb.setChecked(True)
|
|
self.auto_detect_window_cb.setToolTip(
|
|
"Automatically detect loot windows in screenshots"
|
|
)
|
|
detect_layout.addRow(self.auto_detect_window_cb)
|
|
|
|
self.icon_size_combo = QComboBox()
|
|
self.icon_size_combo.addItem("Small (32x32)", "small")
|
|
self.icon_size_combo.addItem("Medium (48x48)", "medium")
|
|
self.icon_size_combo.addItem("Large (64x64)", "large")
|
|
self.icon_size_combo.addItem("HUD (40x40)", "hud")
|
|
detect_layout.addRow("Icon Size:", self.icon_size_combo)
|
|
|
|
self.confidence_thresh_spin = QDoubleSpinBox()
|
|
self.confidence_thresh_spin.setRange(0.1, 1.0)
|
|
self.confidence_thresh_spin.setValue(0.7)
|
|
self.confidence_thresh_spin.setSingleStep(0.05)
|
|
detect_layout.addRow("Detection Confidence:", self.confidence_thresh_spin)
|
|
|
|
layout.addWidget(detect_group)
|
|
|
|
# Matching Settings
|
|
match_group = QGroupBox("Icon Matching")
|
|
match_layout = QFormLayout(match_group)
|
|
|
|
self.hash_match_cb = QCheckBox("Use perceptual hashing")
|
|
self.hash_match_cb.setChecked(True)
|
|
match_layout.addRow(self.hash_match_cb)
|
|
|
|
self.feature_match_cb = QCheckBox("Use feature matching (ORB)")
|
|
self.feature_match_cb.setChecked(True)
|
|
match_layout.addRow(self.feature_match_cb)
|
|
|
|
self.template_match_cb = QCheckBox("Use template matching")
|
|
self.template_match_cb.setChecked(True)
|
|
match_layout.addRow(self.template_match_cb)
|
|
|
|
self.match_thresh_spin = QDoubleSpinBox()
|
|
self.match_thresh_spin.setRange(0.1, 1.0)
|
|
self.match_thresh_spin.setValue(0.70)
|
|
self.match_thresh_spin.setSingleStep(0.05)
|
|
self.match_thresh_spin.setToolTip(
|
|
"Minimum confidence for icon match"
|
|
)
|
|
match_layout.addRow("Match Threshold:", self.match_thresh_spin)
|
|
|
|
layout.addWidget(match_group)
|
|
|
|
# Template Directory
|
|
template_group = QGroupBox("Template Directory")
|
|
template_layout = QHBoxLayout(template_group)
|
|
|
|
self.template_dir_input = QLineEdit()
|
|
self.template_dir_input.setReadOnly(True)
|
|
template_layout.addWidget(self.template_dir_input)
|
|
|
|
self.template_dir_btn = QPushButton("Browse...")
|
|
self.template_dir_btn.clicked.connect(self.browse_template_dir)
|
|
template_layout.addWidget(self.template_dir_btn)
|
|
|
|
layout.addWidget(template_group)
|
|
layout.addStretch()
|
|
|
|
return tab
|
|
|
|
def refresh_gpu_info(self):
|
|
"""Refresh GPU information display."""
|
|
self.gpu_info_label.setText("Detecting GPU...")
|
|
self.refresh_gpu_btn.setEnabled(False)
|
|
|
|
self.gpu_thread = GPUInfoThread()
|
|
self.gpu_thread.info_ready.connect(self.on_gpu_info_ready)
|
|
self.gpu_thread.error_occurred.connect(self.on_gpu_error)
|
|
self.gpu_thread.start()
|
|
|
|
def on_gpu_info_ready(self, info: dict):
|
|
"""Handle GPU info received."""
|
|
self.gpu_info = info
|
|
|
|
backend = info.get('backend', 'cpu')
|
|
cuda_available = info.get('cuda_available', False)
|
|
mps_available = info.get('mps_available', False)
|
|
|
|
# Update label
|
|
if backend == 'cuda':
|
|
devices = info.get('devices', [])
|
|
if devices:
|
|
device_name = devices[0].get('name', 'Unknown')
|
|
memory_gb = devices[0].get('memory_total', 0) / (1024**3)
|
|
self.gpu_info_label.setText(
|
|
f"✅ GPU Detected: {device_name} ({memory_gb:.1f} GB)"
|
|
)
|
|
else:
|
|
self.gpu_info_label.setText("✅ CUDA Available")
|
|
elif backend == 'mps':
|
|
self.gpu_info_label.setText("✅ Apple MPS (Metal) Available")
|
|
elif backend == 'directml':
|
|
self.gpu_info_label.setText("✅ DirectML Available")
|
|
else:
|
|
self.gpu_info_label.setText("⚠️ No GPU detected - CPU only")
|
|
|
|
# Update details
|
|
details = f"Backend: {backend}\n"
|
|
details += f"CUDA Available: {cuda_available}\n"
|
|
details += f"MPS Available: {mps_available}\n"
|
|
|
|
if info.get('devices'):
|
|
for dev in info['devices']:
|
|
details += f"\nDevice {dev['id']}: {dev['name']}"
|
|
|
|
self.gpu_details.setText(details)
|
|
self.refresh_gpu_btn.setEnabled(True)
|
|
|
|
def on_gpu_error(self, error: str):
|
|
"""Handle GPU detection error."""
|
|
self.gpu_info_label.setText(f"❌ Error detecting GPU: {error}")
|
|
self.refresh_gpu_btn.setEnabled(True)
|
|
|
|
def browse_icons_dir(self):
|
|
"""Browse for extracted icons directory."""
|
|
dir_path = QFileDialog.getExistingDirectory(
|
|
self, "Select Extracted Icons Directory",
|
|
self.icons_dir_input.text() or str(Path.home())
|
|
)
|
|
if dir_path:
|
|
self.icons_dir_input.setText(dir_path)
|
|
|
|
def browse_db_dir(self):
|
|
"""Browse for database directory."""
|
|
dir_path = QFileDialog.getExistingDirectory(
|
|
self, "Select Database Directory",
|
|
self.db_dir_input.text() or str(Path.home())
|
|
)
|
|
if dir_path:
|
|
self.db_dir_input.setText(dir_path)
|
|
|
|
def browse_template_dir(self):
|
|
"""Browse for template directory."""
|
|
dir_path = QFileDialog.getExistingDirectory(
|
|
self, "Select Template Directory",
|
|
self.template_dir_input.text() or str(Path.home())
|
|
)
|
|
if dir_path:
|
|
self.template_dir_input.setText(dir_path)
|
|
|
|
def load_settings(self):
|
|
"""Load settings from QSettings."""
|
|
# General
|
|
self.enable_vision_cb.setChecked(
|
|
self.settings.value("vision/enabled", True, bool)
|
|
)
|
|
self.auto_process_cb.setChecked(
|
|
self.settings.value("vision/auto_process", False, bool)
|
|
)
|
|
self.icons_dir_input.setText(
|
|
self.settings.value("vision/icons_dir", "", str)
|
|
)
|
|
self.db_dir_input.setText(
|
|
self.settings.value("vision/db_dir", "", str)
|
|
)
|
|
self.extract_text_cb.setChecked(
|
|
self.settings.value("vision/extract_text", True, bool)
|
|
)
|
|
self.extract_icons_cb.setChecked(
|
|
self.settings.value("vision/extract_icons", True, bool)
|
|
)
|
|
self.save_icons_cb.setChecked(
|
|
self.settings.value("vision/save_icons", True, bool)
|
|
)
|
|
self.match_icons_cb.setChecked(
|
|
self.settings.value("vision/match_icons", True, bool)
|
|
)
|
|
|
|
# GPU
|
|
self.use_gpu_cb.setChecked(
|
|
self.settings.value("vision/use_gpu", True, bool)
|
|
)
|
|
backend = self.settings.value("vision/gpu_backend", "auto", str)
|
|
index = self.backend_combo.findData(backend)
|
|
if index >= 0:
|
|
self.backend_combo.setCurrentIndex(index)
|
|
self.batch_size_spin.setValue(
|
|
self.settings.value("vision/batch_size", 1, int)
|
|
)
|
|
self.threads_spin.setValue(
|
|
self.settings.value("vision/threads", 2, int)
|
|
)
|
|
|
|
# OCR
|
|
lang = self.settings.value("vision/ocr_lang", "en", str)
|
|
index = self.ocr_lang_combo.findData(lang)
|
|
if index >= 0:
|
|
self.ocr_lang_combo.setCurrentIndex(index)
|
|
self.multi_lang_cb.setChecked(
|
|
self.settings.value("vision/multi_lang", False, bool)
|
|
)
|
|
self.det_thresh_spin.setValue(
|
|
self.settings.value("vision/det_thresh", 0.3, float)
|
|
)
|
|
self.rec_thresh_spin.setValue(
|
|
self.settings.value("vision/rec_thresh", 0.5, float)
|
|
)
|
|
self.use_angle_cls_cb.setChecked(
|
|
self.settings.value("vision/use_angle_cls", True, bool)
|
|
)
|
|
self.denoise_cb.setChecked(
|
|
self.settings.value("vision/denoise", True, bool)
|
|
)
|
|
self.contrast_enhance_cb.setChecked(
|
|
self.settings.value("vision/contrast_enhance", True, bool)
|
|
)
|
|
|
|
# Icon Detection
|
|
self.auto_detect_window_cb.setChecked(
|
|
self.settings.value("vision/auto_detect_window", True, bool)
|
|
)
|
|
icon_size = self.settings.value("vision/icon_size", "medium", str)
|
|
index = self.icon_size_combo.findData(icon_size)
|
|
if index >= 0:
|
|
self.icon_size_combo.setCurrentIndex(index)
|
|
self.confidence_thresh_spin.setValue(
|
|
self.settings.value("vision/confidence_thresh", 0.7, float)
|
|
)
|
|
self.hash_match_cb.setChecked(
|
|
self.settings.value("vision/hash_match", True, bool)
|
|
)
|
|
self.feature_match_cb.setChecked(
|
|
self.settings.value("vision/feature_match", True, bool)
|
|
)
|
|
self.template_match_cb.setChecked(
|
|
self.settings.value("vision/template_match", True, bool)
|
|
)
|
|
self.match_thresh_spin.setValue(
|
|
self.settings.value("vision/match_thresh", 0.70, float)
|
|
)
|
|
self.template_dir_input.setText(
|
|
self.settings.value("vision/template_dir", "", str)
|
|
)
|
|
|
|
def save_settings(self):
|
|
"""Save settings to QSettings."""
|
|
# General
|
|
self.settings.setValue("vision/enabled", self.enable_vision_cb.isChecked())
|
|
self.settings.setValue("vision/auto_process", self.auto_process_cb.isChecked())
|
|
self.settings.setValue("vision/icons_dir", self.icons_dir_input.text())
|
|
self.settings.setValue("vision/db_dir", self.db_dir_input.text())
|
|
self.settings.setValue("vision/extract_text", self.extract_text_cb.isChecked())
|
|
self.settings.setValue("vision/extract_icons", self.extract_icons_cb.isChecked())
|
|
self.settings.setValue("vision/save_icons", self.save_icons_cb.isChecked())
|
|
self.settings.setValue("vision/match_icons", self.match_icons_cb.isChecked())
|
|
|
|
# GPU
|
|
self.settings.setValue("vision/use_gpu", self.use_gpu_cb.isChecked())
|
|
self.settings.setValue("vision/gpu_backend", self.backend_combo.currentData())
|
|
self.settings.setValue("vision/batch_size", self.batch_size_spin.value())
|
|
self.settings.setValue("vision/threads", self.threads_spin.value())
|
|
|
|
# OCR
|
|
self.settings.setValue("vision/ocr_lang", self.ocr_lang_combo.currentData())
|
|
self.settings.setValue("vision/multi_lang", self.multi_lang_cb.isChecked())
|
|
self.settings.setValue("vision/det_thresh", self.det_thresh_spin.value())
|
|
self.settings.setValue("vision/rec_thresh", self.rec_thresh_spin.value())
|
|
self.settings.setValue("vision/use_angle_cls", self.use_angle_cls_cb.isChecked())
|
|
self.settings.setValue("vision/denoise", self.denoise_cb.isChecked())
|
|
self.settings.setValue("vision/contrast_enhance", self.contrast_enhance_cb.isChecked())
|
|
|
|
# Icon Detection
|
|
self.settings.setValue("vision/auto_detect_window", self.auto_detect_window_cb.isChecked())
|
|
self.settings.setValue("vision/icon_size", self.icon_size_combo.currentData())
|
|
self.settings.setValue("vision/confidence_thresh", self.confidence_thresh_spin.value())
|
|
self.settings.setValue("vision/hash_match", self.hash_match_cb.isChecked())
|
|
self.settings.setValue("vision/feature_match", self.feature_match_cb.isChecked())
|
|
self.settings.setValue("vision/template_match", self.template_match_cb.isChecked())
|
|
self.settings.setValue("vision/match_thresh", self.match_thresh_spin.value())
|
|
self.settings.setValue("vision/template_dir", self.template_dir_input.text())
|
|
|
|
self.settings.sync()
|
|
|
|
self.settings_saved.emit()
|
|
self.accept()
|
|
|
|
logger.info("Vision settings saved")
|
|
|
|
def reset_settings(self):
|
|
"""Reset settings to defaults."""
|
|
reply = QMessageBox.question(
|
|
self, "Reset Settings",
|
|
"Are you sure you want to reset all vision settings to defaults?",
|
|
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
|
|
)
|
|
|
|
if reply == QMessageBox.StandardButton.Yes:
|
|
self.settings.clear()
|
|
self.load_settings()
|
|
QMessageBox.information(self, "Reset Complete",
|
|
"Settings have been reset to defaults.")
|
|
|
|
def open_test_dialog(self):
|
|
"""Open vision test dialog."""
|
|
from .vision_test_dialog import VisionTestDialog
|
|
dialog = VisionTestDialog(self)
|
|
dialog.exec()
|
|
|
|
|
|
# Export
|
|
__all__ = ['VisionSettingsDialog']
|