wip: ImagePHashDatabase & SizesV2

This commit is contained in:
283375 2023-09-27 17:16:33 +08:00
parent d701055c74
commit 9c06c6d9f1
Signed by: 283375
SSH Key Fingerprint: SHA256:UcX0qg6ZOSDOeieKPGokA5h7soykG61nz2uxuQgVLSk
7 changed files with 363 additions and 315 deletions

View File

@ -59,11 +59,11 @@
<item> <item>
<widget class="QGroupBox" name="groupBox_4"> <widget class="QGroupBox" name="groupBox_4">
<property name="title"> <property name="title">
<string>siftDatabaseSelector.title</string> <string>phashDatabaseSelector.title</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_5"> <layout class="QVBoxLayout" name="verticalLayout_5">
<item> <item>
<widget class="FileSelector" name="siftDatabaseSelector" native="true"/> <widget class="FileSelector" name="phashDatabaseSelector" native="true"/>
</item> </item>
</layout> </layout>
</widget> </widget>

View File

@ -3,7 +3,7 @@
################################################################################ ################################################################################
## Form generated from reading UI file 'tabOcr_B30.ui' ## Form generated from reading UI file 'tabOcr_B30.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! ## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################ ################################################################################
@ -76,10 +76,10 @@ class Ui_TabOcr_B30(object):
self.groupBox_4.setObjectName(u"groupBox_4") self.groupBox_4.setObjectName(u"groupBox_4")
self.verticalLayout_5 = QVBoxLayout(self.groupBox_4) self.verticalLayout_5 = QVBoxLayout(self.groupBox_4)
self.verticalLayout_5.setObjectName(u"verticalLayout_5") self.verticalLayout_5.setObjectName(u"verticalLayout_5")
self.siftDatabaseSelector = FileSelector(self.groupBox_4) self.phashDatabaseSelector = FileSelector(self.groupBox_4)
self.siftDatabaseSelector.setObjectName(u"siftDatabaseSelector") self.phashDatabaseSelector.setObjectName(u"phashDatabaseSelector")
self.verticalLayout_5.addWidget(self.siftDatabaseSelector) self.verticalLayout_5.addWidget(self.phashDatabaseSelector)
self.horizontalLayout_3.addWidget(self.groupBox_4) self.horizontalLayout_3.addWidget(self.groupBox_4)
@ -119,7 +119,7 @@ class Ui_TabOcr_B30(object):
self.groupBox.setTitle(QCoreApplication.translate("TabOcr_B30", u"b30type", None)) self.groupBox.setTitle(QCoreApplication.translate("TabOcr_B30", u"b30type", None))
self.groupBox_3.setTitle(QCoreApplication.translate("TabOcr_B30", u"knnModelSelector.title", None)) self.groupBox_3.setTitle(QCoreApplication.translate("TabOcr_B30", u"knnModelSelector.title", None))
self.groupBox_5.setTitle(QCoreApplication.translate("TabOcr_B30", u"b30KnnModelSelector.title", None)) self.groupBox_5.setTitle(QCoreApplication.translate("TabOcr_B30", u"b30KnnModelSelector.title", None))
self.groupBox_4.setTitle(QCoreApplication.translate("TabOcr_B30", u"siftDatabaseSelector.title", None)) self.groupBox_4.setTitle(QCoreApplication.translate("TabOcr_B30", u"phashDatabaseSelector.title", None))
self.groupBox_2.setTitle(QCoreApplication.translate("TabOcr_B30", u"imageSelector.title", None)) self.groupBox_2.setTitle(QCoreApplication.translate("TabOcr_B30", u"imageSelector.title", None))
pass pass
# retranslateUi # retranslateUi

View File

