PyPatchMatch 1.0.2__tar.gz → 2.0.0b2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. pypatchmatch-2.0.0b2/CMakeLists.txt +76 -0
  2. pypatchmatch-2.0.0b2/PKG-INFO +140 -0
  3. pypatchmatch-2.0.0b2/README.md +110 -0
  4. pypatchmatch-2.0.0b2/examples/images/forest_pruned.bmp +0 -0
  5. pypatchmatch-2.0.0b2/patchmatch/__init__.py +19 -0
  6. pypatchmatch-2.0.0b2/patchmatch/_lib.py +124 -0
  7. pypatchmatch-2.0.0b2/patchmatch/_version.py +24 -0
  8. {PyPatchMatch-1.0.2 → pypatchmatch-2.0.0b2}/patchmatch/csrc/inpaint.cpp +28 -15
  9. {PyPatchMatch-1.0.2 → pypatchmatch-2.0.0b2}/patchmatch/csrc/masked_image.cpp +0 -1
  10. {PyPatchMatch-1.0.2 → pypatchmatch-2.0.0b2}/patchmatch/csrc/masked_image.h +1 -0
  11. {PyPatchMatch-1.0.2 → pypatchmatch-2.0.0b2}/patchmatch/csrc/nnf.cpp +40 -13
  12. {PyPatchMatch-1.0.2 → pypatchmatch-2.0.0b2}/patchmatch/csrc/nnf.h +5 -0
  13. {PyPatchMatch-1.0.2 → pypatchmatch-2.0.0b2}/patchmatch/csrc/pyinterface.cpp +1 -2
  14. pypatchmatch-2.0.0b2/patchmatch/patch_match.py +192 -0
  15. pypatchmatch-2.0.0b2/patchmatch/py.typed +0 -0
  16. pypatchmatch-2.0.0b2/pyproject.toml +114 -0
  17. pypatchmatch-2.0.0b2/scripts/build_opencv.py +132 -0
  18. pypatchmatch-2.0.0b2/tests/test_e2e.py +157 -0
  19. pypatchmatch-2.0.0b2/tests/test_patch_match.py +343 -0
  20. PyPatchMatch-1.0.2/PKG-INFO +0 -103
  21. PyPatchMatch-1.0.2/PyPatchMatch.egg-info/PKG-INFO +0 -103
  22. PyPatchMatch-1.0.2/PyPatchMatch.egg-info/SOURCES.txt +0 -20
  23. PyPatchMatch-1.0.2/PyPatchMatch.egg-info/dependency_links.txt +0 -1
  24. PyPatchMatch-1.0.2/PyPatchMatch.egg-info/requires.txt +0 -28
  25. PyPatchMatch-1.0.2/PyPatchMatch.egg-info/top_level.txt +0 -1
  26. PyPatchMatch-1.0.2/README.md +0 -67
  27. PyPatchMatch-1.0.2/patchmatch/Makefile +0 -60
  28. PyPatchMatch-1.0.2/patchmatch/__init__.py +0 -3
  29. PyPatchMatch-1.0.2/patchmatch/patch_match.py +0 -381
  30. PyPatchMatch-1.0.2/patchmatch/travis.sh +0 -9
  31. PyPatchMatch-1.0.2/pyproject.toml +0 -71
  32. PyPatchMatch-1.0.2/setup.cfg +0 -4
  33. {PyPatchMatch-1.0.2 → pypatchmatch-2.0.0b2}/LICENSE +0 -0
  34. {PyPatchMatch-1.0.2 → pypatchmatch-2.0.0b2}/patchmatch/csrc/inpaint.h +0 -0
  35. {PyPatchMatch-1.0.2 → pypatchmatch-2.0.0b2}/patchmatch/csrc/pyinterface.h +0 -0
