Skip to content

Commit

Permalink
Update build and release workflow, setup-python version, and upload a…
Browse files Browse the repository at this point in the history
…rtifact actions
  • Loading branch information
valentin-marquez committed Oct 15, 2024
1 parent c18ebb6 commit 6d0a9a9
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 22 deletions.
19 changes: 8 additions & 11 deletions .github/workflows/build-and-release.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
name: Build and Release

on:
workflow_dispatch:
push:
branches: [ "main" ]
tags:
- 'v*'
pull_request:
branches: [ "main" ]
workflow_dispatch:

jobs:
build:
runs-on: windows-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3

- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: '3.9'

Expand Down Expand Up @@ -49,13 +46,13 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./dist/nikke-ocr.exe
asset_name: nikke-ocr.exe
asset_path: ./dist/NIKKE-OCR/NIKKE-OCR.exe
asset_name: NIKKE-OCR.exe
asset_content_type: application/octet-stream

- name: Upload artifact for debugging
if: ${{ !startsWith(github.ref, 'refs/tags/v') }}
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: nikke-ocr
path: ./dist/nikke-ocr.exe
name: NIKKE-OCR
path: ./dist/NIKKE-OCR/NIKKE-OCR.exe
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ MANIFEST
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
!nikke_ocr.spec

# Installer logs
pip-log.txt
Expand Down
72 changes: 72 additions & 0 deletions nikke_ocr.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# -*- mode: python ; coding: utf-8 -*-

import os
from PyInstaller.utils.hooks import collect_all

block_cipher = None

# Collect all necessary data for PyQt5
datas = []
binaries = []
hiddenimports = []
tmp_ret = collect_all('PyQt5')
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]

a = Analysis(
['src/main.py'],
pathex=[],
binaries=binaries,
datas=[
('resources/static', 'resources/static'),
('src/config.py', 'src'),
('resources/icon.png', 'resources'),
] + datas,
hiddenimports=[
'PyQt5', 'PyQt5.QtCore', 'PyQt5.QtGui', 'PyQt5.QtWidgets',
'easyocr', 'numpy', 'cv2', 'skimage', 'pynput', 'pyautogui',
'torch', 'torchvision'
] + hiddenimports,
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)

# Crear las carpetas generated y output al mismo nivel que el ejecutable
a.datas += [('generated/.keep', 'generated/.keep', 'DATA')]
a.datas += [('output/.keep', 'output/.keep', 'DATA')]

pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

exe = EXE(
pyz,
a.scripts,
[],
exclude_binaries=True,
name='NIKKE-OCR',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=False,
disable_windowed_traceback=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon='resources/icon.png'
)

coll = COLLECT(
exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='NIKKE-OCR'
)
5 changes: 5 additions & 0 deletions scripts/build.bat
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ if errorlevel 1 (
goto :error
)

:: Delete previous build
echo Deleting previous build...
rmdir /s /q "%ROOT_DIR%\dist" >nul 2>&1
rmdir /s /q "%ROOT_DIR%\build" >nul 2>&1

:: Install requirements
echo Installing requirements...
pip install -r "%ROOT_DIR%\requirements\dev.txt" -r "%ROOT_DIR%\requirements\prod.txt" >nul 2>&1
Expand Down
15 changes: 11 additions & 4 deletions src/config.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
from pathlib import Path
import sys


class Config:
BASE_DIR = Path(__file__).resolve().parent.parent
RESOURCES_DIR = BASE_DIR / "resources"
if getattr(sys, "frozen", False):
BASE_DIR = Path(sys.executable).parent
INTERNAL_DIR = BASE_DIR / "_internal"
else:
BASE_DIR = Path(__file__).resolve().parent.parent
INTERNAL_DIR = BASE_DIR

RESOURCES_DIR = INTERNAL_DIR / "resources"
STATIC_DIR = RESOURCES_DIR / "static"
GENERATED_DIR = RESOURCES_DIR / "generated"
USER_DATA_DIR = RESOURCES_DIR / "output"

GENERATED_DIR = BASE_DIR / "generated"
USER_DATA_DIR = BASE_DIR / "output"

IMAGES_DIR = STATIC_DIR / "images"
LANG_DIR = STATIC_DIR / "lang"
Expand Down
14 changes: 9 additions & 5 deletions src/gui/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def _setup_ui(self) -> None:
self.setWindowTitle(_("NIKKE OCR"))
self.setGeometry(100, 100, 400, 300)

self.setWindowIcon(QIcon("resources/icon.png"))
self.setWindowIcon(QIcon(str(self.config.STATIC_DIR / "icon.png")))

central_widget = QWidget()
self.setCentralWidget(central_widget)
Expand Down Expand Up @@ -443,11 +443,15 @@ def _compare_images(

for nikke in nikkes:
reference_image: np.ndarray = cv2.imread(
f"{self.config.GENERATED_IMAGES_DIR}/{nikke['images']['big']}"
)
score: float = self.image_processor.compare_images(
nikke_image, reference_image
f"{self.config.GENERATED_IMAGES_DIR}/{nikke['images']['big']}",
cv2.IMREAD_UNCHANGED, # This will load the image as-is, whether it's color or grayscale
)

if reference_image is None:
print(f"Warning: Could not load image for {nikke['name']}")
continue

score: float = self.compare_images(nikke_image, reference_image)
if score > best_score:
best_score = score
best_match = nikke
Expand Down
16 changes: 14 additions & 2 deletions src/utils/image_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,21 @@ def process_roi(self, image: np.ndarray) -> Optional[str]:
return self.ocr_processor.process_name_roi(image)

def compare_images(self, img1: np.ndarray, img2: np.ndarray) -> float:
# Ensure both images have the same dimensions
img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0]))
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

# Convert images to grayscale if they're not already
if len(img1.shape) == 3:
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
else:
gray1 = img1

if len(img2.shape) == 3:
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
else:
gray2 = img2

# Compute SSIM
score, _ = ssim(gray1, gray2, full=True)
return score

Expand Down

0 comments on commit 6d0a9a9

Please sign in to comment.