From bfcd60f153edeb10e57c985ecff4deec54fc8914 Mon Sep 17 00:00:00 2001 From: Kelvin Zhao Date: Thu, 25 Apr 2024 15:58:58 -0700 Subject: [PATCH 1/4] feat: unhide advanced tab --- src/main.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main.py b/src/main.py index 848b152..67dc709 100644 --- a/src/main.py +++ b/src/main.py @@ -115,9 +115,6 @@ def setup_ui(self, MainWindow: QtWidgets.QMainWindow) -> None: self.pushButtonOpenLocation.clicked.connect(self.open_output_location) self.pushButtonRestoreDefaults.clicked.connect(self.reset_settings) - # delete the Advanced tab for now - self.tabWidget.removeTab(1) - self.load_settings() def change_output_location(self) -> None: From 4d7b04583c3a2911176240a682b3112b5da90adb Mon Sep 17 00:00:00 2001 From: Kelvin Zhao Date: Thu, 25 Apr 2024 16:59:32 -0700 Subject: [PATCH 2/4] fix: adjust trace level preprocessing #80 --- src/services/scanner/scanner.py | 2 +- src/ui/hsr_scanner.py | 16 +++++++++------- src/ui/hsr_scanner.ui | 28 +++++++++++++++++----------- src/utils/ocr.py | 4 +++- 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/services/scanner/scanner.py b/src/services/scanner/scanner.py index 55010f3..3ea6191 100644 --- a/src/services/scanner/scanner.py +++ b/src/services/scanner/scanner.py @@ -175,7 +175,7 @@ async def start_scan(self) -> dict: return { "source": "HSR-Scanner", - "build": "v1.0.0", + "build": "v1.1.0", "version": 3, "metadata": { "uid": int(uid) if uid else None, diff --git a/src/ui/hsr_scanner.py b/src/ui/hsr_scanner.py index b59ab42..3156e5e 100644 --- a/src/ui/hsr_scanner.py +++ b/src/ui/hsr_scanner.py @@ -54,19 +54,21 @@ def setupUi(self, MainWindow): self.checkBoxScanChars.setEnabled(True) self.checkBoxScanChars.setObjectName("checkBoxScanChars") self.verticalLayout.addWidget(self.checkBoxScanChars) - self.formLayout.setLayout(1, QtWidgets.QFormLayout.ItemRole.FieldRole, self.verticalLayout) + self.formLayout.setLayout(0, QtWidgets.QFormLayout.ItemRole.FieldRole, self.verticalLayout) self.pushButtonStartScan = QtWidgets.QPushButton(parent=self.Scan) self.pushButtonStartScan.setEnabled(False) self.pushButtonStartScan.setGeometry(QtCore.QRect(10, 460, 111, 41)) self.pushButtonStartScan.setObjectName("pushButtonStartScan") self.groupBox = QtWidgets.QGroupBox(parent=self.Scan) - self.groupBox.setGeometry(QtCore.QRect(270, 320, 151, 91)) + self.groupBox.setGeometry(QtCore.QRect(150, 10, 271, 101)) self.groupBox.setObjectName("groupBox") self.formLayoutWidget = QtWidgets.QWidget(parent=self.groupBox) - self.formLayoutWidget.setGeometry(QtCore.QRect(10, 20, 131, 61)) + self.formLayoutWidget.setGeometry(QtCore.QRect(10, 20, 251, 71)) self.formLayoutWidget.setObjectName("formLayoutWidget") self.formLayout_3 = QtWidgets.QFormLayout(self.formLayoutWidget) + self.formLayout_3.setFormAlignment(QtCore.Qt.AlignmentFlag.AlignLeading|QtCore.Qt.AlignmentFlag.AlignLeft|QtCore.Qt.AlignmentFlag.AlignVCenter) self.formLayout_3.setContentsMargins(0, 0, 0, 0) + self.formLayout_3.setVerticalSpacing(6) self.formLayout_3.setObjectName("formLayout_3") self.label_23 = QtWidgets.QLabel(parent=self.formLayoutWidget) self.label_23.setObjectName("label_23") @@ -246,10 +248,10 @@ def setupUi(self, MainWindow): self.label.setFont(font) self.label.setObjectName("label") self.groupBox_5 = QtWidgets.QGroupBox(parent=self.Scan) - self.groupBox_5.setGeometry(QtCore.QRect(10, 320, 251, 131)) + self.groupBox_5.setGeometry(QtCore.QRect(10, 320, 411, 131)) self.groupBox_5.setObjectName("groupBox_5") self.textEditLog = QtWidgets.QPlainTextEdit(parent=self.groupBox_5) - self.textEditLog.setGeometry(QtCore.QRect(10, 20, 231, 101)) + self.textEditLog.setGeometry(QtCore.QRect(10, 20, 391, 101)) self.textEditLog.setReadOnly(True) self.textEditLog.setObjectName("textEditLog") self.tabWidget.addTab(self.Scan, "") @@ -441,7 +443,7 @@ def setupUi(self, MainWindow): def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate - MainWindow.setWindowTitle(_translate("MainWindow", "HSR Scanner v1.0.0")) + MainWindow.setWindowTitle(_translate("MainWindow", "HSR Scanner v1.1.0-pre.1")) self.formGroupBox.setTitle(_translate("MainWindow", "Items to scan")) self.checkBoxScanLightCones.setText(_translate("MainWindow", "Light Cones")) self.checkBoxScanRelics.setText(_translate("MainWindow", "Relics")) @@ -477,7 +479,7 @@ def retranslateUi(self, MainWindow): "\n" -"

