8 Commits

17 changed files with 1477 additions and 325 deletions

View File

@ -0,0 +1,281 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TabOcr_BuildPHashDatabase</class>
<widget class="QWidget" name="TabOcr_BuildPHashDatabase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>632</width>
<height>551</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">TabOcr_BuildPHashDatabase</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>folders.title</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>folders.songDir</string>
</property>
</widget>
</item>
<item>
<widget class="FileSelector" name="songDirSelector" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>folders.charIconDir</string>
</property>
</widget>
</item>
<item>
<widget class="FileSelector" name="charIconDirSelector" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>options.title</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string notr="true">hash_size</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="hashSizeSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimum">
<number>2</number>
</property>
<property name="maximum">
<number>64</number>
</property>
<property name="value">
<number>16</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string notr="true">highfreq_factor</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="highfreqFactorSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum">
<number>32</number>
</property>
<property name="value">
<number>4</number>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="preprocessCharIconCheckBox">
<property name="text">
<string>options.preprocessCharIcon</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="optionsResetButton">
<property name="text">
<string>resetButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QProgressBar" name="readImageProgressBar">
<property name="maximum">
<number>0</number>
</property>
<property name="value">
<number>0</number>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="format">
<string>[Reading images] %v/%m - %p%</string>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="calculateHashProgressBar">
<property name="maximum">
<number>0</number>
</property>
<property name="value">
<number>0</number>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="format">
<string>[Calculate hashes] %v/%m - %p%</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="buildButton">
<property name="text">
<string>buildButton</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>FileSelector</class>
<extends>QWidget</extends>
<header>ui.implements.components.fileSelector</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,209 @@
# -*- coding: utf-8 -*-
################################################################################
## Form generated from reading UI file 'tabOcr_BuildPHashDatabase.ui'
##
## Created by: Qt User Interface Compiler version 6.5.2
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
QMetaObject, QObject, QPoint, QRect,
QSize, QTime, QUrl, Qt)
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QFont, QFontDatabase, QGradient, QIcon,
QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QCheckBox, QGroupBox, QHBoxLayout,
QLabel, QProgressBar, QPushButton, QSizePolicy,
QSpacerItem, QSpinBox, QVBoxLayout, QWidget)
from ui.implements.components.fileSelector import FileSelector
class Ui_TabOcr_BuildPHashDatabase(object):
def setupUi(self, TabOcr_BuildPHashDatabase):
if not TabOcr_BuildPHashDatabase.objectName():
TabOcr_BuildPHashDatabase.setObjectName(u"TabOcr_BuildPHashDatabase")
TabOcr_BuildPHashDatabase.resize(632, 551)
TabOcr_BuildPHashDatabase.setWindowTitle(u"TabOcr_BuildPHashDatabase")
self.verticalLayout_3 = QVBoxLayout(TabOcr_BuildPHashDatabase)
self.verticalLayout_3.setObjectName(u"verticalLayout_3")
self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
self.verticalLayout_3.addItem(self.verticalSpacer)
self.groupBox = QGroupBox(TabOcr_BuildPHashDatabase)
self.groupBox.setObjectName(u"groupBox")
self.verticalLayout = QVBoxLayout(self.groupBox)
self.verticalLayout.setObjectName(u"verticalLayout")
self.horizontalLayout = QHBoxLayout()
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.label = QLabel(self.groupBox)
self.label.setObjectName(u"label")
self.horizontalLayout.addWidget(self.label)
self.songDirSelector = FileSelector(self.groupBox)
self.songDirSelector.setObjectName(u"songDirSelector")
sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.songDirSelector.sizePolicy().hasHeightForWidth())
self.songDirSelector.setSizePolicy(sizePolicy)
self.horizontalLayout.addWidget(self.songDirSelector)
self.verticalLayout.addLayout(self.horizontalLayout)
self.horizontalLayout_2 = QHBoxLayout()
self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
self.label_2 = QLabel(self.groupBox)
self.label_2.setObjectName(u"label_2")
self.horizontalLayout_2.addWidget(self.label_2)
self.charIconDirSelector = FileSelector(self.groupBox)
self.charIconDirSelector.setObjectName(u"charIconDirSelector")
sizePolicy.setHeightForWidth(self.charIconDirSelector.sizePolicy().hasHeightForWidth())
self.charIconDirSelector.setSizePolicy(sizePolicy)
self.horizontalLayout_2.addWidget(self.charIconDirSelector)
self.verticalLayout.addLayout(self.horizontalLayout_2)
self.verticalLayout_3.addWidget(self.groupBox)
self.groupBox_2 = QGroupBox(TabOcr_BuildPHashDatabase)
self.groupBox_2.setObjectName(u"groupBox_2")
self.horizontalLayout_3 = QHBoxLayout(self.groupBox_2)
self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
self.verticalLayout_2 = QVBoxLayout()
self.verticalLayout_2.setObjectName(u"verticalLayout_2")
self.horizontalLayout_6 = QHBoxLayout()
self.horizontalLayout_6.setObjectName(u"horizontalLayout_6")
self.label_3 = QLabel(self.groupBox_2)
self.label_3.setObjectName(u"label_3")
self.label_3.setText(u"hash_size")
self.label_3.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
self.horizontalLayout_6.addWidget(self.label_3)
self.hashSizeSpinBox = QSpinBox(self.groupBox_2)
self.hashSizeSpinBox.setObjectName(u"hashSizeSpinBox")
sizePolicy1 = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed)
sizePolicy1.setHorizontalStretch(0)
sizePolicy1.setVerticalStretch(0)
sizePolicy1.setHeightForWidth(self.hashSizeSpinBox.sizePolicy().hasHeightForWidth())
self.hashSizeSpinBox.setSizePolicy(sizePolicy1)
self.hashSizeSpinBox.setMinimum(2)
self.hashSizeSpinBox.setMaximum(64)
self.hashSizeSpinBox.setValue(16)
self.horizontalLayout_6.addWidget(self.hashSizeSpinBox)
self.verticalLayout_2.addLayout(self.horizontalLayout_6)
self.horizontalLayout_7 = QHBoxLayout()
self.horizontalLayout_7.setObjectName(u"horizontalLayout_7")
self.label_4 = QLabel(self.groupBox_2)
self.label_4.setObjectName(u"label_4")
self.label_4.setText(u"highfreq_factor")
self.label_4.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
self.horizontalLayout_7.addWidget(self.label_4)
self.highfreqFactorSpinBox = QSpinBox(self.groupBox_2)
self.highfreqFactorSpinBox.setObjectName(u"highfreqFactorSpinBox")
sizePolicy1.setHeightForWidth(self.highfreqFactorSpinBox.sizePolicy().hasHeightForWidth())
self.highfreqFactorSpinBox.setSizePolicy(sizePolicy1)
self.highfreqFactorSpinBox.setMaximum(32)
self.highfreqFactorSpinBox.setValue(4)
self.horizontalLayout_7.addWidget(self.highfreqFactorSpinBox)
self.verticalLayout_2.addLayout(self.horizontalLayout_7)
self.horizontalLayout_3.addLayout(self.verticalLayout_2)
self.preprocessCharIconCheckBox = QCheckBox(self.groupBox_2)
self.preprocessCharIconCheckBox.setObjectName(u"preprocessCharIconCheckBox")
self.preprocessCharIconCheckBox.setChecked(True)
self.horizontalLayout_3.addWidget(self.preprocessCharIconCheckBox)
self.horizontalSpacer_3 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
self.horizontalLayout_3.addItem(self.horizontalSpacer_3)
self.optionsResetButton = QPushButton(self.groupBox_2)
self.optionsResetButton.setObjectName(u"optionsResetButton")
self.horizontalLayout_3.addWidget(self.optionsResetButton)
self.verticalLayout_3.addWidget(self.groupBox_2)
self.readImageProgressBar = QProgressBar(TabOcr_BuildPHashDatabase)
self.readImageProgressBar.setObjectName(u"readImageProgressBar")
self.readImageProgressBar.setMaximum(0)
self.readImageProgressBar.setValue(0)
self.readImageProgressBar.setAlignment(Qt.AlignCenter)
self.verticalLayout_3.addWidget(self.readImageProgressBar)
self.calculateHashProgressBar = QProgressBar(TabOcr_BuildPHashDatabase)
self.calculateHashProgressBar.setObjectName(u"calculateHashProgressBar")
self.calculateHashProgressBar.setMaximum(0)
self.calculateHashProgressBar.setValue(0)
self.calculateHashProgressBar.setAlignment(Qt.AlignCenter)
self.verticalLayout_3.addWidget(self.calculateHashProgressBar)
self.horizontalLayout_5 = QHBoxLayout()
self.horizontalLayout_5.setObjectName(u"horizontalLayout_5")
self.horizontalSpacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
self.horizontalLayout_5.addItem(self.horizontalSpacer)
self.buildButton = QPushButton(TabOcr_BuildPHashDatabase)
self.buildButton.setObjectName(u"buildButton")
self.horizontalLayout_5.addWidget(self.buildButton)
self.horizontalSpacer_2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
self.horizontalLayout_5.addItem(self.horizontalSpacer_2)
self.verticalLayout_3.addLayout(self.horizontalLayout_5)
self.verticalSpacer_2 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
self.verticalLayout_3.addItem(self.verticalSpacer_2)
self.retranslateUi(TabOcr_BuildPHashDatabase)
QMetaObject.connectSlotsByName(TabOcr_BuildPHashDatabase)
# setupUi
def retranslateUi(self, TabOcr_BuildPHashDatabase):
self.groupBox.setTitle(QCoreApplication.translate("TabOcr_BuildPHashDatabase", u"folders.title", None))
self.label.setText(QCoreApplication.translate("TabOcr_BuildPHashDatabase", u"folders.songDir", None))
self.label_2.setText(QCoreApplication.translate("TabOcr_BuildPHashDatabase", u"folders.charIconDir", None))
self.groupBox_2.setTitle(QCoreApplication.translate("TabOcr_BuildPHashDatabase", u"options.title", None))
self.preprocessCharIconCheckBox.setText(QCoreApplication.translate("TabOcr_BuildPHashDatabase", u"options.preprocessCharIcon", None))
self.optionsResetButton.setText(QCoreApplication.translate("TabOcr_BuildPHashDatabase", u"resetButton", None))
self.readImageProgressBar.setFormat(QCoreApplication.translate("TabOcr_BuildPHashDatabase", u"[Reading images] %v/%m - %p%", None))
self.calculateHashProgressBar.setFormat(QCoreApplication.translate("TabOcr_BuildPHashDatabase", u"[Calculate hashes] %v/%m - %p%", None))
self.buildButton.setText(QCoreApplication.translate("TabOcr_BuildPHashDatabase", u"buildButton", None))
pass
# retranslateUi