@ -28,11 +28,22 @@
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<widget class="QCheckBox" name="deviceUseAutoFactorCheckBox"> <layout class="QHBoxLayout" name="horizontalLayout">
<property name="text"> <item>
<string>deviceSelector.useAutoFactor</string> <widget class="QCheckBox" name="deviceUseAutoFactorCheckBox">
</property> <property name="text">
</widget> <string>deviceSelector.useAutoFactor</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="deviceSizesV2CheckBox">
<property name="text">
<string notr="true">SizesV2</string>
</property>
</widget>
</item>
</layout>
</item> </item>
<item> <item>
<widget class="FileSelector" name="deviceFileSelector" native="true"/> <widget class="FileSelector" name="deviceFileSelector" native="true"/>
@ -126,11 +137,11 @@
<item> <item>
<widget class="QGroupBox" name="groupBox_5"> <widget class="QGroupBox" name="groupBox_5">
<property name="title"> <property name="title">
<string>siftDatabaseSelector.title</string> <string>phashDatabaseSelector.title</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_7"> <layout class="QVBoxLayout" name="verticalLayout_7">
<item> <item>
<widget class="FileSelector" name="siftDatabaseSelector" native="true"/> <widget class="FileSelector" name="phashDatabaseSelector" native="true"/>
</item> </item>
</layout> </layout>
</widget> </widget>
@ -161,17 +172,17 @@
<header>ui.implements.components.fileSelector</header> <header>ui.implements.components.fileSelector</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget>
<class>DevicesComboBox</class>
<extends>QComboBox</extends>
<header>ui.implements.components.devicesComboBox</header>
</customwidget>
<customwidget> <customwidget>
<class>OcrQueue</class> <class>OcrQueue</class>
<extends>QWidget</extends> <extends>QWidget</extends>
<header>ui.implements.components.ocrQueue</header> <header>ui.implements.components.ocrQueue</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget>
<class>DevicesComboBox</class>
<extends>QComboBox</extends>
<header>ui.implements.components.devicesComboBox</header>
</customwidget>
</customwidgets> </customwidgets>
<resources/> <resources/>
<connections/> <connections/>

View File

