Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: Deploy MkDocs site to GitHub Pages

on:
push:
branches:
- main
paths:
- 'docs/**' # Trigger hanya ketika ada perubahan di folder docs
- mkdocs.yml
workflow_dispatch: # Menyediakan trigger manual jika dibutuhkan

jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
pages: write
id-token: write
actions: read
steps:
- name: Clone repository
uses: actions/checkout@v4

- name: Install uv and set the python version
uses: astral-sh/setup-uv@v5
with:
version: "0.5.24"
enable-cache: true
cache-dependency-glob: "uv.lock"
python-version: 3.12


- name: Install dependencies
run: |
uv sync

- name: Build MkDocs site
run: |
mkdocs build

- name: Setup Pages
uses: actions/configure-pages@v3

- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./site

deploy:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
needs: build

permissions:
pages: write
id-token: write
actions: read

environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}

steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
11 changes: 11 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
repos:
- repo: https://github.com/astral-sh/uv-pre-commit
# uv version.
rev: 0.5.29
hooks:
- id: uv-lock
name: update uv lock file
- id: uv-export
name: export uv lock file

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: check-added-large-files
args: ['--maxkb=1024'] # 1MB = 1024KB
- id: check-toml
- id: check-yaml
exclude: ^mkdocs\.yml$
- id: detect-private-key
- id: end-of-file-fixer
exclude: ^LICENSE|VERSION$
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@

<div align="center">
<!-- image logo -->
<img src="assets/logo-v1.png" alt="Color Correction Logo" width="150"/>

# Color Correction

<br>

