impr: TabOcr_BuildPHashDatabase

This commit is contained in:
283375 2023-10-10 01:26:20 +08:00
parent 4a1e20a45f
commit 94e4d73a95
Signed by: 283375
SSH Key Fingerprint: SHA256:UcX0qg6ZOSDOeieKPGokA5h7soykG61nz2uxuQgVLSk
6 changed files with 226 additions and 113 deletions

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>tabOcr_BuildPHashDatabase</class> <class>TabOcr_BuildPHashDatabase</class>
<widget class="QWidget" name="tabOcr_BuildPHashDatabase"> <widget class="QWidget" name="TabOcr_BuildPHashDatabase">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -11,7 +11,7 @@
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string notr="true">tabOcr_BuildPHashDatabase</string> <string notr="true">TabOcr_BuildPHashDatabase</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_3"> <layout class="QVBoxLayout" name="verticalLayout_3">
<item> <item>
@ -151,6 +151,16 @@
</item> </item>
</layout> </layout>
</item> </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> <item>
<spacer name="horizontalSpacer_3"> <spacer name="horizontalSpacer_3">
<property name="orientation"> <property name="orientation">
@ -175,7 +185,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QProgressBar" name="progressBar"> <widget class="QProgressBar" name="readImageProgressBar">
<property name="maximum"> <property name="maximum">
<number>0</number> <number>0</number>
</property> </property>
@ -186,7 +196,23 @@
<set>Qt::AlignCenter</set> <set>Qt::AlignCenter</set>
</property> </property>
<property name="format"> <property name="format">
<string notr="true">%v/%m - %p%</string> <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> </property>
</widget> </widget>
</item> </item>

View File