@ -40,10 +40,21 @@ class Ui_TabOcr_Device(object):
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")
self.horizontalLayout = QHBoxLayout()
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.deviceUseAutoFactorCheckBox = QCheckBox(self.groupBox) self.deviceUseAutoFactorCheckBox = QCheckBox(self.groupBox)
self.deviceUseAutoFactorCheckBox.setObjectName(u"deviceUseAutoFactorCheckBox") self.deviceUseAutoFactorCheckBox.setObjectName(u"deviceUseAutoFactorCheckBox")
self.verticalLayout.addWidget(self.deviceUseAutoFactorCheckBox) self.horizontalLayout.addWidget(self.deviceUseAutoFactorCheckBox)
self.deviceSizesV2CheckBox = QCheckBox(self.groupBox)
self.deviceSizesV2CheckBox.setObjectName(u"deviceSizesV2CheckBox")
self.deviceSizesV2CheckBox.setText(u"SizesV2")
self.horizontalLayout.addWidget(self.deviceSizesV2CheckBox)
self.verticalLayout.addLayout(self.horizontalLayout)
self.deviceFileSelector = FileSelector(self.groupBox) self.deviceFileSelector = FileSelector(self.groupBox)
self.deviceFileSelector.setObjectName(u"deviceFileSelector") self.deviceFileSelector.setObjectName(u"deviceFileSelector")
@ -109,10 +120,10 @@ class Ui_TabOcr_Device(object):
self.groupBox_5.setObjectName(u"groupBox_5") self.groupBox_5.setObjectName(u"groupBox_5")
self.verticalLayout_7 = QVBoxLayout(self.groupBox_5) self.verticalLayout_7 = QVBoxLayout(self.groupBox_5)
self.verticalLayout_7.setObjectName(u"verticalLayout_7") self.verticalLayout_7.setObjectName(u"verticalLayout_7")
self.siftDatabaseSelector = FileSelector(self.groupBox_5) self.phashDatabaseSelector = FileSelector(self.groupBox_5)
self.siftDatabaseSelector.setObjectName(u"siftDatabaseSelector") self.phashDatabaseSelector.setObjectName(u"phashDatabaseSelector")
self.verticalLayout_7.addWidget(self.siftDatabaseSelector) self.verticalLayout_7.addWidget(self.phashDatabaseSelector)
self.verticalLayout_4.addWidget(self.groupBox_5) self.verticalLayout_4.addWidget(self.groupBox_5)
@ -149,7 +160,7 @@ class Ui_TabOcr_Device(object):
self.deviceUseAutoFactorCheckBox.setText(QCoreApplication.translate("TabOcr_Device", u"deviceSelector.useAutoFactor", 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_6.setTitle(QCoreApplication.translate("TabOcr_Device", u"knnModelSelector.title", None))
self.groupBox_4.setTitle(QCoreApplication.translate("TabOcr_Device", u"tesseractSelector.title", None)) self.groupBox_4.setTitle(QCoreApplication.translate("TabOcr_Device", u"tesseractSelector.title", None))
self.groupBox_5.setTitle(QCoreApplication.translate("TabOcr_Device", u"siftDatabaseSelector.title", None)) self.groupBox_5.setTitle(QCoreApplication.translate("TabOcr_Device", u"phashDatabaseSelector.title", None))
pass pass
# retranslateUi # retranslateUi

View File

@ -5,8 +5,8 @@ from typing import Tuple
from arcaea_offline.database import Database from arcaea_offline.database import Database
from arcaea_offline.models import Chart, Score from arcaea_offline.models import Chart, Score
from arcaea_offline_ocr.device.shared import DeviceOcrResult from arcaea_offline_ocr.device.shared import DeviceOcrResult
from arcaea_offline_ocr.device.v2.ocr import DeviceV2Ocr from arcaea_offline_ocr.device.v2 import DeviceV2AutoRois, DeviceV2Ocr, DeviceV2Rois
from arcaea_offline_ocr.device.v2.rois import DeviceV2AutoRois, DeviceV2Rois from arcaea_offline_ocr.device.v2.sizes import SizesV1, SizesV2
from arcaea_offline_ocr.utils import imread_unicode from arcaea_offline_ocr.utils import imread_unicode
from PySide6.QtCore import QDateTime, QFileInfo from PySide6.QtCore import QDateTime, QFileInfo
@ -18,17 +18,23 @@ import exif
class TabDeviceV2OcrRunnable(OcrRunnable): class TabDeviceV2OcrRunnable(OcrRunnable):
def __init__(self, imagePath, device, knnModel, siftDb): def __init__(self, imagePath, device, knnModel, phashDb, *, sizesV2: bool):
super().__init__() super().__init__()
self.imagePath = imagePath self.imagePath = imagePath
self.device = device self.device = device
self.knnModel = knnModel self.knnModel = knnModel
self.siftDb = siftDb self.phashDb = phashDb
self.sizesV2 = sizesV2
def run(self): def run(self):
try: try:
rois = DeviceV2Rois(self.device, imread_unicode(self.imagePath)) rois = DeviceV2Rois(self.device, imread_unicode(self.imagePath))
ocr = DeviceV2Ocr(self.knnModel, self.siftDb) rois.sizes = (
SizesV2(self.device.factor)
if self.sizesV2
else SizesV1(self.device.factor)
)
ocr = DeviceV2Ocr(self.knnModel, self.phashDb)
result = ocr.ocr(rois) result = ocr.ocr(rois)
self.signals.resultReady.emit(result) self.signals.resultReady.emit(result)
except Exception: except Exception:
@ -38,16 +44,19 @@ class TabDeviceV2OcrRunnable(OcrRunnable):
class TabDeviceV2AutoRoisOcrRunnable(OcrRunnable): class TabDeviceV2AutoRoisOcrRunnable(OcrRunnable):
def __init__(self, imagePath, knnModel, siftDb): def __init__(self, imagePath, knnModel, phashDb, *, sizesV2: bool):
super().__init__() super().__init__()
self.imagePath = imagePath self.imagePath = imagePath
self.knnModel = knnModel self.knnModel = knnModel
self.siftDb = siftDb self.phashDb = phashDb
self.sizesV2 = sizesV2
def run(self): def run(self):
try: try:
rois = DeviceV2AutoRois(imread_unicode(self.imagePath)) rois = DeviceV2AutoRois(imread_unicode(self.imagePath))
ocr = DeviceV2Ocr(self.knnModel, self.siftDb) factor = rois.sizes.factor
rois.sizes = SizesV2(factor) if self.sizesV2 else SizesV1(factor)
ocr = DeviceV2Ocr(self.knnModel, self.phashDb)
result = ocr.ocr(rois) result = ocr.ocr(rois)
self.signals.resultReady.emit(result) self.signals.resultReady.emit(result)
except Exception: except Exception:

View File

@ -2,6 +2,7 @@ import logging
import cv2 import cv2
from arcaea_offline_ocr.b30.chieri.v4.ocr import ChieriBotV4Ocr from arcaea_offline_ocr.b30.chieri.v4.ocr import ChieriBotV4Ocr
from arcaea_offline_ocr.phash_db import ImagePHashDatabase
from arcaea_offline_ocr.sift_db import SIFTDatabase from arcaea_offline_ocr.sift_db import SIFTDatabase
from arcaea_offline_ocr.utils import imread_unicode from arcaea_offline_ocr.utils import imread_unicode
from PySide6.QtCore import Signal, Slot from PySide6.QtCore import Signal, Slot
@ -34,10 +35,11 @@ class TabOcr_B30(Ui_TabOcr_B30, QWidget):
self.imageSelector.filesSelected.connect(self.imageSelected) self.imageSelector.filesSelected.connect(self.imageSelected)
self.knnModelSelector.filesSelected.connect(self.knnModelSelected) self.knnModelSelector.filesSelected.connect(self.knnModelSelected)
self.b30KnnModelSelector.filesSelected.connect(self.b30KnnModelSelected) self.b30KnnModelSelector.filesSelected.connect(self.b30KnnModelSelected)
self.siftDatabaseSelector.filesSelected.connect(self.siftDatabaseSelected) # self.siftDatabaseSelector.filesSelected.connect(self.siftDatabaseSelected)
self.phashDatabaseSelector.filesSelected.connect(self.phashDatabaseSelected)
self.knnModelSelector.connectSettings(KNN_MODEL_FILE) self.knnModelSelector.connectSettings(KNN_MODEL_FILE)
self.siftDatabaseSelector.connectSettings(SIFT_DATABASE_FILE) # self.siftDatabaseSelector.connectSettings(SIFT_DATABASE_FILE)
self.imagePath = None # for checking only self.imagePath = None # for checking only
self.img = None self.img = None
@ -45,7 +47,8 @@ class TabOcr_B30(Ui_TabOcr_B30, QWidget):
self.paddle = None self.paddle = None
self.knnModel = None self.knnModel = None
self.b30KnnModel = None self.b30KnnModel = None
self.siftDatabase = None # self.siftDatabase = None
self.phashDatabase = None
self.ocr = None self.ocr = None
@ -54,7 +57,7 @@ class TabOcr_B30(Ui_TabOcr_B30, QWidget):
settings = Settings() settings = Settings()
logger.info("Applying default settings...") logger.info("Applying default settings...")
self.knnModelSelector.selectFile(settings.knnModelFile()) self.knnModelSelector.selectFile(settings.knnModelFile())
self.siftDatabaseSelector.selectFile(settings.siftDatabaseFile()) # self.siftDatabaseSelector.selectFile(settings.siftDatabaseFile())
self.ocrQueueModel = OcrQueueModel(self) self.ocrQueueModel = OcrQueueModel(self)
self.ocrQueue.setModel(self.ocrQueueModel) self.ocrQueue.setModel(self.ocrQueueModel)
@ -84,6 +87,12 @@ class TabOcr_B30(Ui_TabOcr_B30, QWidget):
self.siftDatabase = SIFTDatabase(siftDatabasePath) self.siftDatabase = SIFTDatabase(siftDatabasePath)
self.tryPrepareOcr.emit() self.tryPrepareOcr.emit()
def phashDatabaseSelected(self):
if selectedFiles := self.phashDatabaseSelector.selectedFiles():
phashDatabasePath = selectedFiles[0]
self.phashDatabase = ImagePHashDatabase(phashDatabasePath)
self.tryPrepareOcr.emit()
def prepareOcr(self): def prepareOcr(self):
b30Type = self.b30TypeComboBox.currentData() b30Type = self.b30TypeComboBox.currentData()
if not b30Type: if not b30Type:
@ -94,13 +103,13 @@ class TabOcr_B30(Ui_TabOcr_B30, QWidget):
not self.imagePath not self.imagePath
or not self.knnModel or not self.knnModel
or not self.b30KnnModel or not self.b30KnnModel
or not self.siftDatabase or not self.phashDatabase
): ):
return return
self.ocrQueueModel.clear() self.ocrQueueModel.clear()
ocr = ChieriBotV4Ocr(self.knnModel, self.b30KnnModel, self.siftDatabase) ocr = ChieriBotV4Ocr(self.knnModel, self.b30KnnModel, self.phashDatabase)
ocr.set_factor(self.img) ocr.set_factor(self.img)
self.ocr = ocr self.ocr = ocr
@ -116,7 +125,7 @@ class TabOcr_B30(Ui_TabOcr_B30, QWidget):
not self.imagePath not self.imagePath
or not self.knnModel or not self.knnModel
or not self.b30KnnModel or not self.b30KnnModel
or not self.siftDatabase or not self.phashDatabase
): ):
return return