View File

@ -24,45 +24,37 @@
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>deviceSelector.title</string>
<string>options.title</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QCheckBox" name="deviceUseAutoFactorCheckBox">
<widget class="QCheckBox" name="options_usePresetCheckBox">
<property name="text">
<string>deviceSelector.useAutoFactor</string>
<string>options.usePreset</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="deviceSizesV2CheckBox">
<property name="text">
<string notr="true">SizesV2</string>
<widget class="QComboBox" name="options_presetComboBox">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="FileSelector" name="deviceFileSelector" native="true"/>
</item>
<item>
<widget class="DevicesComboBox" name="deviceComboBox"/>
</item>
</layout>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="horizontalWidget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<widget class="QWidget" name="options_preciseControlWidget" native="true">
<layout class="QGridLayout" name="gridLayout_2" columnstretch="0,1,0">
<property name="leftMargin">
<number>0</number>
</property>
@ -75,24 +67,22 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="groupBox_6">
<property name="title">
<string>knnModelSelector.title</string>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>options.rois</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="FileSelector" name="knnModelSelector" native="true"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QStackedWidget" name="deviceDependenciesStackedWidget">
<item row="0" column="1">
<widget class="QStackedWidget" name="options_roisStackedWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="deviceV1">
<widget class="QWidget" name="page">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>0</number>
@ -107,20 +97,11 @@
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>tesseractSelector.title</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="FileSelector" name="tesseractFileSelector" native="true"/>
<widget class="QComboBox" name="options_roisComboBox"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="deviceV2">
<widget class="QWidget" name="page_2">
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="leftMargin">
<number>0</number>
@ -135,19 +116,145 @@
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="groupBox_5">
<property name="title">
<string>phashDatabaseSelector.title</string>
<widget class="FileSelector" name="options_roisCustomSelector" native="true"/>
</item>
</layout>
</widget>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>options.masker</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QCheckBox" name="options_roisUseCustomCheckBox">
<property name="text">
<string>options.useCustom</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="options_maskerUseCustomCheckBox">
<property name="text">
<string>options.useCustom</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QStackedWidget" name="options_maskerStackedWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="page_3">
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="FileSelector" name="phashDatabaseSelector" native="true"/>
<widget class="QComboBox" name="options_maskerComboBox"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_4">
<layout class="QVBoxLayout" name="verticalLayout_6">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="FileSelector" name="options_maskerCustomSelector" native="true"/>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>dependencies.title</string>
</property>
<layout class="QGridLayout" name="gridLayout" columnstretch="0,0,0,0,1">
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>dependencies.knnModel</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="dependencies_knnModelStatusLabel">
<property name="text">
<string notr="true">...</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="dependencies_phashDatabaseStatusLabel">
<property name="text">
<string notr="true">...</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="FileSelector" name="dependencies_phashDatabaseSelector" native="true"/>
</item>
<item row="0" column="1" rowspan="2">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="FileSelector" name="dependencies_knnModelSelector" native="true"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>dependencies.phashDatabase</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="3" rowspan="2">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
</layout>
@ -178,12 +285,24 @@
<header>ui.implements.components.ocrQueue</header>
<container>1</container>
</customwidget>
<customwidget>
<class>DevicesComboBox</class>
<extends>QComboBox</extends>
<header>ui.implements.components.devicesComboBox</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
<connections>
<connection>
<sender>options_usePresetCheckBox</sender>
<signal>toggled(bool)</signal>
<receiver>options_presetComboBox</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>82</x>
<y>111</y>
</hint>
<hint type="destinationlabel">
<x>82</x>
<y>175</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -15,11 +15,11 @@ from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QFont, QFontDatabase, QGradient, QIcon,
QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QCheckBox, QGroupBox, QHBoxLayout,
from PySide6.QtWidgets import (QApplication, QCheckBox, QComboBox, QFrame,
QGridLayout, QGroupBox, QHBoxLayout, QLabel,
QPushButton, QSizePolicy, QStackedWidget, QVBoxLayout,
QWidget)
from ui.implements.components.devicesComboBox import DevicesComboBox
from ui.implements.components.fileSelector import FileSelector
from ui.implements.components.ocrQueue import OcrQueue
@ -38,117 +38,191 @@ class Ui_TabOcr_Device(object):
self.groupBox = QGroupBox(TabOcr_Device)
self.groupBox.setObjectName(u"groupBox")
self.verticalLayout = QVBoxLayout(self.groupBox)
self.verticalLayout.setObjectName(u"verticalLayout")
self.horizontalLayout = QHBoxLayout()
self.horizontalLayout = QHBoxLayout(self.groupBox)
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.deviceUseAutoFactorCheckBox = QCheckBox(self.groupBox)
self.deviceUseAutoFactorCheckBox.setObjectName(u"deviceUseAutoFactorCheckBox")
self.verticalLayout = QVBoxLayout()
self.verticalLayout.setObjectName(u"verticalLayout")
self.options_usePresetCheckBox = QCheckBox(self.groupBox)
self.options_usePresetCheckBox.setObjectName(u"options_usePresetCheckBox")
self.horizontalLayout.addWidget(self.deviceUseAutoFactorCheckBox)
self.verticalLayout.addWidget(self.options_usePresetCheckBox)
self.deviceSizesV2CheckBox = QCheckBox(self.groupBox)
self.deviceSizesV2CheckBox.setObjectName(u"deviceSizesV2CheckBox")
self.deviceSizesV2CheckBox.setText(u"SizesV2")
self.options_presetComboBox = QComboBox(self.groupBox)
self.options_presetComboBox.setObjectName(u"options_presetComboBox")
self.options_presetComboBox.setEnabled(False)
self.horizontalLayout.addWidget(self.deviceSizesV2CheckBox)
self.verticalLayout.addWidget(self.options_presetComboBox)
self.verticalLayout.addLayout(self.horizontalLayout)
self.horizontalLayout.addLayout(self.verticalLayout)
self.deviceFileSelector = FileSelector(self.groupBox)
self.deviceFileSelector.setObjectName(u"deviceFileSelector")
self.line_3 = QFrame(self.groupBox)
self.line_3.setObjectName(u"line_3")
self.line_3.setFrameShape(QFrame.VLine)
self.line_3.setFrameShadow(QFrame.Sunken)
self.verticalLayout.addWidget(self.deviceFileSelector)
self.horizontalLayout.addWidget(self.line_3)
self.deviceComboBox = DevicesComboBox(self.groupBox)
self.deviceComboBox.setObjectName(u"deviceComboBox")
self.options_preciseControlWidget = QWidget(self.groupBox)
self.options_preciseControlWidget.setObjectName(u"options_preciseControlWidget")
self.gridLayout_2 = QGridLayout(self.options_preciseControlWidget)
self.gridLayout_2.setObjectName(u"gridLayout_2")
self.gridLayout_2.setContentsMargins(0, 0, 0, 0)
self.label = QLabel(self.options_preciseControlWidget)
self.label.setObjectName(u"label")
self.label.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
self.verticalLayout.addWidget(self.deviceComboBox)
self.gridLayout_2.addWidget(self.label, 0, 0, 1, 1)
self.options_roisStackedWidget = QStackedWidget(self.options_preciseControlWidget)
self.options_roisStackedWidget.setObjectName(u"options_roisStackedWidget")
self.page = QWidget()
self.page.setObjectName(u"page")
self.verticalLayout_2 = QVBoxLayout(self.page)
self.verticalLayout_2.setObjectName(u"verticalLayout_2")
self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
self.options_roisComboBox = QComboBox(self.page)
self.options_roisComboBox.setObjectName(u"options_roisComboBox")
self.verticalLayout_2.addWidget(self.options_roisComboBox)
self.options_roisStackedWidget.addWidget(self.page)
self.page_2 = QWidget()
self.page_2.setObjectName(u"page_2")
self.verticalLayout_4 = QVBoxLayout(self.page_2)
self.verticalLayout_4.setObjectName(u"verticalLayout_4")
self.verticalLayout_4.setContentsMargins(0, 0, 0, 0)
self.options_roisCustomSelector = FileSelector(self.page_2)
self.options_roisCustomSelector.setObjectName(u"options_roisCustomSelector")
self.verticalLayout_4.addWidget(self.options_roisCustomSelector)
self.options_roisStackedWidget.addWidget(self.page_2)
self.gridLayout_2.addWidget(self.options_roisStackedWidget, 0, 1, 1, 1)
self.label_2 = QLabel(self.options_preciseControlWidget)
self.label_2.setObjectName(u"label_2")
self.label_2.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
self.gridLayout_2.addWidget(self.label_2, 1, 0, 1, 1)
self.options_roisUseCustomCheckBox = QCheckBox(self.options_preciseControlWidget)
self.options_roisUseCustomCheckBox.setObjectName(u"options_roisUseCustomCheckBox")
self.gridLayout_2.addWidget(self.options_roisUseCustomCheckBox, 0, 2, 1, 1)
self.options_maskerUseCustomCheckBox = QCheckBox(self.options_preciseControlWidget)
self.options_maskerUseCustomCheckBox.setObjectName(u"options_maskerUseCustomCheckBox")
self.gridLayout_2.addWidget(self.options_maskerUseCustomCheckBox, 1, 2, 1, 1)
self.options_maskerStackedWidget = QStackedWidget(self.options_preciseControlWidget)
self.options_maskerStackedWidget.setObjectName(u"options_maskerStackedWidget")
self.page_3 = QWidget()
self.page_3.setObjectName(u"page_3")
self.verticalLayout_5 = QVBoxLayout(self.page_3)
self.verticalLayout_5.setObjectName(u"verticalLayout_5")
self.verticalLayout_5.setContentsMargins(0, 0, 0, 0)
self.options_maskerComboBox = QComboBox(self.page_3)
self.options_maskerComboBox.setObjectName(u"options_maskerComboBox")
self.verticalLayout_5.addWidget(self.options_maskerComboBox)
self.options_maskerStackedWidget.addWidget(self.page_3)
self.page_4 = QWidget()
self.page_4.setObjectName(u"page_4")
self.verticalLayout_6 = QVBoxLayout(self.page_4)
self.verticalLayout_6.setObjectName(u"verticalLayout_6")
self.verticalLayout_6.setContentsMargins(0, 0, 0, 0)
self.options_maskerCustomSelector = FileSelector(self.page_4)
self.options_maskerCustomSelector.setObjectName(u"options_maskerCustomSelector")
self.verticalLayout_6.addWidget(self.options_maskerCustomSelector)
self.options_maskerStackedWidget.addWidget(self.page_4)
self.gridLayout_2.addWidget(self.options_maskerStackedWidget, 1, 1, 1, 1)
self.gridLayout_2.setColumnStretch(1, 1)
self.horizontalLayout.addWidget(self.options_preciseControlWidget)
self.verticalLayout_3.addWidget(self.groupBox)
self.horizontalWidget = QWidget(TabOcr_Device)
self.horizontalWidget.setObjectName(u"horizontalWidget")
sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.horizontalWidget.sizePolicy().hasHeightForWidth())
self.horizontalWidget.setSizePolicy(sizePolicy)
self.horizontalLayout_2 = QHBoxLayout(self.horizontalWidget)
self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
self.groupBox_6 = QGroupBox(self.horizontalWidget)
self.groupBox_6.setObjectName(u"groupBox_6")
self.verticalLayout_6 = QVBoxLayout(self.groupBox_6)
self.verticalLayout_6.setObjectName(u"verticalLayout_6")
self.knnModelSelector = FileSelector(self.groupBox_6)
self.knnModelSelector.setObjectName(u"knnModelSelector")
self.groupBox_2 = QGroupBox(TabOcr_Device)
self.groupBox_2.setObjectName(u"groupBox_2")
self.gridLayout = QGridLayout(self.groupBox_2)
self.gridLayout.setObjectName(u"gridLayout")
self.label_3 = QLabel(self.groupBox_2)
self.label_3.setObjectName(u"label_3")
self.label_3.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
self.verticalLayout_6.addWidget(self.knnModelSelector)
self.gridLayout.addWidget(self.label_3, 0, 0, 1, 1)
self.dependencies_knnModelStatusLabel = QLabel(self.groupBox_2)
self.dependencies_knnModelStatusLabel.setObjectName(u"dependencies_knnModelStatusLabel")
self.dependencies_knnModelStatusLabel.setText(u"...")
self.horizontalLayout_2.addWidget(self.groupBox_6)
self.gridLayout.addWidget(self.dependencies_knnModelStatusLabel, 0, 2, 1, 1)
self.deviceDependenciesStackedWidget = QStackedWidget(self.horizontalWidget)
self.deviceDependenciesStackedWidget.setObjectName(u"deviceDependenciesStackedWidget")
self.deviceV1 = QWidget()
self.deviceV1.setObjectName(u"deviceV1")
self.verticalLayout_2 = QVBoxLayout(self.deviceV1)
self.verticalLayout_2.setObjectName(u"verticalLayout_2")
self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
self.groupBox_4 = QGroupBox(self.deviceV1)
self.groupBox_4.setObjectName(u"groupBox_4")
self.verticalLayout_5 = QVBoxLayout(self.groupBox_4)
self.verticalLayout_5.setObjectName(u"verticalLayout_5")
self.tesseractFileSelector = FileSelector(self.groupBox_4)
self.tesseractFileSelector.setObjectName(u"tesseractFileSelector")
self.dependencies_phashDatabaseStatusLabel = QLabel(self.groupBox_2)
self.dependencies_phashDatabaseStatusLabel.setObjectName(u"dependencies_phashDatabaseStatusLabel")
self.dependencies_phashDatabaseStatusLabel.setText(u"...")
self.verticalLayout_5.addWidget(self.tesseractFileSelector)
self.gridLayout.addWidget(self.dependencies_phashDatabaseStatusLabel, 1, 2, 1, 1)
self.dependencies_phashDatabaseSelector = FileSelector(self.groupBox_2)
self.dependencies_phashDatabaseSelector.setObjectName(u"dependencies_phashDatabaseSelector")
self.verticalLayout_2.addWidget(self.groupBox_4)
self.gridLayout.addWidget(self.dependencies_phashDatabaseSelector, 1, 4, 1, 1)
self.deviceDependenciesStackedWidget.addWidget(self.deviceV1)
self.deviceV2 = QWidget()
self.deviceV2.setObjectName(u"deviceV2")
self.verticalLayout_4 = QVBoxLayout(self.deviceV2)
self.verticalLayout_4.setObjectName(u"verticalLayout_4")
self.verticalLayout_4.setContentsMargins(0, 0, 0, 0)
self.groupBox_5 = QGroupBox(self.deviceV2)
self.groupBox_5.setObjectName(u"groupBox_5")
self.verticalLayout_7 = QVBoxLayout(self.groupBox_5)
self.verticalLayout_7.setObjectName(u"verticalLayout_7")
self.phashDatabaseSelector = FileSelector(self.groupBox_5)
self.phashDatabaseSelector.setObjectName(u"phashDatabaseSelector")
self.line = QFrame(self.groupBox_2)
self.line.setObjectName(u"line")
self.line.setFrameShape(QFrame.VLine)
self.line.setFrameShadow(QFrame.Sunken)
self.verticalLayout_7.addWidget(self.phashDatabaseSelector)
self.gridLayout.addWidget(self.line, 0, 1, 2, 1)
self.dependencies_knnModelSelector = FileSelector(self.groupBox_2)
self.dependencies_knnModelSelector.setObjectName(u"dependencies_knnModelSelector")
self.verticalLayout_4.addWidget(self.groupBox_5)
self.gridLayout.addWidget(self.dependencies_knnModelSelector, 0, 4, 1, 1)
self.deviceDependenciesStackedWidget.addWidget(self.deviceV2)
self.label_4 = QLabel(self.groupBox_2)
self.label_4.setObjectName(u"label_4")
self.label_4.setAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter)
self.horizontalLayout_2.addWidget(self.deviceDependenciesStackedWidget)
self.gridLayout.addWidget(self.label_4, 1, 0, 1, 1)
self.line_2 = QFrame(self.groupBox_2)
self.line_2.setObjectName(u"line_2")
self.line_2.setFrameShape(QFrame.VLine)
self.line_2.setFrameShadow(QFrame.Sunken)
self.verticalLayout_3.addWidget(self.horizontalWidget)
self.gridLayout.addWidget(self.line_2, 0, 3, 2, 1)
self.gridLayout.setColumnStretch(4, 1)
self.verticalLayout_3.addWidget(self.groupBox_2)
self.ocrQueue = OcrQueue(TabOcr_Device)
self.ocrQueue.setObjectName(u"ocrQueue")
sizePolicy1 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
sizePolicy1.setHorizontalStretch(0)
sizePolicy1.setVerticalStretch(0)
sizePolicy1.setHeightForWidth(self.ocrQueue.sizePolicy().hasHeightForWidth())
self.ocrQueue.setSizePolicy(sizePolicy1)
sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.ocrQueue.sizePolicy().hasHeightForWidth())
self.ocrQueue.setSizePolicy(sizePolicy)
self.verticalLayout_3.addWidget(self.ocrQueue)
self.retranslateUi(TabOcr_Device)
self.options_usePresetCheckBox.toggled.connect(self.options_presetComboBox.setEnabled)
self.deviceDependenciesStackedWidget.setCurrentIndex(0)
self.options_roisStackedWidget.setCurrentIndex(0)
self.options_maskerStackedWidget.setCurrentIndex(0)
QMetaObject.connectSlotsByName(TabOcr_Device)
@ -156,11 +230,15 @@ class Ui_TabOcr_Device(object):
def retranslateUi(self, TabOcr_Device):
self.openWizardButton.setText(QCoreApplication.translate("TabOcr_Device", u"openWizardButton", None))
self.groupBox.setTitle(QCoreApplication.translate("TabOcr_Device", u"deviceSelector.title", None))
self.deviceUseAutoFactorCheckBox.setText(QCoreApplication.translate("TabOcr_Device", u"deviceSelector.useAutoFactor", None))
self.groupBox_6.setTitle(QCoreApplication.translate("TabOcr_Device", u"knnModelSelector.title", None))
self.groupBox_4.setTitle(QCoreApplication.translate("TabOcr_Device", u"tesseractSelector.title", None))
self.groupBox_5.setTitle(QCoreApplication.translate("TabOcr_Device", u"phashDatabaseSelector.title", None))
self.groupBox.setTitle(QCoreApplication.translate("TabOcr_Device", u"options.title", None))
self.options_usePresetCheckBox.setText(QCoreApplication.translate("TabOcr_Device", u"options.usePreset", None))
self.label.setText(QCoreApplication.translate("TabOcr_Device", u"options.rois", None))
self.label_2.setText(QCoreApplication.translate("TabOcr_Device", u"options.masker", None))
self.options_roisUseCustomCheckBox.setText(QCoreApplication.translate("TabOcr_Device", u"options.useCustom", None))
self.options_maskerUseCustomCheckBox.setText(QCoreApplication.translate("TabOcr_Device", u"options.useCustom", None))
self.groupBox_2.setTitle(QCoreApplication.translate("TabOcr_Device", u"dependencies.title", None))
self.label_3.setText(QCoreApplication.translate("TabOcr_Device", u"dependencies.knnModel", None))
self.label_4.setText(QCoreApplication.translate("TabOcr_Device", u"dependencies.phashDatabase", None))
pass
# retranslateUi