@ -15,25 +15,25 @@ from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QFont, QFontDatabase, QGradient, QIcon, QFont, QFontDatabase, QGradient, QIcon,
QImage, QKeySequence, QLinearGradient, QPainter, QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform) QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QGroupBox, QHBoxLayout, QLabel, from PySide6.QtWidgets import (QApplication, QCheckBox, QGroupBox, QHBoxLayout,
QProgressBar, QPushButton, QSizePolicy, QSpacerItem, QLabel, QProgressBar, QPushButton, QSizePolicy,
QSpinBox, QVBoxLayout, QWidget) QSpacerItem, QSpinBox, QVBoxLayout, QWidget)
from ui.implements.components.fileSelector import FileSelector from ui.implements.components.fileSelector import FileSelector
class Ui_tabOcr_BuildPHashDatabase(object): class Ui_TabOcr_BuildPHashDatabase(object):
def setupUi(self, tabOcr_BuildPHashDatabase): def setupUi(self, TabOcr_BuildPHashDatabase):
if not tabOcr_BuildPHashDatabase.objectName(): if not TabOcr_BuildPHashDatabase.objectName():
tabOcr_BuildPHashDatabase.setObjectName(u"tabOcr_BuildPHashDatabase") TabOcr_BuildPHashDatabase.setObjectName(u"TabOcr_BuildPHashDatabase")
tabOcr_BuildPHashDatabase.resize(632, 551) TabOcr_BuildPHashDatabase.resize(632, 551)
tabOcr_BuildPHashDatabase.setWindowTitle(u"tabOcr_BuildPHashDatabase") TabOcr_BuildPHashDatabase.setWindowTitle(u"TabOcr_BuildPHashDatabase")
self.verticalLayout_3 = QVBoxLayout(tabOcr_BuildPHashDatabase) self.verticalLayout_3 = QVBoxLayout(TabOcr_BuildPHashDatabase)
self.verticalLayout_3.setObjectName(u"verticalLayout_3") self.verticalLayout_3.setObjectName(u"verticalLayout_3")
self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) self.verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
self.verticalLayout_3.addItem(self.verticalSpacer) self.verticalLayout_3.addItem(self.verticalSpacer)
self.groupBox = QGroupBox(tabOcr_BuildPHashDatabase) self.groupBox = QGroupBox(TabOcr_BuildPHashDatabase)
self.groupBox.setObjectName(u"groupBox") self.groupBox.setObjectName(u"groupBox")
self.verticalLayout = QVBoxLayout(self.groupBox) self.verticalLayout = QVBoxLayout(self.groupBox)
self.verticalLayout.setObjectName(u"verticalLayout") self.verticalLayout.setObjectName(u"verticalLayout")
@ -77,7 +77,7 @@ class Ui_tabOcr_BuildPHashDatabase(object):
self.verticalLayout_3.addWidget(self.groupBox) self.verticalLayout_3.addWidget(self.groupBox)
self.groupBox_2 = QGroupBox(tabOcr_BuildPHashDatabase) self.groupBox_2 = QGroupBox(TabOcr_BuildPHashDatabase)
self.groupBox_2.setObjectName(u"groupBox_2") self.groupBox_2.setObjectName(u"groupBox_2")
self.horizontalLayout_3 = QHBoxLayout(self.groupBox_2) self.horizontalLayout_3 = QHBoxLayout(self.groupBox_2)
self.horizontalLayout_3.setObjectName(u"horizontalLayout_3") self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
@ -132,6 +132,12 @@ class Ui_tabOcr_BuildPHashDatabase(object):
self.horizontalLayout_3.addLayout(self.verticalLayout_2) 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.horizontalSpacer_3 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)
self.horizontalLayout_3.addItem(self.horizontalSpacer_3) self.horizontalLayout_3.addItem(self.horizontalSpacer_3)
@ -144,14 +150,21 @@ class Ui_tabOcr_BuildPHashDatabase(object):
self.verticalLayout_3.addWidget(self.groupBox_2) self.verticalLayout_3.addWidget(self.groupBox_2)
self.progressBar = QProgressBar(tabOcr_BuildPHashDatabase) self.readImageProgressBar = QProgressBar(TabOcr_BuildPHashDatabase)
self.progressBar.setObjectName(u"progressBar") self.readImageProgressBar.setObjectName(u"readImageProgressBar")
self.progressBar.setMaximum(0) self.readImageProgressBar.setMaximum(0)
self.progressBar.setValue(0) self.readImageProgressBar.setValue(0)
self.progressBar.setAlignment(Qt.AlignCenter) self.readImageProgressBar.setAlignment(Qt.AlignCenter)
self.progressBar.setFormat(u"%v/%m - %p%")
self.verticalLayout_3.addWidget(self.progressBar) 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 = QHBoxLayout()
self.horizontalLayout_5.setObjectName(u"horizontalLayout_5") self.horizontalLayout_5.setObjectName(u"horizontalLayout_5")
@ -159,7 +172,7 @@ class Ui_tabOcr_BuildPHashDatabase(object):
self.horizontalLayout_5.addItem(self.horizontalSpacer) self.horizontalLayout_5.addItem(self.horizontalSpacer)
self.buildButton = QPushButton(tabOcr_BuildPHashDatabase) self.buildButton = QPushButton(TabOcr_BuildPHashDatabase)
self.buildButton.setObjectName(u"buildButton") self.buildButton.setObjectName(u"buildButton")
self.horizontalLayout_5.addWidget(self.buildButton) self.horizontalLayout_5.addWidget(self.buildButton)
@ -176,18 +189,21 @@ class Ui_tabOcr_BuildPHashDatabase(object):
self.verticalLayout_3.addItem(self.verticalSpacer_2) self.verticalLayout_3.addItem(self.verticalSpacer_2)
self.retranslateUi(tabOcr_BuildPHashDatabase) self.retranslateUi(TabOcr_BuildPHashDatabase)
QMetaObject.connectSlotsByName(tabOcr_BuildPHashDatabase) QMetaObject.connectSlotsByName(TabOcr_BuildPHashDatabase)
# setupUi # setupUi
def retranslateUi(self, tabOcr_BuildPHashDatabase): def retranslateUi(self, TabOcr_BuildPHashDatabase):
self.groupBox.setTitle(QCoreApplication.translate("tabOcr_BuildPHashDatabase", u"folders.title", None)) self.groupBox.setTitle(QCoreApplication.translate("TabOcr_BuildPHashDatabase", u"folders.title", None))
self.label.setText(QCoreApplication.translate("tabOcr_BuildPHashDatabase", u"folders.songDir", 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.label_2.setText(QCoreApplication.translate("TabOcr_BuildPHashDatabase", u"folders.charIconDir", None))
self.groupBox_2.setTitle(QCoreApplication.translate("tabOcr_BuildPHashDatabase", u"options.title", None)) self.groupBox_2.setTitle(QCoreApplication.translate("TabOcr_BuildPHashDatabase", u"options.title", None))
self.optionsResetButton.setText(QCoreApplication.translate("tabOcr_BuildPHashDatabase", u"resetButton", None)) self.preprocessCharIconCheckBox.setText(QCoreApplication.translate("TabOcr_BuildPHashDatabase", u"options.preprocessCharIcon", None))
self.buildButton.setText(QCoreApplication.translate("tabOcr_BuildPHashDatabase", u"buildButton", 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 pass
# retranslateUi # retranslateUi

View File

@ -1,14 +1,29 @@
import sqlite3 import sqlite3
import time import time
from pathlib import Path
from typing import Any, Callable, Optional from typing import Any, Callable, Optional
import cv2 import cv2
import numpy as np
from arcaea_offline_ocr.phash_db import phash_opencv 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( def build_image_phash_database(
images: list[Path], images: list[cv2.Mat],
labels: list[str], labels: list[str],
*, *,
hash_size: int = 16, hash_size: int = 16,
@ -33,9 +48,9 @@ def build_image_phash_database(
image_num = len(images) image_num = len(images)
id_hashes = [] id_hashes = []
for i, label, image_path in zip(range(image_num), labels, images): for i, label, image in zip(range(image_num), labels, images):
image_hash = phash_opencv( image_hash = phash_opencv(
cv2.imread(str(image_path.resolve()), cv2.IMREAD_GRAYSCALE), image,
hash_size=hash_size, hash_size=hash_size,
highfreq_factor=highfreq_factor, highfreq_factor=highfreq_factor,
) )

View File

@ -4,13 +4,15 @@ import sqlite3
import time import time
from pathlib import Path from pathlib import Path
import cv2
from PySide6.QtCore import QThread, Signal, Slot from PySide6.QtCore import QThread, Signal, Slot
from PySide6.QtWidgets import QFileDialog, QMessageBox, QWidget from PySide6.QtWidgets import QFileDialog, QMessageBox, QWidget
from ui.designer.tabs.tabOcr.tabOcr_BuildPHashDatabase_ui import ( from ui.designer.tabs.tabOcr.tabOcr_BuildPHashDatabase_ui import (
Ui_tabOcr_BuildPHashDatabase, Ui_TabOcr_BuildPHashDatabase,
) )
from ui.extends.ocr import build_image_phash_database 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__) logger = logging.getLogger(__name__)
@ -57,11 +59,14 @@ class BuildDatabaseThread(QThread):
self.finished.emit() self.finished.emit()
class TabOcr_BuildPHashDatabase(Ui_tabOcr_BuildPHashDatabase, QWidget): class TabOcr_BuildPHashDatabase(Ui_TabOcr_BuildPHashDatabase, QWidget):
def __init__(self, parent=None): def __init__(self, parent=None):
super().__init__(parent) super().__init__(parent)
self.setupUi(self) self.setupUi(self)
self.languageChangeEventFilter = LanguageChangeEventFilter(self)
self.installEventFilter(self.languageChangeEventFilter)
self.songDirSelector.setMode(self.songDirSelector.getExistingDirectory) self.songDirSelector.setMode(self.songDirSelector.getExistingDirectory)
self.charIconDirSelector.setMode(self.charIconDirSelector.getExistingDirectory) self.charIconDirSelector.setMode(self.charIconDirSelector.getExistingDirectory)
@ -93,11 +98,30 @@ class TabOcr_BuildPHashDatabase(Ui_tabOcr_BuildPHashDatabase, QWidget):
charIconFilePaths = [ charIconFilePaths = [
p for p in Path(charIconDir).glob("**/*") if p.suffix in acceptExts 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] songLabels = [re.sub(r"_.*$", "", p.stem) for p in songFilePaths]
charLabels = [f"character||{p.stem}" for p in charIconFilePaths] charLabels = [f"partner||{p.stem}" for p in charIconFilePaths]
self.databaseBuildThread = BuildDatabaseThread( self.databaseBuildThread = BuildDatabaseThread(
songFilePaths + charIconFilePaths, songLabels + charLabels songMats + charIconMats, songLabels + charLabels
) )
self.databaseBuildThread.progress.connect(self.databaseBuildProgress) self.databaseBuildThread.progress.connect(self.databaseBuildProgress)
self.databaseBuildThread.success.connect(self.databaseBuildSuccess) self.databaseBuildThread.success.connect(self.databaseBuildSuccess)
@ -108,8 +132,8 @@ class TabOcr_BuildPHashDatabase(Ui_tabOcr_BuildPHashDatabase, QWidget):
@Slot(int, int) @Slot(int, int)
def databaseBuildProgress(self, i: int, total: int): def databaseBuildProgress(self, i: int, total: int):
if i < 5: if i < 5:
self.progressBar.setMaximum(total) self.calculateHashProgressBar.setMaximum(total)
self.progressBar.setValue(i) self.calculateHashProgressBar.setValue(i)
@Slot(str) @Slot(str)
def databaseBuildError(self, msg: str): def databaseBuildError(self, msg: str):
@ -133,6 +157,8 @@ class TabOcr_BuildPHashDatabase(Ui_tabOcr_BuildPHashDatabase, QWidget):
def databaseBuildCleanUp(self): def databaseBuildCleanUp(self):
self.databaseBuildThread.deleteLater() self.databaseBuildThread.deleteLater()
self.databaseBuildThread = None self.databaseBuildThread = None
self.progressBar.setMaximum(0) self.readImageProgressBar.setMaximum(0)
self.progressBar.setValue(0) self.readImageProgressBar.setValue(0)
self.calculateHashProgressBar.setMaximum(0)
self.calculateHashProgressBar.setValue(0)
self.buildButton.setEnabled(True) self.buildButton.setEnabled(True)

View File

@ -730,6 +730,54 @@ validation</translation>
<translation>Select Image</translation> <translation>Select Image</translation>
</message> </message>
</context> </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> <context>
<name>TabOcr_Device</name> <name>TabOcr_Device</name>
<message> <message>
@ -1172,37 +1220,4 @@ validation</translation>
<translation>Result (play rating)</translation> <translation>Result (play rating)</translation>
</message> </message>
</context> </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>Character 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="170"/>
<source>resetButton</source>
<translation>Reset</translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui" line="211"/>
<source>buildButton</source>
<translation>Build</translation>
</message>
</context>
</TS> </TS>

View File

@ -729,6 +729,54 @@
<translation></translation> <translation></translation>
</message> </message>
</context> </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> <context>
<name>TabOcr_Device</name> <name>TabOcr_Device</name>
<message> <message>
@ -1171,37 +1219,4 @@
<translation> PTT</translation> <translation> PTT</translation>
</message> </message>
</context> </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="170"/>
<source>resetButton</source>
<translation></translation>
</message>
<message>
<location filename="../../designer/tabs/tabOcr/tabOcr_BuildPHashDatabase.ui" line="211"/>
<source>buildButton</source>
<translation></translation>
</message>
</context>
</TS> </TS>