View File

@ -6,6 +6,7 @@ import cv2
from arcaea_offline_ocr.device.v1.definition import DeviceV1 from arcaea_offline_ocr.device.v1.definition import DeviceV1
from arcaea_offline_ocr.device.v2.definition import DeviceV2 from arcaea_offline_ocr.device.v2.definition import DeviceV2
from arcaea_offline_ocr.sift_db import SIFTDatabase from arcaea_offline_ocr.sift_db import SIFTDatabase
from arcaea_offline_ocr.phash_db import ImagePHashDatabase
from PySide6.QtCore import Qt, Slot from PySide6.QtCore import Qt, Slot
from PySide6.QtWidgets import QApplication, QFileDialog, QWidget from PySide6.QtWidgets import QApplication, QFileDialog, QWidget
@ -38,11 +39,12 @@ class TabOcr_Device(Ui_TabOcr_Device, QWidget):
self.deviceFileSelector.filesSelected.connect(self.deviceFileSelected) self.deviceFileSelector.filesSelected.connect(self.deviceFileSelected)
self.knnModelSelector.filesSelected.connect(self.knnModelFileSelected) self.knnModelSelector.filesSelected.connect(self.knnModelFileSelected)
self.siftDatabaseSelector.filesSelected.connect(self.siftDatabaseFileSelected) # self.siftDatabaseSelector.filesSelected.connect(self.siftDatabaseFileSelected)
self.phashDatabaseSelector.filesSelected.connect(self.phashDatabaseFileSelected)
self.deviceFileSelector.connectSettings(DEVICES_JSON_FILE) self.deviceFileSelector.connectSettings(DEVICES_JSON_FILE)
self.knnModelSelector.connectSettings(KNN_MODEL_FILE) self.knnModelSelector.connectSettings(KNN_MODEL_FILE)
self.siftDatabaseSelector.connectSettings(SIFT_DATABASE_FILE) # self.siftDatabaseSelector.connectSettings(SIFT_DATABASE_FILE)
settings = Settings() settings = Settings()
logger.info("Applying default settings...") logger.info("Applying default settings...")
@ -50,7 +52,7 @@ class TabOcr_Device(Ui_TabOcr_Device, QWidget):
self.tesseractFileSelector.selectFile(settings.tesseractPath()) self.tesseractFileSelector.selectFile(settings.tesseractPath())
self.deviceComboBox.selectDevice(settings.deviceUuid()) self.deviceComboBox.selectDevice(settings.deviceUuid())
self.knnModelSelector.selectFile(settings.knnModelFile()) self.knnModelSelector.selectFile(settings.knnModelFile())
self.siftDatabaseSelector.selectFile(settings.siftDatabaseFile()) # vself.siftDatabaseSelector.selectFile(settings.siftDatabaseFile())
self.ocrQueueModel = OcrQueueModel(self) self.ocrQueueModel = OcrQueueModel(self)
self.ocrQueue.setModel(self.ocrQueueModel) self.ocrQueue.setModel(self.ocrQueueModel)
@ -96,6 +98,10 @@ class TabOcr_Device(Ui_TabOcr_Device, QWidget):
if selectedFiles := self.siftDatabaseSelector.selectedFiles(): if selectedFiles := self.siftDatabaseSelector.selectedFiles():
self.siftDatabase = SIFTDatabase(selectedFiles[0]) self.siftDatabase = SIFTDatabase(selectedFiles[0])
def phashDatabaseFileSelected(self):
if selectedFiles := self.phashDatabaseSelector.selectedFiles():
self.phashDatabase = ImagePHashDatabase(selectedFiles[0])
@Slot() @Slot()
def on_ocr_addImageButton_clicked(self): def on_ocr_addImageButton_clicked(self):
files, _filter = QFileDialog.getOpenFileNames( files, _filter = QFileDialog.getOpenFileNames(
@ -115,14 +121,16 @@ class TabOcr_Device(Ui_TabOcr_Device, QWidget):
runnable = TabDeviceV2AutoRoisOcrRunnable( runnable = TabDeviceV2AutoRoisOcrRunnable(
imagePath, imagePath,
self.knnModel, self.knnModel,
self.siftDatabase, self.phashDatabase,
sizesV2=self.deviceSizesV2CheckBox.isChecked(),
) )
else: else:
runnable = TabDeviceV2OcrRunnable( runnable = TabDeviceV2OcrRunnable(
imagePath, imagePath,
self.deviceComboBox.currentData(), self.deviceComboBox.currentData(),
self.knnModel, self.knnModel,
self.siftDatabase, self.phashDatabase,
sizesV2=self.deviceSizesV2CheckBox.isChecked(),
) )
self.ocrQueueModel.setData(index, runnable, OcrQueueModel.OcrRunnableRole) self.ocrQueueModel.setData(index, runnable, OcrQueueModel.OcrRunnableRole)
self.ocrQueueModel.setData( self.ocrQueueModel.setData(