View File

@ -29,6 +29,11 @@
<string>tab.b30</string>
</attribute>
</widget>
<widget class="TabOcr_BuildPHashDatabase" name="tab_3">
<attribute name="title">
<string>tab.buildPHashDatabase</string>
</attribute>
</widget>
</widget>
</item>
</layout>
@ -46,6 +51,12 @@
<header>ui.implements.tabs.tabOcr.tabOcr_B30</header>
<container>1</container>
</customwidget>
<customwidget>
<class>TabOcr_BuildPHashDatabase</class>
<extends>QWidget</extends>
<header>ui.implements.tabs.tabOcr.tabOcr_BuildPHashDatabase</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>

View File

@ -3,7 +3,7 @@
################################################################################
## Form generated from reading UI file 'tabOcrEntry.ui'
##
## Created by: Qt User Interface Compiler version 6.5.1
## Created by: Qt User Interface Compiler version 6.5.2
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
@ -19,6 +19,7 @@ from PySide6.QtWidgets import (QApplication, QSizePolicy, QTabWidget, QVBoxLayou
QWidget)
from ui.implements.tabs.tabOcr.tabOcr_B30 import TabOcr_B30
from ui.implements.tabs.tabOcr.tabOcr_BuildPHashDatabase import TabOcr_BuildPHashDatabase
from ui.implements.tabs.tabOcr.tabOcr_Device import TabOcr_Device
class Ui_TabOcrEntry(object):
@ -37,6 +38,9 @@ class Ui_TabOcrEntry(object):
self.tab_2 = TabOcr_B30()
self.tab_2.setObjectName(u"tab_2")
self.tabWidget.addTab(self.tab_2, "")
self.tab_3 = TabOcr_BuildPHashDatabase()
self.tab_3.setObjectName(u"tab_3")
self.tabWidget.addTab(self.tab_3, "")
self.verticalLayout.addWidget(self.tabWidget)
@ -52,6 +56,7 @@ class Ui_TabOcrEntry(object):
def retranslateUi(self, TabOcrEntry):
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), QCoreApplication.translate("TabOcrEntry", u"tab.device", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), QCoreApplication.translate("TabOcrEntry", u"tab.b30", None))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), QCoreApplication.translate("TabOcrEntry", u"tab.buildPHashDatabase", None))
pass
# retranslateUi