[![version](https://badge.fury.io/py/color-correction.svg)](https://badge.fury.io/py/color-correction)
[![downloads](https://img.shields.io/pypi/dm/color-correction-asdfghjkl)](https://pypistats.org/packages/color-correction-asdfghjkl)
[![downloads](https://img.shields.io/pypi/dm/color-correction)](https://pypistats.org/packages/color-correction)
[![python-version](https://img.shields.io/pypi/pyversions/color-correction)](https://badge.fury.io/py/color-correction)


Expand Down
Binary file added assets/logo-v1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
52 changes: 46 additions & 6 deletions color_correction/core/card_detection/det_yv8_onnx.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,52 @@


class YOLOv8CardDetector(BaseCardDetector):
"""YOLOv8CardDetector is a class that implements card detection
using the YOLOv8 model.

Reference
---------
https://github.com/ibaiGorordo/ONNX-YOLOv8-Object-Detection/blob/main/yolov8/YOLOv8.py
"""YOLOv8CardDetector is a class that implements card detection using the YOLOv8
model.

This class provides functionality to detect cards in images using a YOLOv8 model
implemented with ONNX runtime. It handles model initialization, image preprocessing,
inference, and post-processing of detection results.

Parameters
----------
conf_th : float, optional
Confidence threshold for filtering detections, by default 0.15
iou_th : float, optional
Intersection over Union threshold for non-maximum suppression, by default 0.7
path : str or None, optional
Path to the ONNX model file.
If None, downloads the default model, by default None
use_gpu : bool, optional
Whether to use GPU for inference, by default False

Attributes
----------
conf_threshold : float
Threshold for filtering detections based on confidence scores
iou_threshold : float
Threshold for non-maximum suppression
use_gpu : bool
Flag indicating whether to use GPU for inference
session : onnxruntime.InferenceSession
ONNX Runtime session for model inference
input_names : list
Names of model input nodes
output_names : list
Names of model output nodes
input_shape : tuple
Shape of the input tensor
input_height : int
Height of the input image required by the model
input_width : int
Width of the input image required by the model
scale_to_ori : float
Scale factor to map predictions back to original image size

Methods
-------
detect(image)
Detect cards in the input image and return detection results

"""

Expand Down
8 changes: 4 additions & 4 deletions color_correction/core/correction/__init__.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
from color_correction.core.correction._factory import (
CorrectionModelFactory,
)
from color_correction.core.correction.affine_reg import AffineReg
from color_correction.core.correction.affine_reg import AffineRegression
from color_correction.core.correction.least_squares import (
LeastSquaresRegression,
)
from color_correction.core.correction.linear_reg import LinearReg
from color_correction.core.correction.linear_reg import LinearRegression
from color_correction.core.correction.polynomial import Polynomial

__all__ = [
"CorrectionModelFactory",
"LeastSquaresRegression",
"Polynomial",
"LinearReg",
"AffineReg",
"LinearRegression",
"AffineRegression",
]
8 changes: 4 additions & 4 deletions color_correction/core/correction/_factory.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from color_correction.core.correction.affine_reg import AffineReg
from color_correction.core.correction.affine_reg import AffineRegression
from color_correction.core.correction.least_squares import (
LeastSquaresRegression,
)
from color_correction.core.correction.linear_reg import LinearReg
from color_correction.core.correction.linear_reg import LinearRegression
from color_correction.core.correction.polynomial import Polynomial


Expand All @@ -12,7 +12,7 @@ def create(model_name: str, **kwargs: dict) -> ...:
model_registry = {
"least_squares": LeastSquaresRegression(),
"polynomial": Polynomial(**kwargs),
"linear_reg": LinearReg(),
"affine_reg": AffineReg(),
"linear_reg": LinearRegression(),
"affine_reg": AffineRegression(),
}
return model_registry.get(model_name)
43 changes: 42 additions & 1 deletion color_correction/core/correction/affine_reg.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,15 @@
)


class AffineReg(BaseComputeCorrection):
class AffineRegression(BaseComputeCorrection):
"""
Apply an affine (linear) regression for color correction.

This class uses a linear regression model without an intercept
(by adding a bias column) to compute a correction transformation
between input and reference patches.
"""

def __init__(self) -> None:
self.model = None

Expand All @@ -19,6 +27,21 @@ def fit(
x_patches: np.ndarray, # input patches
y_patches: np.ndarray, # reference patches
) -> np.ndarray:
"""
Fit a linear regression model using input and reference patches.

Parameters
----------
x_patches : np.ndarray
Array of input patches with shape (n_samples, n_features).
y_patches : np.ndarray
Array of reference patches with shape (n_samples, n_targets).

Returns
-------
np.ndarray
The fitted linear regression model.
"""
start_time = time.perf_counter()
x_patches = np.array(x_patches)
print("x_patches.shape", x_patches.shape)
Expand All @@ -30,6 +53,24 @@ def fit(
return self.model

def compute_correction(self, input_image: np.ndarray) -> np.ndarray:
"""
Compute the color-corrected image using the fitted regression model.

Parameters
----------
input_image : np.ndarray
The input image to be corrected.

Returns
-------
np.ndarray
The color-corrected output image.

Raises
------
ValueError
If the model has not been fitted before calling this method.
"""
if self.model is None:
raise ValueError("Model is not fitted yet. Please call fit() method first.")

Expand Down
40 changes: 40 additions & 0 deletions color_correction/core/correction/least_squares.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@


class LeastSquaresRegression(BaseComputeCorrection):
"""
Apply a least squares regression for color correction.

This class computes a color correction transformation by solving the least squares
problem to find the best fit coefficients.
"""

def __init__(self) -> None:
self.model = None

Expand All @@ -18,6 +25,21 @@ def fit(
x_patches: np.ndarray, # input patches
y_patches: np.ndarray, # reference patches
) -> np.ndarray:
"""
Fit the least squares regression model using input and reference patches.

Parameters
----------
x_patches : np.ndarray
Array of input patches.
y_patches : np.ndarray
Array of reference patches.

Returns
-------
np.ndarray
The matrix of coefficients obtained from the least squares solution.
"""
start_time = time.perf_counter()

self.model = np.linalg.lstsq(
Expand All @@ -31,6 +53,24 @@ def fit(
return self.model

def compute_correction(self, input_image: np.ndarray) -> np.ndarray:
"""
Compute the color-corrected image using the fitted least squares model.

Parameters
----------
input_image : np.ndarray
The input image represented as an array of color values.

Returns
-------
np.ndarray
The color-corrected output image.

Raises
------
ValueError
If the model has not been fitted before calling this method.
"""
if self.model is None:
raise ValueError("Model is not fitted yet. Please call fit() method first.")

Expand Down
Loading