@@ -0,0 +1,76 @@
1
+ cmake_minimum_required(VERSION 3.21)
2
+ project(patchmatch LANGUAGES CXX)
3
+
4
+ option(PATCHMATCH_BUILD_EXAMPLES "Build the C++ example (requires OpenCV imgcodecs)" OFF)
5
+ option(PATCHMATCH_WITH_HIGHGUI "Enable the debug visualization of Inpainting::run (requires OpenCV highgui)" OFF)
6
+ option(PATCHMATCH_FAST_MATH "Compile with fast-math optimizations" ON)
7
+
8
+ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
9
+ set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
10
+ endif()
11
+
12
+ set(CMAKE_CXX_STANDARD 17)
13
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
14
+ set(CMAKE_CXX_EXTENSIONS OFF)
15
+ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
16
+
17
+ set(PATCHMATCH_OPENCV_COMPONENTS core)
18
+ if(PATCHMATCH_WITH_HIGHGUI)
19
+ list(APPEND PATCHMATCH_OPENCV_COMPONENTS imgproc highgui)
20
+ endif()
21
+ if(PATCHMATCH_BUILD_EXAMPLES)
22
+ list(APPEND PATCHMATCH_OPENCV_COMPONENTS imgcodecs)
23
+ endif()
24
+ find_package(OpenCV REQUIRED COMPONENTS ${PATCHMATCH_OPENCV_COMPONENTS})
25
+
26
+ add_library(patchmatch SHARED
27
+ patchmatch/csrc/inpaint.cpp
28
+ patchmatch/csrc/masked_image.cpp
29
+ patchmatch/csrc/nnf.cpp
30
+ patchmatch/csrc/pyinterface.cpp
31
+ )
32
+ target_include_directories(patchmatch PUBLIC patchmatch/csrc)
33
+ target_link_libraries(patchmatch PUBLIC opencv_core)
34
+
35
+ if(MSVC AND NOT OpenCV_SHARED)
36
+ # A static OpenCV (as built by scripts/build_opencv.py) uses the static MSVC runtime.
37
+ set_property(TARGET patchmatch PROPERTY
38
+ MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
39
+ endif()
40
+
41
+ if(PATCHMATCH_FAST_MATH)
42
+ if(MSVC)
43
+ target_compile_options(patchmatch PRIVATE /fp:fast)
44
+ else()
45
+ target_compile_options(patchmatch PRIVATE -ffast-math)
46
+ endif()
47
+ endif()
48
+
49
+ if(PATCHMATCH_WITH_HIGHGUI)
50
+ target_compile_definitions(patchmatch PRIVATE PATCHMATCH_WITH_HIGHGUI)
51
+ target_link_libraries(patchmatch PRIVATE opencv_imgproc opencv_highgui)
52
+ endif()
53
+
54
+ if(PATCHMATCH_BUILD_EXAMPLES)
55
+ add_executable(cpp_example examples/cpp_example.cpp)
56
+ target_link_libraries(cpp_example PRIVATE patchmatch opencv_imgcodecs)
57
+ endif()
58
+
59
+ # The Python package loads the library via ctypes from its own directory.
60
+ install(TARGETS patchmatch
61
+ LIBRARY DESTINATION patchmatch
62
+ RUNTIME DESTINATION patchmatch
63
+ )
64
+
65
+ # A static OpenCV becomes part of the library, so a wheel has to ship its licenses,
66
+ # which scripts/build_opencv.py collects in <prefix>/licenses.
67
+ if(DEFINED SKBUILD_METADATA_DIR AND NOT OpenCV_SHARED)
68
+ set(PATCHMATCH_OPENCV_LICENSES "${OpenCV_INSTALL_PATH}/licenses")
69
+ if(EXISTS "${PATCHMATCH_OPENCV_LICENSES}/opencv-LICENSE")
70
+ install(DIRECTORY "${PATCHMATCH_OPENCV_LICENSES}/"
71
+ DESTINATION "${SKBUILD_METADATA_DIR}/licenses/opencv")
72
+ else()
73
+ message(WARNING "No OpenCV licenses in ${PATCHMATCH_OPENCV_LICENSES}, "
74
+ "the wheel will not include them")
75
+ endif()
76
+ endif()
@@ -0,0 +1,140 @@
1
+ Metadata-Version: 2.4
2
+ Name: PyPatchMatch
3
+ Version: 2.0.0b2
4
+ Summary: This library implements the PatchMatch based inpainting algorithm.
5
+ Keywords: inpainting,patchmatch,image-processing,opencv
6
+ Author-Email: The InvokeAI Project <lincoln.stein@gmail.com>, Jiayuan Mao <maojiayuan@gmail.com>, Kyle Schouviller <kyle0654@hotmail.com>, Matthias Wild <mauwii@outlook.de>, Younesse ANDAM <younesse.andam@gmail.com>
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Operating System :: MacOS
11
+ Classifier: Operating System :: Microsoft :: Windows
12
+ Classifier: Operating System :: POSIX :: Linux
13
+ Classifier: Programming Language :: C++
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Topic :: Multimedia :: Graphics
21
+ Classifier: Topic :: Scientific/Engineering :: Image Processing
22
+ Classifier: Typing :: Typed
23
+ Project-URL: Source Code, https://github.com/mauwii/PyPatchMatch
24
+ Project-URL: Issues, https://github.com/mauwii/PyPatchMatch/issues
25
+ Project-URL: Release Notes, https://github.com/mauwii/PyPatchMatch/releases
26
+ Requires-Python: >=3.10
27
+ Requires-Dist: numpy
28
+ Requires-Dist: pillow
29
+ Description-Content-Type: text/markdown
30
+
31
+ # PatchMatch based Inpainting
32
+
33
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blueviolet.svg)](https://github.com/mauwii/PyPatchMatch/blob/main/LICENSE)
34
+ [![PyPI](https://img.shields.io/pypi/v/PyPatchMatch)](https://pypi.org/project/PyPatchMatch/)
35
+ [![Downloads](https://static.pepy.tech/badge/pypatchmatch)](https://pepy.tech/projects/pypatchmatch)
36
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
37
+
38
+ This library implements the PatchMatch based inpainting algorithm. It provides both C++
39
+ and Python interfaces. This implementation is heavily based on the implementation by
40
+ Younesse ANDAM: [younesse-cv/PatchMatch](https://github.com/younesse-cv/PatchMatch),
41
+ with some bug fixes, and updates.
42
+
43
+ ## Installation
44
+
45
+ ```sh
46
+ pip install PyPatchMatch
47
+ ```
48
+
49
+ Wheels for Linux (glibc, x86_64 and aarch64), macOS 11+ (arm64 and x86_64) and Windows
50
+ (x64) ship the compiled library with a statically linked OpenCV, so no compiler or
51
+ OpenCV installation is needed. On other platforms, e.g. Alpine Linux or Windows on ARM,
52
+ pip builds from the source distribution, which requires a C++17 compiler, CMake and the
53
+ OpenCV development files (e.g. `apt install libopencv-dev` or `brew install opencv`).
54
+
55
+ ## Usage
56
+
57
+ Python (see
58
+ [examples/py_example.py](https://github.com/mauwii/PyPatchMatch/blob/main/examples/py_example.py)):
59
+
60
+ ```python
61
+ import patchmatch
62
+
63
+ image = ... # HxWx3 uint8 numpy array or PIL image
64
+ mask = ... # HxW uint8 or bool numpy array or PIL image, non-zero marks the holes
65
+ result = patchmatch.inpaint(image, mask, patch_size=3)
66
+ ```
67
+
68
+ The mask must have the same height and width as the image. If `mask` is omitted, all
69
+ pure white pixels are treated as holes. The optional keyword argument `global_mask`, in
70
+ the same format, marks pixels that are neither filled nor used as a source; they keep
71
+ their values (see
72
+ [examples/py_example_global_mask.py](https://github.com/mauwii/PyPatchMatch/blob/main/examples/py_example_global_mask.py)).
73
+ `patchmatch.patchmatch_available` tells whether the native library could be loaded.
74
+ The previous import path `from patchmatch import patch_match` keeps working.
75
+
76
+ `patchmatch.set_random_seed(seed)` sets the seed of the randomized search and
77
+ `patchmatch.set_verbose(True)` prints the progress of the native code to stderr.
78
+ `patchmatch.inpaint_regularity(image, mask, ijmap)` additionally guides the search with
79
+ a regularity map, an HxWx3 float32 array with the regularity coordinates of each pixel.
80
+
81
+ C++ (see
82
+ [examples/cpp_example.cpp](https://github.com/mauwii/PyPatchMatch/blob/main/examples/cpp_example.cpp),
83
+ build and run it with
84
+ [examples/cpp_example_run.sh](https://github.com/mauwii/PyPatchMatch/blob/main/examples/cpp_example_run.sh)):
85
+
86
+ ```cpp
87
+ #include "inpaint.h"
88
+
89
+ int main() {
90
+ cv::Mat image = ...;
91
+ cv::Mat mask = ...;
92
+
93
+ auto metric = PatchSSDDistanceMetric(5);
94
+ cv::Mat result = Inpainting(image, mask, &metric).run();
95
+ }
96
+ ```
97
+
98
+ The library is built with CMake; `PATCHMATCH_BUILD_EXAMPLES` builds the example and
99
+ `PATCHMATCH_WITH_HIGHGUI` enables the debug visualization of `Inpainting::run`.
100
+
101
+ ## Development
102
+
103
+ The project is managed with [uv](https://docs.astral.sh/uv/):
104
+
105
+ ```sh
106
+ uv sync # create .venv, build the library, install dev deps
107
+ uv run pre-commit install # enable ruff and the other hooks on commit
108
+ uv run pytest # run the test suite
109
+ uv run pytest -m "not e2e" # only the fast unit tests
110
+ ```
111
+
112
+ Releases are published to PyPI by creating a GitHub release; the version is taken from
113
+ its tag (e.g. `v2.0.0`).
114
+
115
+ ## License
116
+
117
+ PyPatchMatch is released under the
118
+ [MIT License](https://github.com/mauwii/PyPatchMatch/blob/main/LICENSE). The wheels
119
+ contain a statically linked build of OpenCV core (Apache-2.0) and its bundled
120
+ third-party code; their licenses are included in the `licenses/opencv` directory of the
121
+ wheel's `.dist-info`.
122
+
123
+ ## README and COPYRIGHT by Younesse ANDAM
124
+
125
+ @Author: Younesse ANDAM
126
+
127
+ @Contact: <younesse.andam@gmail.com>
128
+
129
+ Description:
130
+
131
+ This project is a personal implementation of an algorithm called PATCHMATCH
132
+ that restores missing areas in an image. The algorithm is presented in the following
133
+ paper PatchMatch A Randomized Correspondence Algorithm for Structural Image Editing by
134
+ C.Barnes, E.Shechtman, A.Finkelstein and Dan B.Goldman ACM Transactions on Graphics
135
+ (Proc. SIGGRAPH), vol.28, aug-2009
136
+
137
+ For more information please refer to
138
+ <https://gfx.cs.princeton.edu/pubs/Barnes_2009_PAR/>
139
+
140
+ Copyright (c) 2010-2011
@@ -0,0 +1,110 @@
1
+ # PatchMatch based Inpainting
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blueviolet.svg)](https://github.com/mauwii/PyPatchMatch/blob/main/LICENSE)
4
+ [![PyPI](https://img.shields.io/pypi/v/PyPatchMatch)](https://pypi.org/project/PyPatchMatch/)
5
+ [![Downloads](https://static.pepy.tech/badge/pypatchmatch)](https://pepy.tech/projects/pypatchmatch)
6
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
7
+
8
+ This library implements the PatchMatch based inpainting algorithm. It provides both C++
9
+ and Python interfaces. This implementation is heavily based on the implementation by
10
+ Younesse ANDAM: [younesse-cv/PatchMatch](https://github.com/younesse-cv/PatchMatch),
11
+ with some bug fixes, and updates.
12
+
13
+ ## Installation
14
+
15
+ ```sh
16
+ pip install PyPatchMatch
17
+ ```
18
+
19
+ Wheels for Linux (glibc, x86_64 and aarch64), macOS 11+ (arm64 and x86_64) and Windows
20
+ (x64) ship the compiled library with a statically linked OpenCV, so no compiler or
21
+ OpenCV installation is needed. On other platforms, e.g. Alpine Linux or Windows on ARM,
22
+ pip builds from the source distribution, which requires a C++17 compiler, CMake and the
23
+ OpenCV development files (e.g. `apt install libopencv-dev` or `brew install opencv`).
24
+
25
+ ## Usage
26
+
27
+ Python (see
28
+ [examples/py_example.py](https://github.com/mauwii/PyPatchMatch/blob/main/examples/py_example.py)):
29
+
30
+ ```python
31
+ import patchmatch
32
+
33
+ image = ... # HxWx3 uint8 numpy array or PIL image
34
+ mask = ... # HxW uint8 or bool numpy array or PIL image, non-zero marks the holes
35
+ result = patchmatch.inpaint(image, mask, patch_size=3)
36
+ ```
37
+
38
+ The mask must have the same height and width as the image. If `mask` is omitted, all
39
+ pure white pixels are treated as holes. The optional keyword argument `global_mask`, in
40
+ the same format, marks pixels that are neither filled nor used as a source; they keep
41
+ their values (see
42
+ [examples/py_example_global_mask.py](https://github.com/mauwii/PyPatchMatch/blob/main/examples/py_example_global_mask.py)).
43
+ `patchmatch.patchmatch_available` tells whether the native library could be loaded.
44
+ The previous import path `from patchmatch import patch_match` keeps working.
45
+
46
+ `patchmatch.set_random_seed(seed)` sets the seed of the randomized search and
47
+ `patchmatch.set_verbose(True)` prints the progress of the native code to stderr.
48
+ `patchmatch.inpaint_regularity(image, mask, ijmap)` additionally guides the search with
49
+ a regularity map, an HxWx3 float32 array with the regularity coordinates of each pixel.
50
+
51
+ C++ (see
52
+ [examples/cpp_example.cpp](https://github.com/mauwii/PyPatchMatch/blob/main/examples/cpp_example.cpp),
53
+ build and run it with
54
+ [examples/cpp_example_run.sh](https://github.com/mauwii/PyPatchMatch/blob/main/examples/cpp_example_run.sh)):
55
+
56
+ ```cpp
57
+ #include "inpaint.h"
58
+
59
+ int main() {
60
+ cv::Mat image = ...;
61
+ cv::Mat mask = ...;
62
+
63
+ auto metric = PatchSSDDistanceMetric(5);
64
+ cv::Mat result = Inpainting(image, mask, &metric).run();
65
+ }
66
+ ```
67
+
68
+ The library is built with CMake; `PATCHMATCH_BUILD_EXAMPLES` builds the example and
69
+ `PATCHMATCH_WITH_HIGHGUI` enables the debug visualization of `Inpainting::run`.
70
+
71
+ ## Development
72
+
73
+ The project is managed with [uv](https://docs.astral.sh/uv/):
74
+
75
+ ```sh
76
+ uv sync # create .venv, build the library, install dev deps
77
+ uv run pre-commit install # enable ruff and the other hooks on commit
78
+ uv run pytest # run the test suite
79
+ uv run pytest -m "not e2e" # only the fast unit tests
80
+ ```
81
+
82
+ Releases are published to PyPI by creating a GitHub release; the version is taken from
83
+ its tag (e.g. `v2.0.0`).
84
+
85
+ ## License
86
+
87
+ PyPatchMatch is released under the
88
+ [MIT License](https://github.com/mauwii/PyPatchMatch/blob/main/LICENSE). The wheels
89
+ contain a statically linked build of OpenCV core (Apache-2.0) and its bundled
90
+ third-party code; their licenses are included in the `licenses/opencv` directory of the
91
+ wheel's `.dist-info`.
92
+
93
+ ## README and COPYRIGHT by Younesse ANDAM
94
+
95
+ @Author: Younesse ANDAM
96
+
97
+ @Contact: <younesse.andam@gmail.com>
98
+
99
+ Description:
100
+
101
+ This project is a personal implementation of an algorithm called PATCHMATCH
102
+ that restores missing areas in an image. The algorithm is presented in the following
103
+ paper PatchMatch A Randomized Correspondence Algorithm for Structural Image Editing by
104
+ C.Barnes, E.Shechtman, A.Finkelstein and Dan B.Goldman ACM Transactions on Graphics
105
+ (Proc. SIGGRAPH), vol.28, aug-2009
106
+
107
+ For more information please refer to
108
+ <https://gfx.cs.princeton.edu/pubs/Barnes_2009_PAR/>
109
+
110
+ Copyright (c) 2010-2011
@@ -0,0 +1,19 @@
1
+ """PatchMatch based inpainting."""
2
+
3
+ from ._version import __version__
4
+ from .patch_match import (
5
+ inpaint,
6
+ inpaint_regularity,
7
+ patchmatch_available,
8
+ set_random_seed,
9
+ set_verbose,
10
+ )
11
+
12
+ __all__ = [
13
+ "__version__",
14
+ "inpaint",
15
+ "inpaint_regularity",
16
+ "patchmatch_available",
17
+ "set_random_seed",
18
+ "set_verbose",
19
+ ]
@@ -0,0 +1,124 @@
1
+ """ctypes bindings for the native patchmatch library."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import ctypes
6
+ import sys
7
+ from pathlib import Path
8
+
9
+ import numpy as np
10
+
11
+ if sys.platform == "win32":
12
+ LIBRARY_NAME = "patchmatch.dll"
13
+ elif sys.platform == "darwin":
14
+ LIBRARY_NAME = "libpatchmatch.dylib"
15
+ else:
16
+ LIBRARY_NAME = "libpatchmatch.so"
17
+
18
+
19
+ class CShapeT(ctypes.Structure):
20
+ _fields_ = [
21
+ ("width", ctypes.c_int),
22
+ ("height", ctypes.c_int),
23
+ ("channels", ctypes.c_int),
24
+ ]
25
+
26
+
27
+ class CMatT(ctypes.Structure):
28
+ _fields_ = [
29
+ ("data_ptr", ctypes.c_void_p),
30
+ ("shape", CShapeT),
31
+ ("dtype", ctypes.c_int),
32
+ ]
33
+
34
+
35
+ # Order matches the PM_dtype_e enum in csrc/pyinterface.h.
36
+ _PYMAT_DTYPES = [
37
+ np.dtype(np.uint8),
38
+ np.dtype(np.int8),
39
+ np.dtype(np.uint16),
40
+ np.dtype(np.int16),
41
+ np.dtype(np.int32),
42
+ np.dtype(np.float32),
43
+ np.dtype(np.float64),
44
+ ]
45
+ _PYMAT_DTYPE_IDS = {dtype: i for i, dtype in enumerate(_PYMAT_DTYPES)}
46
+
47
+
48
+ def np_to_pymat(npmat: np.ndarray) -> CMatT:
49
+ """Wrap a contiguous HxWxC array without copying it."""
50
+ if npmat.ndim != 3:
51
+ raise ValueError(f"expected a 3-dimensional array, got {npmat.ndim} dims")
52
+ if not npmat.flags.c_contiguous:
53
+ raise ValueError("expected a C-contiguous array")
54
+ try:
55
+ dtype_id = _PYMAT_DTYPE_IDS[npmat.dtype]
56
+ except KeyError:
57
+ raise TypeError(f"unsupported dtype {npmat.dtype}") from None
58
+ height, width, channels = npmat.shape
59
+ return CMatT(
60
+ ctypes.c_void_p(npmat.ctypes.data),
61
+ CShapeT(width, height, channels),
62
+ dtype_id,
63
+ )
64
+
65
+
66
+ def pymat_to_np(pymat: CMatT) -> np.ndarray:
67
+ """Copy the data referenced by ``pymat`` into a new numpy array."""
68
+ dtype = _PYMAT_DTYPES[pymat.dtype]
69
+ shape = (pymat.shape.height, pymat.shape.width, pymat.shape.channels)
70
+ buffer = (ctypes.c_byte * (int(np.prod(shape)) * dtype.itemsize)).from_address(
71
+ pymat.data_ptr
72
+ )
73
+ return np.frombuffer(buffer, dtype=dtype).reshape(shape).copy()
74
+
75
+
76
+ def find_library() -> Path:
77
+ """Locate the shared library that is installed next to this package."""
78
+ package = sys.modules[__package__]
79
+ for directory in package.__path__:
80
+ candidate = Path(directory) / LIBRARY_NAME
81
+ if candidate.is_file():
82
+ return candidate
83
+ raise OSError(
84
+ f"{LIBRARY_NAME} not found in {list(package.__path__)}; "
85
+ "reinstall PyPatchMatch or build it from source with OpenCV available"
86
+ )
87
+
88
+
89
+ def load_library() -> ctypes.CDLL:
90
+ lib = ctypes.CDLL(str(find_library()))
91
+
92
+ lib.PM_set_random_seed.argtypes = [ctypes.c_uint]
93
+ lib.PM_set_random_seed.restype = None
94
+ lib.PM_set_verbose.argtypes = [ctypes.c_int]
95
+ lib.PM_set_verbose.restype = None
96
+ lib.PM_free_pymat.argtypes = [CMatT]
97
+ lib.PM_free_pymat.restype = None
98
+
99
+ lib.PM_inpaint.argtypes = [CMatT, CMatT, ctypes.c_int]
100
+ lib.PM_inpaint2.argtypes = [CMatT, CMatT, CMatT, ctypes.c_int]
101
+ lib.PM_inpaint_regularity.argtypes = [
102
+ CMatT,
103
+ CMatT,
104
+ CMatT,
105
+ ctypes.c_int,
106
+ ctypes.c_float,
107
+ ]
108
+ lib.PM_inpaint2_regularity.argtypes = [
109
+ CMatT,
110
+ CMatT,
111
+ CMatT,
112
+ CMatT,
113
+ ctypes.c_int,
114
+ ctypes.c_float,
115
+ ]
116
+ for func in (
117
+ lib.PM_inpaint,
118
+ lib.PM_inpaint2,
119
+ lib.PM_inpaint_regularity,
120
+ lib.PM_inpaint2_regularity,
121
+ ):
122
+ func.restype = CMatT
123
+
124
+ return lib
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '2.0.0b2'
22
+ __version_tuple__ = version_tuple = (2, 0, 0, 'b2')
23
+
24
+ __commit_id__ = commit_id = 'gd8a13321b'
@@ -1,20 +1,19 @@
1
1
  #include <algorithm>
2
2
  #include <iostream>
3
- #include <opencv2/imgcodecs.hpp>
3
+ #ifdef PATCHMATCH_WITH_HIGHGUI
4
4
  #include <opencv2/imgproc.hpp>
5
5
  #include <opencv2/highgui.hpp>
6
+ #endif
6
7
 
7
8
  #include "inpaint.h"
8
9
 
9
10
  namespace
10
11
  {
11
- static std::vector<double> kDistance2Similarity;
12
-
13
- void init_kDistance2Similarity()
12
+ std::vector<double> make_distance2similarity()
14
13
  {
15
14
  double base[11] = {1.0, 0.99, 0.96, 0.83, 0.38, 0.11, 0.02, 0.005, 0.0006, 0.0001, 0};
16
15
  int length = (PatchDistanceMetric::kDistanceScale + 1);
17
- kDistance2Similarity.resize(length);
16
+ std::vector<double> table(length);
18
17
  for (int i = 0; i < length; ++i)
19
18
  {
20
19
  double t = (double)i / length;
@@ -22,8 +21,17 @@ namespace
22
21
  int k = j + 1;
23
22
  double vj = (j < 11) ? base[j] : 0;
24
23
  double vk = (k < 11) ? base[k] : 0;
25
- kDistance2Similarity[i] = vj + (100 * t - j) * (vk - vj);
24
+ table[i] = vj + (100 * t - j) * (vk - vj);
26
25
  }
26
+ return table;
27
+ }
28
+
29
+ // Built on first use. The initialization of a local static is thread-safe, which
30
+ // matters because the Python bindings release the GIL during inpainting.
31
+ const std::vector<double> &distance2similarity()
32
+ {
33
+ static const std::vector<double> table = make_distance2similarity();
34
+ return table;
27
35
  }
28
36
 
29
37
  inline void _weighted_copy(const MaskedImage &source, int ys, int xs, cv::Mat &target, int yt, int xt, double weight)
@@ -48,13 +56,13 @@ namespace
48
56
  */
49
57
 
50
58
  Inpainting::Inpainting(cv::Mat image, cv::Mat mask, const PatchDistanceMetric *metric)
51
- : m_initial(image, mask), m_distance_metric(metric), m_pyramid(), m_source2target(), m_target2source()
59
+ : m_initial(image, mask), m_pyramid(), m_source2target(), m_target2source(), m_distance_metric(metric)
52
60
  {
53
61
  _initialize_pyramid();
54
62
  }
55
63
 
56
64
  Inpainting::Inpainting(cv::Mat image, cv::Mat mask, cv::Mat global_mask, const PatchDistanceMetric *metric)
57
- : m_initial(image, mask, global_mask), m_distance_metric(metric), m_pyramid(), m_source2target(), m_target2source()
65
+ : m_initial(image, mask, global_mask), m_pyramid(), m_source2target(), m_target2source(), m_distance_metric(metric)
58
66
  {
59
67
  _initialize_pyramid();
60
68
  }
@@ -68,16 +76,11 @@ void Inpainting::_initialize_pyramid()
68
76
  source = source.downsample();
69
77
  m_pyramid.push_back(source);
70
78
  }
71
-
72
- if (kDistance2Similarity.size() == 0)
73
- {
74
- init_kDistance2Similarity();
75
- }
76
79
  }
77
80
 
78
81
  cv::Mat Inpainting::run(bool verbose, bool verbose_visualize, unsigned int random_seed)
79
82
  {
80
- srand(random_seed);
83
+ NearestNeighborField::seed_random(random_seed);
81
84
  const int nr_levels = m_pyramid.size();
82
85
 
83
86
  MaskedImage source, target;
@@ -104,6 +107,7 @@ cv::Mat Inpainting::run(bool verbose, bool verbose_visualize, unsigned int rando
104
107
  if (verbose)
105
108
  std::cerr << "Initialization done." << std::endl;
106
109
 
110
+ #ifdef PATCHMATCH_WITH_HIGHGUI
107
111
  if (verbose_visualize)
108
112
  {
109
113
  auto visualize_size = m_initial.size();
@@ -115,11 +119,19 @@ cv::Mat Inpainting::run(bool verbose, bool verbose_visualize, unsigned int rando
115
119
  cv::imshow("Target", target_visualize);
116
120
  cv::waitKey(0);
117
121
  }
122
+ #else
123
+ (void)verbose_visualize;
124
+ #endif
118
125
 
119
126
  target = _expectation_maximization(source, target, level, verbose);
120
127
  }
121
128
 
122
- return target.image();
129
+ // Globally masked pixels are neither filled nor used as a source, so the pyramid
130
+ // leaves them black. Keep their input values instead.
131
+ cv::Mat result = target.image();
132
+ if (!m_initial.global_mask().empty())
133
+ m_initial.image().copyTo(result, m_initial.global_mask());
134
+ return result;
123
135
  }
124
136
 
125
137
  // EM-Like algorithm (see "PatchMatch" - page 6).
@@ -206,6 +218,7 @@ void Inpainting::_expectation_step(
206
218
  auto source_size = nnf.source_size();
207
219
  auto target_size = nnf.target_size();
208
220
  const int patch_size = m_distance_metric->patch_size();
221
+ const auto &kDistance2Similarity = distance2similarity();
209
222
 
210
223
  for (int i = 0; i < source_size.height; ++i)
211
224
  {
@@ -150,7 +150,6 @@ void MaskedImage::compute_image_gradients()
150
150
 
151
151
  for (int i = 1; i < size.height - 1; ++i)
152
152
  {
153
- const auto *ptr = m_image.ptr<unsigned char>(i, 0);
154
153
  const auto *ptry1 = m_image.ptr<unsigned char>(i + 1, 0);
155
154
  const auto *ptry2 = m_image.ptr<unsigned char>(i - 1, 0);
156
155
  const auto *ptrx1 = m_image.ptr<unsigned char>(i, 0) + 3;
@@ -1,5 +1,6 @@
1
1
  #pragma once
2
2
 
3
+ #include <cassert>
3
4
  #include <opencv2/core.hpp>
4
5
 
5
6
  class MaskedImage