View File

@ -1,3 +1,5 @@
from .build_phash import build_image_phash_database
try:
import json

View File

@ -0,0 +1,76 @@
import sqlite3
import time
from typing import Any, Callable, Optional
import cv2
import numpy as np
from arcaea_offline_ocr.phash_db import phash_opencv
def preprocess_char_icon(img_gray: cv2.Mat):
h, w = img_gray.shape[:2]
img = cv2.fillPoly(
img_gray,
[
np.array([[0, 0], [round(w / 2), 0], [0, round(h / 2)]], np.int32),
np.array([[w, 0], [round(w / 2), 0], [w, round(h / 2)]], np.int32),
np.array([[0, h], [round(w / 2), h], [0, round(h / 2)]], np.int32),
np.array([[w, h], [round(w / 2), h], [w, round(h / 2)]], np.int32),
],
(128),
)
return img
def build_image_phash_database(
images: list[cv2.Mat],
labels: list[str],
*,
hash_size: int = 16,
highfreq_factor: int = 4,
progress_func: Optional[Callable[[int, int], Any]] = None,
):
assert len(images) == len(labels)
conn = sqlite3.connect(":memory:", check_same_thread=False)
with conn:
cursor = conn.cursor()
cursor.execute("CREATE TABLE properties (key TEXT, value TEXT)")
cursor.executemany(
"INSERT INTO properties VALUES (?, ?)",
[
("hash_size", hash_size),
("highfreq_factor", highfreq_factor),
],
)
image_num = len(images)
id_hashes = []
for i, label, image in zip(range(image_num), labels, images):
image_hash = phash_opencv(
image,
hash_size=hash_size,
highfreq_factor=highfreq_factor,
)
image_hash_bytes = image_hash.flatten().tobytes()
id_hashes.append([label, image_hash_bytes])
if progress_func:
progress_func(i + 1, image_num)
hash_length = len(id_hashes[0][1])
cursor.execute(f"CREATE TABLE hashes (id TEXT, hash BLOB({hash_length}))")
cursor.executemany(
"INSERT INTO hashes VALUES (?, ?)",
id_hashes,
)
cursor.executemany(
"INSERT INTO properties VALUES (?, ?)",
[("built_timestamp", int(time.time()))],
)
conn.commit()
return conn