HSR SCANNER v1.0.0

\n" +"

HSR SCANNER v1.1.0-pre.1

\n" "


\n" "

HOW TO RUN

\n" "

1. Set text language to English

\n" diff --git a/src/ui/hsr_scanner.ui b/src/ui/hsr_scanner.ui index b4c1cc6..61b4fc7 100644 --- a/src/ui/hsr_scanner.ui +++ b/src/ui/hsr_scanner.ui @@ -35,7 +35,7 @@ false - HSR Scanner v1.0.0 + HSR Scanner v1.1.0-pre.1 @@ -91,7 +91,7 @@ Items to scan - + @@ -140,10 +140,10 @@ - 270 - 320 - 151 - 91 + 150 + 10 + 271 + 101 @@ -154,11 +154,17 @@ 10 20 - 131 - 61 + 251 + 71 + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + 6 + @@ -566,7 +572,7 @@ <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">HSR SCANNER v1.0.0</span></p> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">HSR SCANNER v1.1.0-pre.1</span></p> <p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">HOW TO RUN</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">1. Set text language to English</p> @@ -629,7 +635,7 @@ p, li { white-space: pre-wrap; } 10 320 - 251 + 411 131 @@ -641,7 +647,7 @@ p, li { white-space: pre-wrap; } 10 20 - 231 + 391 101 diff --git a/src/utils/ocr.py b/src/utils/ocr.py index db54481..d4f05cb 100644 --- a/src/utils/ocr.py +++ b/src/utils/ocr.py @@ -83,8 +83,10 @@ def preprocess_trace_img(img: Image) -> Image: (33, 180, 182), (38, 212, 206), (14, 77, 82), + (0, 255, 255), + (0, 160, 180) ], - [50, 50, 20, 20, 30, 30, 15, 10], + [50, 50, 20, 20, 30, 30, 15, 10, 50, 20], ) return img From 62c4d131c87109a9a8501d89398653d4e77c2d00 Mon Sep 17 00:00:00 2001 From: Kelvin Zhao Date: Fri, 31 May 2024 23:44:12 -0700 Subject: [PATCH 3/4] fix: detect trailblazer items #88 --- src/config/screenshot.py | 2 ++ src/services/scanner/parsers/light_cone_strategy.py | 3 +++ src/services/scanner/parsers/relic_strategy.py | 3 +++ 3 files changed, 8 insertions(+) diff --git a/src/config/screenshot.py b/src/config/screenshot.py index e488fe1..a693c27 100644 --- a/src/config/screenshot.py +++ b/src/config/screenshot.py @@ -72,6 +72,7 @@ "superimposition": (0.53, 0.495, 0.6, 0.55), "equipped": (0.45, 0.935, 0.67, 0.965), "equipped_avatar": (0.3505, 0.916, 0.4375, 0.966675), + "equipped_avatar_trailblazer": (0.3905, 0.916, 0.4775, 0.966675), "lock": (0.896, 0.321, 0.97, 0.365), }, "relic": { @@ -82,6 +83,7 @@ "rarity": (0.07, 0.15, 0.2, 0.22), "equipped": (0.45, 0.935, 0.67, 0.965), "equipped_avatar": (0.3505, 0.916, 0.4375, 0.966675), + "equipped_avatar_trailblazer": (0.3905, 0.916, 0.4775, 0.966675), "mainStatKey": (0.11, 0.358, 0.7, 0.4), "substat_names": (0.11, 0.4, 0.5, 0.6), "substat_vals": (0.775, 0.4, 0.975, 0.6), diff --git a/src/services/scanner/parsers/light_cone_strategy.py b/src/services/scanner/parsers/light_cone_strategy.py index 3dcbdc2..6cfe06b 100644 --- a/src/services/scanner/parsers/light_cone_strategy.py +++ b/src/services/scanner/parsers/light_cone_strategy.py @@ -240,6 +240,9 @@ def parse(self, stats_dict: dict, lc_id: int) -> dict: if equipped == "Equipped": equipped_avatar = stats_dict["equipped_avatar"] location = self._game_data.get_equipped_character(equipped_avatar) + elif equipped == "Equippe": # https://github.com/kel-z/HSR-Scanner/issues/88 + equipped_avatar = stats_dict["equipped_avatar_trailblazer"] + location = self._game_data.get_equipped_character(equipped_avatar) result = { "key": name, diff --git a/src/services/scanner/parsers/relic_strategy.py b/src/services/scanner/parsers/relic_strategy.py index 48c2d2d..cbcfe27 100644 --- a/src/services/scanner/parsers/relic_strategy.py +++ b/src/services/scanner/parsers/relic_strategy.py @@ -269,6 +269,9 @@ def parse(self, stats_dict: dict, relic_id: int) -> dict: if equipped == "Equipped": equipped_avatar = stats_dict["equipped_avatar"] location = self._game_data.get_equipped_character(equipped_avatar) + elif equipped == "Equippe": # https://github.com/kel-z/HSR-Scanner/issues/88 + equipped_avatar = stats_dict["equipped_avatar_trailblazer"] + location = self._game_data.get_equipped_character(equipped_avatar) result = { "set": set_key, From d56c2d01dea0723c3ab1d1052eac9aabb17513b9 Mon Sep 17 00:00:00 2001 From: Kelvin Zhao Date: Mon, 3 Jun 2024 19:35:05 -0700 Subject: [PATCH 4/4] fix: character trace level fallback --- src/main.py | 6 -- .../scanner/parsers/character_parser.py | 25 ++++++- src/ui/hsr_scanner.py | 61 ++++++++--------- src/ui/hsr_scanner.ui | 65 ++++++++++--------- src/utils/ocr.py | 12 +++- 5 files changed, 98 insertions(+), 71 deletions(-) diff --git a/src/main.py b/src/main.py index 67dc709..39d652e 100644 --- a/src/main.py +++ b/src/main.py @@ -1,11 +1,9 @@ import asyncio import datetime -import os import sys import traceback import winsound -import pytesseract from pynput.keyboard import Key, Listener from PyQt6 import QtGui, QtWidgets from PyQt6.QtCore import QSettings, QThread, QUrl, pyqtSignal @@ -26,10 +24,6 @@ ) from utils.window import bring_window_to_foreground, flash_window -# set environment variables for Tesseract -os.environ["TESSDATA_PREFIX"] = resource_path("assets/tesseract/tessdata") -pytesseract.pytesseract.tesseract_cmd = resource_path("assets/tesseract/tesseract.exe") - class HSRScannerUI(QtWidgets.QMainWindow, Ui_MainWindow): """HSRScannerUI handles the UI for the HSR Scanner application""" diff --git a/src/services/scanner/parsers/character_parser.py b/src/services/scanner/parsers/character_parser.py index 29fe6b2..6f95ee9 100644 --- a/src/services/scanner/parsers/character_parser.py +++ b/src/services/scanner/parsers/character_parser.py @@ -91,10 +91,33 @@ def parse(self, stats_dict: dict) -> dict: for k, v in traces_dict["levels"].items(): try: res = image_to_string(v, "0123456789/", 6, True, preprocess_trace_img) - if not res or not res.find("/"): + + # If the first OCR attempt failed, try again with different parameters + if not res or "/" not in res: + self._log( + f"{character['key']}: Failed to parse '{k}' level. Trying again with PSM 6 and no force preprocess.", + LogLevel.DEBUG, + ) + res = image_to_string( + v, "0123456789/", 6, False, preprocess_trace_img + ) + if not res or "/" not in res: + self._log( + f"{character['key']}: Failed to parse '{k}' level. Trying again with PSM 7 and force preprocess.", + LogLevel.DEBUG, + ) res = image_to_string( v, "0123456789/", 7, True, preprocess_trace_img ) + if not res or "/" not in res: + self._log( + f"{character['key']}: Failed to parse '{k}' level. Trying again with PSM 7 and no force preprocess.", + LogLevel.DEBUG, + ) + res = image_to_string( + v, "0123456789/", 7, False, preprocess_trace_img + ) + character["skills"][k] += int(res.split("/")[0]) if not 1 <= character["skills"][k] <= (6 if k == "basic" else 10): raise ValueError diff --git a/src/ui/hsr_scanner.py b/src/ui/hsr_scanner.py index 3156e5e..e3a3692 100644 --- a/src/ui/hsr_scanner.py +++ b/src/ui/hsr_scanner.py @@ -127,7 +127,7 @@ def setupUi(self, MainWindow): self.groupBox_2.setGeometry(QtCore.QRect(10, 120, 411, 101)) self.groupBox_2.setObjectName("groupBox_2") self.formLayoutWidget_2 = QtWidgets.QWidget(parent=self.groupBox_2) - self.formLayoutWidget_2.setGeometry(QtCore.QRect(10, 20, 111, 71)) + self.formLayoutWidget_2.setGeometry(QtCore.QRect(10, 20, 111, 76)) self.formLayoutWidget_2.setObjectName("formLayoutWidget_2") self.formLayout_2 = QtWidgets.QFormLayout(self.formLayoutWidget_2) self.formLayout_2.setContentsMargins(0, 0, 0, 0) @@ -160,7 +160,7 @@ def setupUi(self, MainWindow): self.spinBoxLightConeMinLevel.setObjectName("spinBoxLightConeMinLevel") self.formLayout_2.setWidget(1, QtWidgets.QFormLayout.ItemRole.FieldRole, self.spinBoxLightConeMinLevel) self.formLayoutWidget_3 = QtWidgets.QWidget(parent=self.groupBox_2) - self.formLayoutWidget_3.setGeometry(QtCore.QRect(150, 20, 111, 71)) + self.formLayoutWidget_3.setGeometry(QtCore.QRect(150, 20, 111, 76)) self.formLayoutWidget_3.setObjectName("formLayoutWidget_3") self.formLayout_4 = QtWidgets.QFormLayout(self.formLayoutWidget_3) self.formLayout_4.setContentsMargins(0, 0, 0, 0) @@ -202,7 +202,7 @@ def setupUi(self, MainWindow): self.formLayout_7.setWidget(1, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_20) self.spinBoxCharacterMinLevel = QtWidgets.QSpinBox(parent=self.formLayoutWidget_5) self.spinBoxCharacterMinLevel.setCorrectionMode(QtWidgets.QAbstractSpinBox.CorrectionMode.CorrectToNearestValue) - self.spinBoxCharacterMinLevel.setMinimum(0) + self.spinBoxCharacterMinLevel.setMinimum(1) self.spinBoxCharacterMinLevel.setMaximum(80) self.spinBoxCharacterMinLevel.setProperty("value", 1) self.spinBoxCharacterMinLevel.setObjectName("spinBoxCharacterMinLevel") @@ -211,7 +211,7 @@ def setupUi(self, MainWindow): self.groupBox_3.setGeometry(QtCore.QRect(10, 230, 411, 81)) self.groupBox_3.setObjectName("groupBox_3") self.gridLayoutWidget = QtWidgets.QWidget(parent=self.groupBox_3) - self.gridLayoutWidget.setGeometry(QtCore.QRect(10, 20, 391, 51)) + self.gridLayoutWidget.setGeometry(QtCore.QRect(10, 20, 391, 59)) self.gridLayoutWidget.setObjectName("gridLayoutWidget") self.gridLayout = QtWidgets.QGridLayout(self.gridLayoutWidget) self.gridLayout.setContentsMargins(0, 0, 0, 0) @@ -299,10 +299,10 @@ def setupUi(self, MainWindow): self.Configure = QtWidgets.QWidget() self.Configure.setObjectName("Configure") self.groupBox_6 = QtWidgets.QGroupBox(parent=self.Configure) - self.groupBox_6.setGeometry(QtCore.QRect(10, 90, 171, 81)) + self.groupBox_6.setGeometry(QtCore.QRect(10, 90, 191, 81)) self.groupBox_6.setObjectName("groupBox_6") self.formLayoutWidget_4 = QtWidgets.QWidget(parent=self.groupBox_6) - self.formLayoutWidget_4.setGeometry(QtCore.QRect(10, 20, 151, 51)) + self.formLayoutWidget_4.setGeometry(QtCore.QRect(10, 20, 171, 53)) self.formLayoutWidget_4.setObjectName("formLayoutWidget_4") self.formLayout_5 = QtWidgets.QFormLayout(self.formLayoutWidget_4) self.formLayout_5.setContentsMargins(0, 0, 0, 0) @@ -327,10 +327,10 @@ def setupUi(self, MainWindow): self.lineEditInventoryKey.setObjectName("lineEditInventoryKey") self.formLayout_5.setWidget(0, QtWidgets.QFormLayout.ItemRole.FieldRole, self.lineEditInventoryKey) self.groupBox_7 = QtWidgets.QGroupBox(parent=self.Configure) - self.groupBox_7.setGeometry(QtCore.QRect(10, 10, 181, 71)) + self.groupBox_7.setGeometry(QtCore.QRect(10, 10, 191, 71)) self.groupBox_7.setObjectName("groupBox_7") self.verticalLayoutWidget_2 = QtWidgets.QWidget(parent=self.groupBox_7) - self.verticalLayoutWidget_2.setGeometry(QtCore.QRect(10, 20, 161, 42)) + self.verticalLayoutWidget_2.setGeometry(QtCore.QRect(10, 20, 171, 49)) self.verticalLayoutWidget_2.setObjectName("verticalLayoutWidget_2") self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget_2) self.verticalLayout_4.setContentsMargins(0, 0, 0, 0) @@ -345,7 +345,7 @@ def setupUi(self, MainWindow): self.groupBox_8.setGeometry(QtCore.QRect(10, 280, 201, 71)) self.groupBox_8.setObjectName("groupBox_8") self.verticalLayoutWidget = QtWidgets.QWidget(parent=self.groupBox_8) - self.verticalLayoutWidget.setGeometry(QtCore.QRect(10, 20, 181, 42)) + self.verticalLayoutWidget.setGeometry(QtCore.QRect(10, 20, 181, 49)) self.verticalLayoutWidget.setObjectName("verticalLayoutWidget") self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget) self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) @@ -443,7 +443,7 @@ def setupUi(self, MainWindow): def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate - MainWindow.setWindowTitle(_translate("MainWindow", "HSR Scanner v1.1.0-pre.1")) + MainWindow.setWindowTitle(_translate("MainWindow", "HSR Scanner v1.1.0")) self.formGroupBox.setTitle(_translate("MainWindow", "Items to scan")) self.checkBoxScanLightCones.setText(_translate("MainWindow", "Light Cones")) self.checkBoxScanRelics.setText(_translate("MainWindow", "Relics")) @@ -478,11 +478,11 @@ def retranslateUi(self, MainWindow): self.textEdit.setHtml(_translate("MainWindow", "\n" "\n" -"

HSR SCANNER v1.1.0-pre.1

\n" -"


\n" -"

HOW TO RUN

\n" -"

1. Set text language to English

\n" +"\n" +"

HSR SCANNER v1.1.0

\n" +"


\n" +"

HOW TO RUN

\n" +"

1. Set text language to English

\n" "

2. Set resolution with aspect ratio 16:9 (such as 1920x1080)

\n" "

3. Open cellphone menu (ESC)

\n" "

4. Press the start scan button

\n" @@ -490,10 +490,11 @@ def retranslateUi(self, MainWindow): "


\n" "

NOTES

\n" "

- The inventory screen is translucent and overall accuracy can be influenced by poor text contrast. Make sure the item details and quantity number have a dark background before starting the scan.

\n" -"

- Certain dual monitor configurations can cause screenshots to capture incorrectly. If this is the case, try moving HSR to a different monitor before retrying the scan. HDR should also be off to ensure OCR accuracy.

\n" -"

- Database is updated separately from this app. If the database version doesn\'t match the latest game version, then the database hasn\'t been updated yet. You will need to check again later.

\n" -"


\n" -"

HSR-Scanner is not affiliated with, endorsed, sponsored, or approved by HoYoverse.

")) +"

- HDR should be off to ensure OCR accuracy.

\n" +"

- Certain dual monitor configurations can cause screenshots to capture incorrectly. If this is the case, try moving HSR to a different monitor before retrying the scan.

\n" +"

- Database is updated separately from this app. If the database version doesn\'t match the latest game version, then the database hasn\'t been updated yet. You will need to check again later.

\n" +"


\n" +"

HSR-Scanner is not affiliated with, endorsed, sponsored, or approved by HoYoverse.

")) self.label_18.setText(_translate("MainWindow", "

GitHub

")) self.label.setText(_translate("MainWindow", "Press ENTER to cancel")) self.groupBox_5.setTitle(_translate("MainWindow", "Log")) @@ -506,12 +507,12 @@ def retranslateUi(self, MainWindow): self.textEdit_2.setHtml(_translate("MainWindow", "\n" "\n" -"

This tab will contain partial scan options for cases where scanning the entire account again isn\'t ideal.

\n" -"


\n" -"

SCAN MOST RECENT RELICS

\n" -"

Useful for exporting only newly acquired relics without needing to do a full relic scan.

\n" -"


")) +"\n" +"

This tab will contain partial scan options for cases where scanning the entire account again isn\'t ideal.

\n" +"


\n" +"

SCAN MOST RECENT RELICS

\n" +"

Useful for exporting only newly acquired relics without needing to do a full relic scan.

\n" +"


")) self.label_17.setText(_translate("MainWindow", "

GitHub

")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.Advanced), _translate("MainWindow", "Advanced")) self.groupBox_6.setTitle(_translate("MainWindow", "Hotkeys")) @@ -538,14 +539,14 @@ def retranslateUi(self, MainWindow): self.textEdit_3.setHtml(_translate("MainWindow", "\n" "\n" -"

ADDITIONAL DELAY

\n" -"

If Star Rail lags during the scan process, the scanner might produce inaccurate output or fail entirely. To compensate, there are two types of delay that can be increased accordingly to your system:

\n" +"\n" +"

ADDITIONAL DELAY

\n" +"

If Star Rail lags during the scan process, the scanner might produce inaccurate output or fail entirely. To compensate, there are two types of delay that can be increased accordingly to your system:

\n" "

- Navigation delay for navigating between different pages (inventory, character details, etc.)

\n" "

- Scan delay for clicking between individual items (relics, light cones, and characters).

\n" "


\n" -"

DEBUG MODE

\n" -"

Enabling this option will export ALL screenshots taken during a scan. The screenshots will be saved to a debug folder in the same directory as the JSON output.

")) +"

DEBUG MODE

\n" +"

Enabling this option will export ALL screenshots taken during a scan. The screenshots will be saved to a debug folder in the same directory as the JSON output.

")) self.label_16.setText(_translate("MainWindow", "

GitHub

")) self.pushButtonRestoreDefaults.setText(_translate("MainWindow", "Restore Defaults")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.Configure), _translate("MainWindow", "Configure")) diff --git a/src/ui/hsr_scanner.ui b/src/ui/hsr_scanner.ui index 61b4fc7..49f3530 100644 --- a/src/ui/hsr_scanner.ui +++ b/src/ui/hsr_scanner.ui @@ -35,7 +35,7 @@ false - HSR Scanner v1.1.0-pre.1 + HSR Scanner v1.1.0 @@ -306,7 +306,7 @@ 10 20 111 - 71 + 76 @@ -383,7 +383,7 @@ 150 20 111 - 71 + 76 @@ -472,7 +472,7 @@ QAbstractSpinBox::CorrectToNearestValue - 0 + 1 80 @@ -503,7 +503,7 @@ 10 20 391 - 51 + 59 @@ -571,11 +571,11 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">HSR SCANNER v1.1.0-pre.1</span></p> -<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">HOW TO RUN</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">1. Set text language to English</p> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">HSR SCANNER v1.1.0</span></p> +<p align="center" style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8.25pt; text-decoration: underline;">HOW TO RUN</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8.25pt;">1. Set text language to English</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">2. Set resolution with aspect ratio 16:9 (such as 1920x1080)</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">3. Open cellphone menu (ESC)</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">4. Press the start scan button</span></p> @@ -583,10 +583,11 @@ p, li { white-space: pre-wrap; } <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt; font-weight:600; text-decoration: underline;">NOTES</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; color:#ff0000;">- </span><span style=" font-size:8pt; color:#ff0000;">The inventory screen is translucent and overall accuracy can be influenced by poor text contrast. </span><span style=" font-size:8pt; font-weight:600; color:#ff0000;">Make sure the item details and quantity number have a dark background before starting the scan.</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Certain dual monitor configurations can cause screenshots to capture incorrectly. If this is the case, try moving HSR to a different monitor before retrying the scan. HDR should also be off to ensure OCR accuracy.</p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- Database is updated separately from this app. If the database version doesn't match the latest game version, then the database hasn't been updated yet. You will need to check again later.</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">HSR-Scanner is not affiliated with, endorsed, sponsored, or approved by HoYoverse.</p></body></html> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">- <span style=" font-size:8.25pt;">HDR should be off to ensure OCR accuracy.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8.25pt;">- Certain dual monitor configurations can cause screenshots to capture incorrectly. If this is the case, try moving HSR to a different monitor before retrying the scan.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8.25pt;">- Database is updated separately from this app. If the database version doesn't match the latest game version, then the database hasn't been updated yet. You will need to check again later.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8.25pt;">HSR-Scanner is not affiliated with, endorsed, sponsored, or approved by HoYoverse.</span></p></body></html> Qt::TextBrowserInteraction @@ -751,12 +752,12 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This tab will contain partial scan options for cases where scanning the entire account again isn't ideal.</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">SCAN MOST RECENT RELICS</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Useful for exporting only newly acquired relics without needing to do a full relic scan.</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8.25pt;">This tab will contain partial scan options for cases where scanning the entire account again isn't ideal.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8.25pt; text-decoration: underline;">SCAN MOST RECENT RELICS</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8.25pt;">Useful for exporting only newly acquired relics without needing to do a full relic scan.</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8.25pt;"><br /></p></body></html> @@ -789,7 +790,7 @@ p, li { white-space: pre-wrap; } 10 90 - 171 + 191 81 @@ -801,8 +802,8 @@ p, li { white-space: pre-wrap; } 10 20 - 151 - 51 + 171 + 53 @@ -863,7 +864,7 @@ p, li { white-space: pre-wrap; } 10 10 - 181 + 191 71 @@ -875,8 +876,8 @@ p, li { white-space: pre-wrap; } 10 20 - 161 - 42 + 171 + 49 @@ -915,7 +916,7 @@ p, li { white-space: pre-wrap; } 10 20 181 - 42 + 49 @@ -1139,14 +1140,14 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">ADDITIONAL DELAY</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">If Star Rail lags during the scan process, the scanner might produce inaccurate output or fail entirely. To compensate, there are two types of delay that can be increased accordingly to your system:</p> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8.25pt; text-decoration: underline;">ADDITIONAL DELAY</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8.25pt;">If Star Rail lags during the scan process, the scanner might produce inaccurate output or fail entirely. To compensate, there are two types of delay that can be increased accordingly to your system:</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">- Navigation delay for navigating between different pages (inventory, character details, etc.)</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">- Scan delay for clicking between individual items (relics, light cones, and characters).</span></p> <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" text-decoration: underline;">DEBUG MODE</span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Enabling this option will export ALL screenshots taken during a scan. The screenshots will be saved to a debug folder in the same directory as the JSON output.</p></body></html> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8.25pt; text-decoration: underline;">DEBUG MODE</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8.25pt;">Enabling this option will export ALL screenshots taken during a scan. The screenshots will be saved to a debug folder in the same directory as the JSON output.</span></p></body></html> diff --git a/src/utils/ocr.py b/src/utils/ocr.py index d4f05cb..3a379fb 100644 --- a/src/utils/ocr.py +++ b/src/utils/ocr.py @@ -1,12 +1,20 @@ +import os + import cv2 import numpy as np import pytesseract from PIL import Image as PILImage from PIL.Image import Image +from utils.data import resource_path + +# set environment variables for Tesseract +os.environ["TESSDATA_PREFIX"] = resource_path("assets/tesseract/tessdata") +pytesseract.pytesseract.tesseract_cmd = resource_path("assets/tesseract/tesseract.exe") + def preprocess_img(img: Image) -> Image: - """Preprocess image + """Generic image preprocessing function :param img: The image to preprocess :return: The preprocessed image @@ -84,7 +92,7 @@ def preprocess_trace_img(img: Image) -> Image: (38, 212, 206), (14, 77, 82), (0, 255, 255), - (0, 160, 180) + (0, 160, 180), ], [50, 50, 20, 20, 30, 30, 15, 10, 50, 20], )