From 52f75a625d8383ce5a47eb25a947001048b9e52d Mon Sep 17 00:00:00 2001 From: Tohrusky <65994850+Tohrusky@users.noreply.github.com> Date: Sat, 27 Sep 2025 06:41:40 +0800 Subject: [PATCH 1/6] feat: replace ccrestoration with cccv --- Final2x_core/SRclass.py | 6 +++--- Final2x_core/SRqueue.py | 4 ++-- Final2x_core/__init__.py | 6 +++--- Final2x_core/config.py | 2 +- Final2x_core/util/__init__.py | 6 +++--- Final2x_core/util/device.py | 7 +++---- pyproject.toml | 18 +++++++++++++++--- scripts/gen_config.py | 2 +- scripts/gen_pretrained_model_name.py | 2 +- tests/test_targetscale.py | 6 +++--- uv.lock | 12 +++++------- 11 files changed, 40 insertions(+), 31 deletions(-) diff --git a/Final2x_core/SRclass.py b/Final2x_core/SRclass.py index 0d6154c..98b4429 100644 --- a/Final2x_core/SRclass.py +++ b/Final2x_core/SRclass.py @@ -2,16 +2,16 @@ import cv2 import numpy as np -from ccrestoration import AutoModel, SRBaseModel +from cccv import AutoModel, SRBaseModel from loguru import logger from Final2x_core.config import SRConfig from Final2x_core.util import PrintProgressLog, get_device -class CCRestoration: +class SRWrapper: """ - Super-resolution class for processing images, using ccrestoration. + Super-resolution class for processing images, using cccv. :param config: SRConfig """ diff --git a/Final2x_core/SRqueue.py b/Final2x_core/SRqueue.py index ff3e144..a300009 100644 --- a/Final2x_core/SRqueue.py +++ b/Final2x_core/SRqueue.py @@ -6,7 +6,7 @@ from loguru import logger from Final2x_core.config import SRConfig -from Final2x_core.SRclass import CCRestoration +from Final2x_core.SRclass import SRWrapper from Final2x_core.util import PrintProgressLog @@ -20,7 +20,7 @@ def sr_queue(config: SRConfig) -> None: input_path: List[Path] = config.input_path output_path: Path = config.output_path / "outputs" output_path.mkdir(parents=True, exist_ok=True) # create output folder - sr = CCRestoration(config) + sr = SRWrapper(config) logger.info("Processing------[ 0.0% ]") diff --git a/Final2x_core/__init__.py b/Final2x_core/__init__.py index 6818b3e..64d777e 100644 --- a/Final2x_core/__init__.py +++ b/Final2x_core/__init__.py @@ -1,3 +1,3 @@ -from Final2x_core.SRqueue import sr_queue # noqa -from Final2x_core.SRclass import CCRestoration # noqa -from Final2x_core.config import SRConfig # noqa +from Final2x_core.config import SRConfig +from Final2x_core.SRclass import SRWrapper +from Final2x_core.SRqueue import sr_queue diff --git a/Final2x_core/config.py b/Final2x_core/config.py index d1de928..430cc14 100644 --- a/Final2x_core/config.py +++ b/Final2x_core/config.py @@ -4,7 +4,7 @@ from typing import Any, List, Optional, Union import yaml -from ccrestoration import AutoConfig, BaseConfig, ConfigType +from cccv import AutoConfig, BaseConfig, ConfigType from pydantic import BaseModel, DirectoryPath, FilePath, field_validator diff --git a/Final2x_core/util/__init__.py b/Final2x_core/util/__init__.py index a340aa8..dcf371c 100644 --- a/Final2x_core/util/__init__.py +++ b/Final2x_core/util/__init__.py @@ -1,3 +1,3 @@ -from Final2x_core.util.progressLog import PrintProgressLog # noqa -from Final2x_core.util.singleton import singleton # noqa -from Final2x_core.util.device import get_device # noqa +from Final2x_core.util.device import get_device +from Final2x_core.util.progressLog import PrintProgressLog +from Final2x_core.util.singleton import singleton diff --git a/Final2x_core/util/device.py b/Final2x_core/util/device.py index 8d05f85..98f1be4 100644 --- a/Final2x_core/util/device.py +++ b/Final2x_core/util/device.py @@ -1,7 +1,7 @@ from typing import Union import torch -from ccrestoration.util.device import default_device +from cccv.util.device import DEFAULT_DEVICE def get_device(device: str) -> Union[torch.device, str]: @@ -13,7 +13,7 @@ def get_device(device: str) -> Union[torch.device, str]: device = device.lower() if device.startswith("auto"): - return default_device() + return DEFAULT_DEVICE elif device.startswith("cpu"): return torch.device("cpu") elif device.startswith("cuda"): @@ -27,5 +27,4 @@ def get_device(device: str) -> Union[torch.device, str]: elif device.startswith("xpu"): return torch.device("xpu") else: - print(f"Unknown device: {device}, use auto instead.") - return default_device() + return DEFAULT_DEVICE diff --git a/pyproject.toml b/pyproject.toml index d570e9b..621522a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,6 @@ requires = ["hatchling"] [dependency-groups] dev = [ "numpy~=1.26.4", - "ccrestoration==0.2.2", "opencv-python~=4.10.0.84", "torch~=2.7.1", "torchvision~=0.22.1", @@ -34,7 +33,7 @@ classifiers = [ ] dependencies = [ "PyYAML", - "ccrestoration==0.2.2", + "cccv==0.0.3", "loguru", "pydantic" ] @@ -94,7 +93,17 @@ quote-style = "double" skip-magic-trailing-comma = false [tool.ruff.lint] -extend-ignore = ["B018", "B019", "RUF001", "PGH003", "PGH004", "RUF003", "E402", "RUF002", "B904"] +extend-ignore = [ + "B018", + "B019", + "RUF001", + "PGH003", + "PGH004", + "RUF003", + "E402", + "RUF002", + "B904" +] extend-select = [ "I", # isort "B", # flake8-bugbear @@ -112,6 +121,9 @@ combine-as-imports = true [tool.ruff.lint.mccabe] max-complexity = 10 +[tool.ruff.lint.per-file-ignores] +"**/__init__.py" = ["F401", "F403"] + [tool.uv] default-groups = [ "dev", diff --git a/scripts/gen_config.py b/scripts/gen_config.py index a6ba61d..15e83b2 100644 --- a/scripts/gen_config.py +++ b/scripts/gen_config.py @@ -2,7 +2,7 @@ from pathlib import Path import yaml -from ccrestoration import ConfigType +from cccv import ConfigType projectPATH = Path(__file__).resolve().parent.parent.absolute() diff --git a/scripts/gen_pretrained_model_name.py b/scripts/gen_pretrained_model_name.py index 079adcf..8978cd7 100644 --- a/scripts/gen_pretrained_model_name.py +++ b/scripts/gen_pretrained_model_name.py @@ -1,7 +1,7 @@ from pathlib import Path from typing import List -from ccrestoration import ConfigType, ModelType +from cccv import ConfigType, ModelType projectPATH = Path(__file__).resolve().parent.parent.absolute() diff --git a/tests/test_targetscale.py b/tests/test_targetscale.py index b6453a9..ed650fb 100644 --- a/tests/test_targetscale.py +++ b/tests/test_targetscale.py @@ -1,6 +1,6 @@ -from ccrestoration import ConfigType +from cccv import ConfigType -from Final2x_core import CCRestoration, SRConfig +from Final2x_core import SRConfig, SRWrapper from .util import CONFIG_PATH, calculate_image_similarity, compare_image_size, load_image @@ -11,7 +11,7 @@ def test_case_targetscale_positive(self) -> None: config.pretrained_model_name = ConfigType.RealESRGAN_AnimeJaNai_HD_V3_Compact_2x for t in [7.99999, 1, 2, 2.5, 4, 5.6619, 8, 0.673]: config.target_scale = t - SR = CCRestoration(config=config) + SR = SRWrapper(config=config) img1 = load_image() img2 = SR.process(img1) assert calculate_image_similarity(img1, img2) diff --git a/uv.lock b/uv.lock index 51502cd..86f5249 100644 --- a/uv.lock +++ b/uv.lock @@ -39,8 +39,8 @@ wheels = [ ] [[package]] -name = "ccrestoration" -version = "0.2.2" +name = "cccv" +version = "0.0.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "einops" }, @@ -49,7 +49,7 @@ dependencies = [ { name = "tenacity" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/3b/4f/6772f4c54a2517e503b090a87a50cf0e86354f5b4f13b1f4f9e42228186a/ccrestoration-0.2.2-py3-none-any.whl", hash = "sha256:7cf089080f732d0ede368c4c6e49b235040a92590e55b32a14ddd69071be260b", size = 97887, upload-time = "2025-09-09T09:37:21.399Z" }, + { url = "https://files.pythonhosted.org/packages/49/b4/0f46c91da41bbcbedab0e4884d855a3fd1ef12ebac5e6e7f8d4256021bc8/cccv-0.0.3-py3-none-any.whl", hash = "sha256:191694d94ae3c788a24919b828cb1250c49856abca6ea7d1aebbd61b7c7e01b2", size = 107759, upload-time = "2025-09-26T21:55:22.6Z" }, ] [[package]] @@ -230,7 +230,7 @@ name = "final2x-core" version = "3.2.0" source = { editable = "." } dependencies = [ - { name = "ccrestoration" }, + { name = "cccv" }, { name = "loguru" }, { name = "pydantic" }, { name = "pyyaml" }, @@ -238,7 +238,6 @@ dependencies = [ [package.dev-dependencies] dev = [ - { name = "ccrestoration" }, { name = "numpy" }, { name = "opencv-python" }, { name = "pyinstaller" }, @@ -262,7 +261,7 @@ typing = [ [package.metadata] requires-dist = [ - { name = "ccrestoration", specifier = "==0.2.2" }, + { name = "cccv", specifier = "==0.0.3" }, { name = "loguru" }, { name = "pydantic" }, { name = "pyyaml" }, @@ -270,7 +269,6 @@ requires-dist = [ [package.metadata.requires-dev] dev = [ - { name = "ccrestoration", specifier = "==0.2.2" }, { name = "numpy", specifier = "~=1.26.4" }, { name = "opencv-python", specifier = "~=4.10.0.84" }, { name = "pyinstaller", specifier = "~=6.16.0" }, From 5673870a86058435f5a6714c6ee33d1735f310fe Mon Sep 17 00:00:00 2001 From: Tohrusky <65994850+Tohrusky@users.noreply.github.com> Date: Sat, 27 Sep 2025 06:50:57 +0800 Subject: [PATCH 2/6] feat: replace ccrestoration with cccv --- Final2x_core/SRclass.py | 2 +- Final2x_core/config.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Final2x_core/SRclass.py b/Final2x_core/SRclass.py index 98b4429..0d950a1 100644 --- a/Final2x_core/SRclass.py +++ b/Final2x_core/SRclass.py @@ -24,7 +24,7 @@ def __init__(self, config: SRConfig) -> None: PrintProgressLog().set(len(self.config.input_path), 1) self._SR_class: SRBaseModel = AutoModel.from_pretrained( - pretrained_model_name=self.config.pretrained_model_name, + self.config.pretrained_model_name, device=get_device(self.config.device), fp16=False, tile=tile, diff --git a/Final2x_core/config.py b/Final2x_core/config.py index 430cc14..fed2a11 100644 --- a/Final2x_core/config.py +++ b/Final2x_core/config.py @@ -28,7 +28,7 @@ def from_yaml(cls, yaml_path: Union[Path, str]) -> Any: raise ValueError(f"Error loading config: {e}") cfg = cls(**config) - c: BaseConfig = AutoConfig.from_pretrained(pretrained_model_name=cfg.pretrained_model_name) + c: BaseConfig = AutoConfig.from_pretrained(cfg.pretrained_model_name) cfg.cc_model_scale = c.scale if cfg.target_scale is None or cfg.target_scale <= 0: @@ -43,7 +43,7 @@ def from_json_str(cls, json_str: str) -> Any: raise ValueError(f"Error loading config: {e}") cfg = cls(**config) - c: BaseConfig = AutoConfig.from_pretrained(pretrained_model_name=cfg.pretrained_model_name) + c: BaseConfig = AutoConfig.from_pretrained(cfg.pretrained_model_name) cfg.cc_model_scale = c.scale if cfg.target_scale is None or cfg.target_scale <= 0: From c64985bb3210f4930a1604d5d518754f98c30a5a Mon Sep 17 00:00:00 2001 From: Tohrusky <65994850+Tohrusky@users.noreply.github.com> Date: Sat, 27 Sep 2025 06:57:33 +0800 Subject: [PATCH 3/6] feat: replace ccrestoration with cccv --- tests/test_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_config.py b/tests/test_config.py index 41479d9..a54fbd1 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -2,7 +2,7 @@ import pytest -from Final2x_core.config import SRConfig +from Final2x_core import SRConfig from .util import CONFIG_PATH From 0cc9cade159ff33f5d69d93cd0d1a7241fb89f83 Mon Sep 17 00:00:00 2001 From: Tohrusky <65994850+Tohrusky@users.noreply.github.com> Date: Sat, 27 Sep 2025 07:44:28 +0800 Subject: [PATCH 4/6] feat: replace ccrestoration with cccv --- Final2x_core/SRclass.py | 9 ++++++--- Final2x_core/config.py | 13 +++---------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/Final2x_core/SRclass.py b/Final2x_core/SRclass.py index 0d950a1..d483aab 100644 --- a/Final2x_core/SRclass.py +++ b/Final2x_core/SRclass.py @@ -41,6 +41,8 @@ def process(self, img: np.ndarray) -> np.ndarray: :return: """ + _origin_size = (img.shape[1], img.shape[0]) + _target_size = ( math.ceil(img.shape[1] * self.config.target_scale), math.ceil(img.shape[0] * self.config.target_scale), @@ -49,9 +51,10 @@ def process(self, img: np.ndarray) -> np.ndarray: img = self._SR_class.inference_image(img) PrintProgressLog().printProgress() - if abs(float(self.config.target_scale) - float(self.config.cc_model_scale)) < 1e-3: # type: ignore - return img + # calculate current size + _current_size = (img.shape[1], img.shape[0]) - img = cv2.resize(img, _target_size, interpolation=cv2.INTER_LINEAR) + if _current_size != _target_size: + img = cv2.resize(img, _target_size, interpolation=cv2.INTER_LINEAR) return img diff --git a/Final2x_core/config.py b/Final2x_core/config.py index fed2a11..10f592d 100644 --- a/Final2x_core/config.py +++ b/Final2x_core/config.py @@ -4,7 +4,7 @@ from typing import Any, List, Optional, Union import yaml -from cccv import AutoConfig, BaseConfig, ConfigType +from cccv import ConfigType from pydantic import BaseModel, DirectoryPath, FilePath, field_validator @@ -17,7 +17,6 @@ class SRConfig(BaseModel): output_path: DirectoryPath input_path: List[FilePath] save_format: Optional[str] = ".png" - cc_model_scale: Optional[int] = None @classmethod def from_yaml(cls, yaml_path: Union[Path, str]) -> Any: @@ -28,11 +27,8 @@ def from_yaml(cls, yaml_path: Union[Path, str]) -> Any: raise ValueError(f"Error loading config: {e}") cfg = cls(**config) - c: BaseConfig = AutoConfig.from_pretrained(cfg.pretrained_model_name) - - cfg.cc_model_scale = c.scale if cfg.target_scale is None or cfg.target_scale <= 0: - cfg.target_scale = c.scale + cfg.target_scale = 2 return cfg @classmethod @@ -43,11 +39,8 @@ def from_json_str(cls, json_str: str) -> Any: raise ValueError(f"Error loading config: {e}") cfg = cls(**config) - c: BaseConfig = AutoConfig.from_pretrained(cfg.pretrained_model_name) - - cfg.cc_model_scale = c.scale if cfg.target_scale is None or cfg.target_scale <= 0: - cfg.target_scale = c.scale + cfg.target_scale = 2 return cfg @classmethod From 851d8b9029f7d3bcef5bb043c4154ee29988cd5c Mon Sep 17 00:00:00 2001 From: Tohrusky <65994850+Tohrusky@users.noreply.github.com> Date: Sat, 27 Sep 2025 08:20:31 +0800 Subject: [PATCH 5/6] feat: replace ccrestoration with cccv --- pyproject.toml | 2 +- uv.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 621522a..1028923 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,7 +33,7 @@ classifiers = [ ] dependencies = [ "PyYAML", - "cccv==0.0.3", + "cccv==0.0.4", "loguru", "pydantic" ] diff --git a/uv.lock b/uv.lock index 86f5249..3ad5328 100644 --- a/uv.lock +++ b/uv.lock @@ -40,7 +40,7 @@ wheels = [ [[package]] name = "cccv" -version = "0.0.3" +version = "0.0.4" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "einops" }, @@ -49,7 +49,7 @@ dependencies = [ { name = "tenacity" }, ] wheels = [ - { url = "https://files.pythonhosted.org/packages/49/b4/0f46c91da41bbcbedab0e4884d855a3fd1ef12ebac5e6e7f8d4256021bc8/cccv-0.0.3-py3-none-any.whl", hash = "sha256:191694d94ae3c788a24919b828cb1250c49856abca6ea7d1aebbd61b7c7e01b2", size = 107759, upload-time = "2025-09-26T21:55:22.6Z" }, + { url = "https://files.pythonhosted.org/packages/be/b3/36984e26080fd4f37566ada0e83832856a3cc80bce436f35cb5675c65dee/cccv-0.0.4-py3-none-any.whl", hash = "sha256:acbf7ef4f5a9ff9e38150a53638898864e1b3189e69da2d6f2a375a8f39eddfe", size = 107704, upload-time = "2025-09-27T00:18:45.054Z" }, ] [[package]] @@ -261,7 +261,7 @@ typing = [ [package.metadata] requires-dist = [ - { name = "cccv", specifier = "==0.0.3" }, + { name = "cccv", specifier = "==0.0.4" }, { name = "loguru" }, { name = "pydantic" }, { name = "pyyaml" }, From 425cc3f015d176c4a7da22ba48c8ae5376db57e8 Mon Sep 17 00:00:00 2001 From: Tohrusky <65994850+Tohrusky@users.noreply.github.com> Date: Sat, 27 Sep 2025 08:23:45 +0800 Subject: [PATCH 6/6] feat: replace ccrestoration with cccv --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d5045c5..22babd6 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Final2x-core is a cross-platform image super-resolution CLI tool for [Final2x](h Download in [Release](https://github.com/EutropicAI/Final2x-core/releases) or use pip to install (Linux User). -Make sure you have Python >= 3.9 and PyTorch >= 1.13 installed +Make sure you have Python >= 3.9 and PyTorch >= 2.0 installed ```shell pip install Final2x-core @@ -50,6 +50,12 @@ make gen The following references were used in the development of this project: +After v4.0.0, we use cccv as the algorithm implementation, which implemented most of the features from ccrestoration + +- [cccv](https://github.com/EutropicAI/cccv) + +--- + After v3.0.0, ncnn will be deprecated, and the project will use ccrestoration(PyTorch) as the algorithm implementation. - [ccrestoration](https://github.com/EutropicAI/ccrestoration)