View File

@ -1,19 +1,15 @@
from typing import Union
from arcaea_offline.calculate import calculate_score_range
from arcaea_offline.models import Chart, Score
from arcaea_offline.utils.rating import rating_class_to_text
from arcaea_offline.utils.score import score_to_grade_text, zip_score_grade
from arcaea_offline.utils.score import (
clear_type_to_text,
modifier_to_text,
score_to_grade_text,
zip_score_grade,
)
from PySide6.QtCore import QAbstractItemModel, QDateTime, QModelIndex, Qt, Signal
from PySide6.QtGui import QColor, QFont, QLinearGradient
from PySide6.QtWidgets import (
QFrame,
QHBoxLayout,
QLabel,
QPushButton,
QSizePolicy,
QWidget,
)
from PySide6.QtWidgets import QHBoxLayout, QLabel, QPushButton, QSizePolicy, QWidget
from ui.implements.components.scoreEditor import ScoreEditor
@ -27,12 +23,6 @@ class ScoreEditorDelegateWrapper(ScoreEditor):
def __init__(self, parent=None):
super().__init__(parent)
# self.hLine = QFrame(self)
# self.hLine.setFrameShape(QFrame.Shape.HLine)
# self.hLine.setFrameShadow(QFrame.Shadow.Plain)
# self.hLine.setFixedHeight(5)
# self.gridLayout.addWidget(self.hLine, self.gridLayout.rowCount(), 0, -1, -1)
self.delegateHeader = QWidget(self)
self.delegateHeaderHBoxLayout = QHBoxLayout(self.delegateHeader)
self.delegateHeaderHBoxLayout.setContentsMargins(0, 0, 0, 0)
@ -55,7 +45,9 @@ class ScoreEditorDelegateWrapper(ScoreEditor):
text = "Editing "
text += _extra or ""
text += f"score {score.score}"
text += f"<br>(P{score.pure} F{score.far} L{score.lost} | MR{score.max_recall})"
text += (
f"<br>(P{score.pure} F{score.far} L{score.lost} | MR {score.max_recall})"
)
self.editorLabel.setText(text)
@ -111,8 +103,8 @@ class ScoreDelegate(TextSegmentDelegate):
def getTextSegments(self, index, option):
score = self.getScore(index)
chart = self.getChart(index)
if not (isinstance(score, Score) and isinstance(chart, Chart)):
if not isinstance(score, Score):
return [
[
{
@ -128,7 +120,9 @@ class ScoreDelegate(TextSegmentDelegate):
score_font.setPointSize(12)
score_grade_font = QFont(score_font)
score_grade_font.setBold(True)
return [
placeholderColor = option.widget.palette().placeholderText().color()
segments = [
[
{
self.TextRole: score_to_grade_text(score.score),
@ -156,19 +150,47 @@ class ScoreDelegate(TextSegmentDelegate):
self.ColorRole: self.PureFarLostColors[2],
},
{self.TextRole: " | "},
{self.TextRole: f"MAX RECALL {score.max_recall}"},
],
[
{
self.TextRole: QDateTime.fromSecsSinceEpoch(score.date).toString(
"yyyy-MM-dd hh:mm:ss"
)
if score.date
else "-- No Date --"
}
{self.TextRole: f"MR {score.max_recall}"},
],
]
if score.date is not None:
segments.append(
[
{
self.TextRole: QDateTime.fromSecsSinceEpoch(
score.date
).toString("yyyy-MM-dd hh:mm:ss")
}
],
)
else:
segments.append(
[{self.TextRole: "-- No Date --", self.ColorRole: placeholderColor}],
)
modifierClearTypeSegments = []
if score.modifier is not None:
modifierClearTypeSegments.append(
{self.TextRole: modifier_to_text(score.modifier)}
)
else:
modifierClearTypeSegments.append(
{self.TextRole: "Modifier None", self.ColorRole: placeholderColor}
)
modifierClearTypeSegments.append({self.TextRole: ", "})
if score.clear_type is not None:
modifierClearTypeSegments.append(
{self.TextRole: clear_type_to_text(score.clear_type)}
)
else:
modifierClearTypeSegments.append(
{self.TextRole: "Clear Type None", self.ColorRole: placeholderColor}
)
segments.append(modifierClearTypeSegments)
return segments
def paintWarningBackground(self, index: QModelIndex) -> bool:
return True

View File

@ -2,6 +2,7 @@ import base64
import logging
import os
import re
import subprocess
from PySide6.QtCore import QObject, QProcess, QRunnable, QThreadPool, Signal
@ -24,7 +25,12 @@ class AndrealExecuteRunnable(QRunnable):
def run(self):
try:
result = os.popen(f"{self.executePath} {' '.join(self.arguments)}").read()
subp = subprocess.run(
[self.executePath, *self.arguments],
capture_output=True,
encoding="utf-8",
)
result = subp.stdout
b64Result = [s for s in result.split("\n") if s]
imageBytes = base64.b64decode(
re.sub(r"data:image/.*;base64,", "", b64Result[-1])

View File

@ -1,11 +1,10 @@
import logging
import re
from enum import IntEnum
from typing import Literal
from arcaea_offline.database import Database
from arcaea_offline.models import Chart
from PySide6.QtCore import QModelIndex, Qt, Signal, Slot
from PySide6.QtCore import QModelIndex, QSignalMapper, Qt, Signal, Slot
from PySide6.QtWidgets import QCompleter, QWidget
from ui.designer.components.songIdSelector_ui import Ui_SongIdSelector
@ -33,18 +32,22 @@ class SongIdSelector(Ui_SongIdSelector, QWidget):
self.languageChangeEventFilter = LanguageChangeEventFilter(self)
self.installEventFilter(self.languageChangeEventFilter)
self.previousPackageButton.clicked.connect(
lambda: self.quickSwitchSelection("previous", "package")
# quick switch bindings
self.quickSwitchSignalMapper = QSignalMapper(self)
self.previousPackageButton.clicked.connect(self.quickSwitchSignalMapper.map)
self.quickSwitchSignalMapper.setMapping(
self.previousPackageButton, "package||previous"
)
self.previousSongIdButton.clicked.connect(
lambda: self.quickSwitchSelection("previous", "songId")
)
self.nextSongIdButton.clicked.connect(
lambda: self.quickSwitchSelection("next", "songId")
)
self.nextPackageButton.clicked.connect(
lambda: self.quickSwitchSelection("next", "package")
self.nextPackageButton.clicked.connect(self.quickSwitchSignalMapper.map)
self.quickSwitchSignalMapper.setMapping(self.nextPackageButton, "package||next")
self.previousSongIdButton.clicked.connect(self.quickSwitchSignalMapper.map)
self.quickSwitchSignalMapper.setMapping(
self.previousSongIdButton, "songId||previous"
)
self.nextSongIdButton.clicked.connect(self.quickSwitchSignalMapper.map)
self.quickSwitchSignalMapper.setMapping(self.nextSongIdButton, "songId||next")
self.quickSwitchSignalMapper.mappedString.connect(self.quickSwitchSlot)
self.mode = SongIdSelectorMode.SongId
@ -73,12 +76,11 @@ class SongIdSelector(Ui_SongIdSelector, QWidget):
def setMode(self, mode: SongIdSelectorMode):
self.mode = mode
def quickSwitchSelection(
self,
direction: Literal["previous", "next"],
model: Literal["package", "songId"],
):
minIndex = 0
@Slot(str)
def quickSwitchSlot(self, action: str):
model, direction = action.split("||")
minIndex = -1
if model == "package":
maxIndex = self.packComboBox.count() - 1
currentIndex = self.packComboBox.currentIndex() + (
@ -174,7 +176,7 @@ class SongIdSelector(Ui_SongIdSelector, QWidget):
self.songIdComboBox.setCurrentIndex(-1)
@Slot()
def on_packComboBox_activated(self):
def on_packComboBox_currentIndexChanged(self):
self.fillSongIdComboBox()
@Slot(str)

View File

@ -0,0 +1,164 @@
import logging
import re
import sqlite3
import time
from pathlib import Path
import cv2
from PySide6.QtCore import QThread, Signal, Slot
from PySide6.QtWidgets import QFileDialog, QMessageBox, QWidget
from ui.designer.tabs.tabOcr.tabOcr_BuildPHashDatabase_ui import (
Ui_TabOcr_BuildPHashDatabase,
)
from ui.extends.ocr.build_phash import build_image_phash_database, preprocess_char_icon
from ui.extends.shared.language import LanguageChangeEventFilter
logger = logging.getLogger(__name__)
class BuildDatabaseThread(QThread):
conn: sqlite3.Connection
progress = Signal(int, int)
success = Signal()
error = Signal(str)
finished = Signal()
def __init__(
self,
images: list[Path],
labels: list[str],
*,
hashSize: int | None = None,
highfreqFactor: int | None = None,
):
super().__init__()
self.images = images
self.labels = labels
self.hashSize = hashSize
self.highfreqFactor = highfreqFactor
def run(self):
try:
progressFunc = lambda i, total: self.progress.emit(i, total)
kwargsDict = {}
if self.hashSize is not None:
kwargsDict["hash_size"] = self.hashSize
if self.highfreqFactor is not None:
kwargsDict["highfreq_factor"] = self.highfreqFactor
self.conn = build_image_phash_database(
self.images, self.labels, progress_func=progressFunc, **kwargsDict
)
self.success.emit()
except Exception as e:
logger.exception("Error during pHash database build")
self.error.emit(str(e))
finally:
self.finished.emit()
class TabOcr_BuildPHashDatabase(Ui_TabOcr_BuildPHashDatabase, QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.languageChangeEventFilter = LanguageChangeEventFilter(self)
self.installEventFilter(self.languageChangeEventFilter)
self.songDirSelector.setMode(self.songDirSelector.getExistingDirectory)
self.charIconDirSelector.setMode(self.charIconDirSelector.getExistingDirectory)
self.buildButton.clicked.connect(self.databaseBuildStart)
@Slot()
def on_optionsResetButton_clicked(self):
self.hashSizeSpinBox.setValue(16)
self.highfreqFactorSpinBox.setValue(4)
def databaseFileName(self):
return f"image-phash-{int(time.time() * 1000)}.db"
def databaseBuildStart(self):
if not self.songDirSelector.selectedFiles():
QMessageBox.critical(self, None, "Song directory not selected.")
return
if not self.charIconDirSelector.selectedFiles():
QMessageBox.critical(self, None, "Char icon directory not selected.")
return
songDir = self.songDirSelector.selectedFiles()[0]
charIconDir = self.charIconDirSelector.selectedFiles()[0]
acceptExts = [".jpg", ".png"]
songFilePaths = [
p for p in Path(songDir).glob("**/*") if p.suffix in acceptExts
]
charIconFilePaths = [
p for p in Path(charIconDir).glob("**/*") if p.suffix in acceptExts
]
self.readImageProgressBar.setMaximum(
len(songFilePaths) + len(charIconFilePaths)
)
i = 0
songMats = []
charIconMats = []
for image_path in songFilePaths:
songMats.append(cv2.imread(str(image_path.resolve()), cv2.IMREAD_GRAYSCALE))
i += 1
self.readImageProgressBar.setValue(i)
for image_path in charIconFilePaths:
mat = cv2.imread(str(image_path.resolve()), cv2.IMREAD_GRAYSCALE)
if self.preprocessCharIconCheckBox.isChecked():
mat = preprocess_char_icon(mat)
charIconMats.append(mat)
i += 1
self.readImageProgressBar.setValue(i)
songLabels = [re.sub(r"_.*$", "", p.stem) for p in songFilePaths]
charLabels = [f"partner_icon||{p.stem}" for p in charIconFilePaths]
self.databaseBuildThread = BuildDatabaseThread(
songMats + charIconMats, songLabels + charLabels
)
self.databaseBuildThread.progress.connect(self.databaseBuildProgress)
self.databaseBuildThread.success.connect(self.databaseBuildSuccess)
self.databaseBuildThread.error.connect(self.databaseBuildError)
self.buildButton.setEnabled(False)
self.databaseBuildThread.start()
@Slot(int, int)
def databaseBuildProgress(self, i: int, total: int):
if i < 5:
self.calculateHashProgressBar.setMaximum(total)
self.calculateHashProgressBar.setValue(i)
@Slot(str)
def databaseBuildError(self, msg: str):
QMessageBox.critical(self, "Error", msg)
self.databaseBuildCleanUp()
@Slot()
def databaseBuildSuccess(self):
dbMemory = self.databaseBuildThread.conn
dbFileName, _ = QFileDialog.getSaveFileName(self, None, self.databaseFileName())
if not dbFileName:
self.databaseBuildCleanUp()
QMessageBox.information(self, None, "User canceled operation.")
return
dbDisk = sqlite3.connect(dbFileName)
dbMemory.backup(dbDisk)
self.databaseBuildCleanUp()
def databaseBuildCleanUp(self):
self.databaseBuildThread.deleteLater()
self.databaseBuildThread = None
self.readImageProgressBar.setMaximum(0)
self.readImageProgressBar.setValue(0)
self.calculateHashProgressBar.setMaximum(0)
self.calculateHashProgressBar.setValue(0)
self.buildButton.setEnabled(True)

View File

@ -1,31 +1,21 @@
import logging
import cv2
# from arcaea_offline_ocr_device_creation_wizard.implements.wizard import Wizard
from arcaea_offline_ocr.device.v1.definition import DeviceV1
from arcaea_offline_ocr.device.v2.definition import DeviceV2
from arcaea_offline_ocr.phash_db import ImagePHashDatabase
from arcaea_offline_ocr.sift_db import SIFTDatabase
from arcaea_offline_ocr.phash_db import ImagePhashDatabase
from PySide6.QtCore import Qt, Slot
from PySide6.QtWidgets import QApplication, QFileDialog, QWidget
from ui.designer.tabs.tabOcr.tabOcr_Device_ui import Ui_TabOcr_Device
from ui.extends.components.ocrQueue import OcrQueueModel
from ui.extends.shared.language import LanguageChangeEventFilter
from ui.extends.shared.settings import (
DEVICES_JSON_FILE,
KNN_MODEL_FILE,
PHASH_DATABASE_FILE,
TESSERACT_FILE,
Settings,
)
from ui.extends.shared.settings import KNN_MODEL_FILE, PHASH_DATABASE_FILE
from ui.extends.tabs.tabOcr.tabOcr_Device import (
ScoreConverter,
TabDeviceV2AutoRoisOcrRunnable,
TabDeviceV2OcrRunnable,
)
logger = logging.getLogger(__name__)
@ -38,17 +28,36 @@ class TabOcr_Device(Ui_TabOcr_Device, QWidget):
self.languageChangeEventFilter = LanguageChangeEventFilter(self)
self.installEventFilter(self.languageChangeEventFilter)
self.deviceFileSelector.filesSelected.connect(self.deviceFileSelected)
self.knnModelSelector.filesSelected.connect(self.knnModelFileSelected)
self.phashDatabaseSelector.filesSelected.connect(self.phashDatabaseFileSelected)
# connect options checkBoxes & comboBoxes
self.options_roisUseCustomCheckBox.toggled.connect(
lambda useCustom: self.options_roisStackedWidget.setCurrentIndex(
1 if useCustom else 0
)
)
self.options_maskerUseCustomCheckBox.toggled.connect(
lambda useCustom: self.options_maskerStackedWidget.setCurrentIndex(
1 if useCustom else 0
)
)
self.options_usePresetCheckBox.toggled.connect(self.options_setUsePreset)
self.options_presetComboBox.currentIndexChanged.connect(
self.options_presetSelected
)
# fill option values
self.options_fillComboBoxes()
self.dependencies_knnModelSelector.filesSelected.connect(self.knnModelSelected)
self.dependencies_phashDatabaseSelector.filesSelected.connect(
self.phashDatabaseSelected
)
logger.info("Applying settings...")
self.deviceFileSelector.connectSettings(DEVICES_JSON_FILE)
self.knnModelSelector.connectSettings(KNN_MODEL_FILE)
self.tesseractFileSelector.connectSettings(TESSERACT_FILE)
self.phashDatabaseSelector.connectSettings(PHASH_DATABASE_FILE)
settings = Settings()
self.deviceComboBox.selectDevice(settings.deviceUuid())
self.dependencies_knnModelSelector.connectSettings(KNN_MODEL_FILE)
self.dependencies_phashDatabaseSelector.connectSettings(PHASH_DATABASE_FILE)
self.options_usePresetCheckBox.setChecked(True)
self.options_usePresetCheckBox.setEnabled(False)
self.ocrQueueModel = OcrQueueModel(self)
self.ocrQueue.setModel(self.ocrQueueModel)
@ -60,43 +69,70 @@ class TabOcr_Device(Ui_TabOcr_Device, QWidget):
# wizard.open()
pass
@Slot()
def on_deviceUseAutoFactorCheckBox_stateChanged(self):
checkState = self.deviceUseAutoFactorCheckBox.checkState()
if checkState == Qt.CheckState.Checked:
self.deviceDependenciesStackedWidget.setCurrentIndex(1)
self.deviceComboBox.setCurrentIndex(-1)
self.deviceFileSelector.setEnabled(False)
self.deviceComboBox.setEnabled(False)
else:
self.deviceFileSelector.setEnabled(True)
self.deviceComboBox.setEnabled(True)
@Slot(bool)
def options_setUsePreset(self, usePreset: bool):
self.options_roisUseCustomCheckBox.setChecked(not usePreset)
self.options_maskerUseCustomCheckBox.setChecked(not usePreset)
self.options_preciseControlWidget.setEnabled(not usePreset)
if not usePreset:
self.options_presetComboBox.setCurrentIndex(-1)
@Slot()
def on_deviceComboBox_currentIndexChanged(self):
self.changeDeviceDepStackedWidget()
@Slot(int)
def options_presetSelected(self, index: int):
if index < 0:
self.options_roisComboBox.setCurrentIndex(-1)
self.options_maskerComboBox.setCurrentIndex(-1)
def changeDeviceDepStackedWidget(self):
device = self.deviceComboBox.currentData()
if isinstance(device, (DeviceV1, DeviceV2)):
self.deviceDependenciesStackedWidget.setCurrentIndex(device.version - 1)
autoTypeString = self.options_presetComboBox.currentData()
roisAutoTypeIndex = self.options_roisComboBox.findData(autoTypeString)
maskerAutoTypeIndex = self.options_maskerComboBox.findData(autoTypeString)
self.options_roisComboBox.setCurrentIndex(roisAutoTypeIndex)
self.options_maskerComboBox.setCurrentIndex(maskerAutoTypeIndex)
def deviceFileSelected(self):
if selectedFiles := self.deviceFileSelector.selectedFiles():
file = selectedFiles[0]
self.deviceComboBox.loadDevicesJson(file)
def options_fillComboBoxes(self):
self.options_roisComboBox.addItem("RoisAutoT1", "AutoT1")
self.options_roisComboBox.addItem("RoisAutoT2", "AutoT2")
self.options_roisComboBox.setCurrentIndex(-1)
def knnModelFileSelected(self):
if selectedFiles := self.knnModelSelector.selectedFiles():
self.knnModel = cv2.ml.KNearest.load(selectedFiles[0])
self.options_maskerComboBox.addItem("MaskerAutoT1", "AutoT1")
self.options_maskerComboBox.addItem("MaskerAutoT2", "AutoT2")
self.options_maskerComboBox.setCurrentIndex(-1)
def phashDatabaseFileSelected(self):
if selectedFiles := self.phashDatabaseSelector.selectedFiles():
self.phashDatabase = ImagePHashDatabase(selectedFiles[0])
self.options_presetComboBox.addItem("AutoT1 (ver <= 4.7.2)", "AutoT1")
self.options_presetComboBox.addItem("AutoT2 (ver >= 5.0.0)", "AutoT2")
self.options_presetComboBox.setCurrentIndex(1)
def knnModelSelected(self):
try:
knnModelFile = self.dependencies_knnModelSelector.selectedFiles()[0]
self.knnModel = cv2.ml.KNearest.load(knnModelFile)
self.dependencies_knnModelStatusLabel.setText(
f'<font color="green">OK</font>, varCount {self.knnModel.getVarCount()}'
)
except Exception:
logger.exception("Error loading knn model:")
self.dependencies_knnModelStatusLabel.setText(
'<font color="red">Error</font>'
)
def phashDatabaseSelected(self):
try:
phashDbFile = self.dependencies_phashDatabaseSelector.selectedFiles()[0]
self.phashDatabase = ImagePhashDatabase(phashDbFile)
self.dependencies_phashDatabaseStatusLabel.setText(
f'<font color="green">OK</font>, '
f"J{len(self.phashDatabase.jacket_hashes)} "
f"PI{len(self.phashDatabase.partner_icon_hashes)}"
)
except Exception:
logger.exception("Error loading phash database:")
self.dependencies_phashDatabaseStatusLabel.setText(
'<font color="red">Error</font>'
)
@Slot()
def on_ocr_addImageButton_clicked(self):
files, _filter = QFileDialog.getOpenFileNames(
files, _ = QFileDialog.getOpenFileNames(
self, None, "", "Image Files (*.png *.jpg *.jpeg *.bmp *.webp);;*"
)
filesNum = len(files)

View File

@ -180,19 +180,20 @@ class TabTools_Andreal(Ui_TabTools_Andreal, QWidget):
arguments = [
str(self.imageType()),
f'--json-file="{jsonFile}"',
f"--img-version={self.imageVersion()}",
"--json-file",
jsonFile,
"--img-version",
str(self.imageVersion()),
]
if self.andrealFolderSelector.selectedFiles():
arguments.append(
f'--path="{self.andrealFolderSelector.selectedFiles()[0]}"'
)
arguments.append("--path")
arguments.append(self.andrealFolderSelector.selectedFiles()[0])
if preview:
arguments.extend(["--img-format=jpg", "--img-quality=20"])
arguments.extend(["--img-format", "jpg", "--img-quality", "20"])
else:
arguments.append(f"--img-format={self.imageFormat()}")
arguments.extend(["--img-format", self.imageFormat()])
if self.imageFormat() == "jpg":
arguments.append(f"--img-quality={self.jpgQualitySpinBox.value()}")
arguments.extend(["--img-quality", str(self.jpgQualitySpinBox.value())])
return arguments
def getAndrealJsonContent(self):

View File

@ -89,12 +89,12 @@
<translation>Continue</translation>
</message>
<message>
<location filename="../../startup/databaseChecker.py" line="115"/>
<location filename="../../startup/databaseChecker.py" line="117"/>
<source>dialog.tryInitExistingDatabase</source>
<translation>The existing database doesn&apos;t seem to be initialized properly, try initialize again?</translation>
</message>
<message>
<location filename="../../startup/databaseChecker.py" line="131"/>
<location filename="../../startup/databaseChecker.py" line="133"/>
<source>dialog.confirmNewDatabase</source>
<translation>Database file does not exist. Create now?</translation>
</message>
@ -696,6 +696,11 @@ validation</translation>
<source>tab.b30</source>
<translation>B30</translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcrEntry.ui" line="34"/>
<source>tab.buildPHashDatabase</source>
<translation>Build pHash Database</translation>
</message>
</context>
<context>
<name>TabOcr_B30</name>
@ -725,6 +730,54 @@ validation</translation>
<translation>Select Image</translation>
</message>
</context>
<context>
<name>TabOcr_BuildPHashDatabase</name>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui" line="33"/>
<source>folders.title</source>
<translation>Data Folders</translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui" line="41"/>
<source>folders.songDir</source>
<translation>Song jackets</translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui" line="62"/>
<source>folders.charIconDir</source>
<translation>Partner icons</translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui" line="84"/>
<source>options.title</source>
<translation>Options</translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui" line="157"/>
<source>options.preprocessCharIcon</source>
<translation>Preprocess partner icons</translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui" line="180"/>
<source>resetButton</source>
<translation>Reset</translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui" line="199"/>
<source>[Reading images] %v/%m - %p%</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui" line="215"/>
<source>[Calculate hashes] %v/%m - %p%</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui" line="237"/>
<source>buildButton</source>
<translation>Build</translation>
</message>
</context>
<context>
<name>TabOcr_Device</name>
<message>
@ -734,28 +787,44 @@ validation</translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="27"/>
<source>deviceSelector.title</source>
<translation>Select Device</translation>
<source>options.title</source>
<translation>Options</translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="35"/>
<source>deviceSelector.useAutoFactor</source>
<translation>Auto calculate factor</translation>
<source>options.usePreset</source>
<translation>Use preset</translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="81"/>
<source>knnModelSelector.title</source>
<translation>Select KNearest Model</translation>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="73"/>
<source>options.rois</source>
<translation>Rois</translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="112"/>
<source>tesseractSelector.title</source>
<translation>Select tesseract Path</translation>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="128"/>
<source>options.masker</source>
<translation>Masker</translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="140"/>
<source>phashDatabaseSelector.title</source>
<translation>Select Image PHash Database</translation>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="138"/>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="145"/>
<source>options.useCustom</source>
<translation>Use custom options</translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="203"/>
<source>dependencies.title</source>
<translation>OCR Dependencies</translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="209"/>
<source>dependencies.knnModel</source>
<translation>KNearest model</translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="246"/>
<source>dependencies.phashDatabase</source>
<translation>Image pHash database</translation>
</message>
</context>
<context>

View File

@ -89,12 +89,12 @@
<translation></translation>
</message>
<message>
<location filename="../../startup/databaseChecker.py" line="115"/>
<location filename="../../startup/databaseChecker.py" line="117"/>
<source>dialog.tryInitExistingDatabase</source>
<translation></translation>
</message>
<message>
<location filename="../../startup/databaseChecker.py" line="131"/>
<location filename="../../startup/databaseChecker.py" line="133"/>
<source>dialog.confirmNewDatabase</source>
<translation></translation>
</message>
@ -695,6 +695,11 @@
<source>tab.b30</source>
<translation>B30</translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcrEntry.ui" line="34"/>
<source>tab.buildPHashDatabase</source>
<translation> pHash </translation>
</message>
</context>
<context>
<name>TabOcr_B30</name>
@ -724,6 +729,54 @@
<translation></translation>
</message>
</context>
<context>
<name>TabOcr_BuildPHashDatabase</name>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui" line="33"/>
<source>folders.title</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui" line="41"/>
<source>folders.songDir</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui" line="62"/>
<source>folders.charIconDir</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui" line="84"/>
<source>options.title</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui" line="157"/>
<source>options.preprocessCharIcon</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui" line="180"/>
<source>resetButton</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui" line="199"/>
<source>[Reading images] %v/%m - %p%</source>
<translation>[] %v/%m - %p%</translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui" line="215"/>
<source>[Calculate hashes] %v/%m - %p%</source>
<translation>[] %v/%m - %p%</translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui" line="237"/>
<source>buildButton</source>
<translation></translation>
</message>
</context>
<context>
<name>TabOcr_Device</name>
<message>
@ -733,28 +786,44 @@
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="27"/>
<source>deviceSelector.title</source>
<translation></translation>
<source>options.title</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="35"/>
<source>deviceSelector.useAutoFactor</source>
<translation> factor</translation>
<source>options.usePreset</source>
<translation>使</translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="81"/>
<source>knnModelSelector.title</source>
<translation> KNearest </translation>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="73"/>
<source>options.rois</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="112"/>
<source>tesseractSelector.title</source>
<translation> tesseract </translation>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="128"/>
<source>options.masker</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="140"/>
<source>phashDatabaseSelector.title</source>
<translation> PHash </translation>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="138"/>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="145"/>
<source>options.useCustom</source>
<translation>使</translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="203"/>
<source>dependencies.title</source>
<translation>OCR </translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="209"/>
<source>dependencies.knnModel</source>
<translation>KNearest </translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_Device.ui" line="246"/>
<source>dependencies.phashDatabase</source>
<translation> pHash </translation>
</message>
</context>
<context>

View File

@ -74,6 +74,7 @@ class DatabaseChecker(Ui_DatabaseChecker, QDialog):
db = Database(create_engine(dbSqliteUrl))
if db.check_init():
flags |= DatabaseCheckerResult.Initted
self.settings.setDatabaseUrl(self.dbSqliteUrl().toString())
return flags
@ -102,6 +103,7 @@ class DatabaseChecker(Ui_DatabaseChecker, QDialog):
@Slot()
def on_confirmDbPathButton_clicked(self):
dbSqliteUrl = self.dbSqliteUrl()
self.settings.setDatabaseUrl(dbSqliteUrl.toString())
result = self.confirmDb()
if result & DatabaseCheckerResult.Initted: