mirror of
https://github.com/283375/arcaea-offline-pyside-ui.git
synced 2025-07-02 04:46:26 +00:00
Compare commits
4 Commits
v0.3.0b
...
94e4d73a95
Author | SHA1 | Date | |
---|---|---|---|
94e4d73a95
|
|||
4a1e20a45f
|
|||
de8c5d28a7
|
|||
bce48a03a7
|
281
ui/designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui
Normal file
281
ui/designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui
Normal 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>
|
209
ui/designer/tabs/tabOcr/tabOcr_BuildPHashDatabase_ui.py
Normal file
209
ui/designer/tabs/tabOcr/tabOcr_BuildPHashDatabase_ui.py
Normal 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
|
||||
|
@ -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/>
|
||||
|
@ -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
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
from .build_phash import build_image_phash_database
|
||||
|
||||
try:
|
||||
import json
|
||||
|
76
ui/extends/ocr/build_phash.py
Normal file
76
ui/extends/ocr/build_phash.py
Normal 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
|
@ -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])
|
||||
|
164
ui/implements/tabs/tabOcr/tabOcr_BuildPHashDatabase.py
Normal file
164
ui/implements/tabs/tabOcr/tabOcr_BuildPHashDatabase.py
Normal 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||{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)
|
@ -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):
|
||||
|
@ -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'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>
|
||||
|
@ -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>
|
||||
|
@ -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:
|
||||
|
Reference in New Issue
Block a user