OpenStitching / stitching

A Python package for fast and robust Image Stitching
Apache License 2.0
2.04k stars 160 forks source link

problem with largest joint interior rectangle in Cropper class #115

Closed ChanifRusydi closed 1 year ago

ChanifRusydi commented 1 year ago

At first, im trying using the Stitcher class normally like this `import stitching from stitching import Stitcher

settings = {"detector": "akaze", "confidence_threshold": 0.2, "warper_type":"plane"} stitcher = Stitcher(**settings) stitcher = stitching.Stitcher() panorama = stitcher.stitch(["image1_60_left.jpg", "image1_60_right.jpg"])` but then I noticed it took abnormally long time to finish (let them running for like 5 minutes). When I'm doing similar thing using [stitching_detailed.py by opencv it only took at most 3 sec. I decided to look at the error message and dive into Stitching_Tutorial.ipynb and found out that 'cropper.estimate_largest_interior_rectangle(mask)' is the one who caused it.

Screenshot 2023-07-24 011830

As of right now, idk about the thing further from here. And here is the image I use

image1_60_left image1_60_right

lukasalexanderweber commented 1 year ago

Which operating system are you on?

lukasalexanderweber commented 1 year ago

You can get the same result as stitching_detailed by setting crop to false

lukasalexanderweber commented 1 year ago

And can you please share the Error Message?

ChanifRusydi commented 1 year ago

Hi, thanks for the response, I'm on Windows 10, I try setting crop to false still doesnt work " import stitching from stitching import Stitcher

def plot_image(img, figsize_in_inches=(5,5)): fig, ax = plt.subplots(figsize=figsize_in_inches) ax.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB)) plt.show()

settings = {"crop": False,"detector": "akaze", "confidence_threshold": 0.2, "warper_type":"plane" } stitcher = Stitcher(**settings) stitcher = stitching.Stitcher() panorama = stitcher.stitch(["image1_60_left.jpg", "image1_60_right.jpg"]) plot_image(panorama, (20,20)) " here is the full error message ,

"

PermissionError Traceback (most recent call last) File c:\ProgramData\Miniconda3\lib\tempfile.py:255, in _mkstemp_inner(dir, pre, suf, flags, output_type) 254 try: --> 255 fd = _os.open(file, flags, 0o600) 256 except FileExistsError:

PermissionError: [Errno 13] Permission denied: 'c:\ProgramData\Miniconda3\lib\site-packages\largestinteriorrectangle\pycache\tmpoh6rvhh5'

During handling of the above exception, another exception occurred:

KeyboardInterrupt Traceback (most recent call last) Cell In[29], line 1 ----> 1 lir = cropper.estimate_largest_interior_rectangle(mask)

File c:\ProgramData\Miniconda3\lib\site-packages\stitching\cropper.py:94, in Cropper.estimate_largest_interior_rectangle(self, mask) 91 def estimate_largest_interior_rectangle(self, mask): 92 # largestinteriorrectangle is only imported if cropping 93 # is explicitly desired (needs some time to compile at the first run!) ---> 94 import largestinteriorrectangle 96 contours, hierarchy = cv.findContours(mask, cv.RETR_TREE, cv.CHAIN_APPROX_NONE) 97 if not hierarchy.shape == (1, 1, 4) or not np.all(hierarchy == -1):

File c:\ProgramData\Miniconda3\lib\site-packages\largestinteriorrectangle__init.py:1 ----> 1 from .lir import lir, pt1, pt2 3 version__ = "0.2.0"

File c:\ProgramData\Miniconda3\lib\site-packages\largestinteriorrectangle\lir.py:1 ----> 1 from .lir_basis import largest_interior_rectangle as lir_basis 2 from .lir_within_contour import largest_interior_rectangle \ 3 as lir_within_contour 4 from .lir_within_polygon import largest_interior_rectangle \ 5 as lir_within_polygon

File c:\ProgramData\Miniconda3\lib\site-packages\largestinteriorrectangle\lir_basis.py:13 8 s_map = span_map(grid, h_adjacency, v_adjacency) 9 return biggest_span_in_span_map(s_map) 12 @nb.njit('uint32:,::1', parallel=True, cache=True) ---> 13 def horizontal_adjacency(grid): 14 result = np.zeros((grid.shape[0], grid.shape[1]), dtype=np.uint32) 15 for y in nb.prange(grid.shape[0]):

File c:\ProgramData\Miniconda3\lib\site-packages\numba\core\decorators.py:234, in _jit..wrapper(func) 230 disp = dispatcher(py_func=func, locals=locals, 231 targetoptions=targetoptions, 232 **dispatcher_args) 233 if cache: --> 234 disp.enable_caching() 235 if sigs is not None: 236 # Register the Dispatcher to the type inference mechanism, 237 # even though the decorator hasn't returned yet. 238 from numba.core import typeinfer

File c:\ProgramData\Miniconda3\lib\site-packages\numba\core\dispatcher.py:863, in Dispatcher.enable_caching(self) 862 def enable_caching(self): --> 863 self._cache = FunctionCache(self.py_func)

File c:\ProgramData\Miniconda3\lib\site-packages\numba\core\caching.py:601, in Cache.init(self, py_func) 599 self._name = repr(py_func) 600 self._py_func = py_func --> 601 self._impl = self._impl_class(py_func) 602 self._cache_path = self._impl.locator.get_cache_path() 603 # This may be a bit strict but avoids us maintaining a magic number

File c:\ProgramData\Miniconda3\lib\site-packages\numba\core\caching.py:333, in CacheImpl.init(self, py_func) 331 source_path = inspect.getfile(py_func) 332 for cls in self._locator_classes: --> 333 locator = cls.from_function(py_func, source_path) 334 if locator is not None: 335 break

File c:\ProgramData\Miniconda3\lib\site-packages\numba\core\caching.py:180, in _SourceFileBackedLocatorMixin.from_function(cls, py_func, py_file) 178 self = cls(py_func, py_file) 179 try: --> 180 self.ensure_cache_path() 181 except OSError: 182 # Cannot ensure the cache directory exists or is writable 183 return

File c:\ProgramData\Miniconda3\lib\site-packages\numba\core\caching.py:107, in _CacheLocator.ensure_cache_path(self) 105 os.makedirs(path, exist_ok=True) 106 # Ensure the directory is writable by trying to write a temporary file --> 107 tempfile.TemporaryFile(dir=path).close()

File c:\ProgramData\Miniconda3\lib\tempfile.py:545, in NamedTemporaryFile(mode, buffering, encoding, newline, suffix, prefix, dir, delete, errors) 542 if _os.name == 'nt' and delete: 543 flags |= _os.O_TEMPORARY --> 545 (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags, output_type) 546 try: 547 file = _io.open(fd, mode, buffering=buffering, 548 newline=newline, encoding=encoding, errors=errors)

File c:\ProgramData\Miniconda3\lib\tempfile.py:261, in _mkstemp_inner(dir, pre, suf, flags, output_type) 257 continue # try again 258 except PermissionError: 259 # This exception is thrown when a directory with the chosen name 260 # already exists on windows. --> 261 if (_os.name == 'nt' and _os.path.isdir(dir) and 262 _os.access(dir, _os.W_OK)): 263 continue 264 else:

File c:\ProgramData\Miniconda3\lib\genericpath.py:42, in isdir(s) 40 """Return true if the pathname refers to an existing directory.""" 41 try: ---> 42 st = os.stat(s) 43 except (OSError, ValueError): 44 return False "

the same the error message from my previous comment and using "crop to false" I guess its also related to numba, as you said in the Stitching_Tutorial.ipynb that you implement largest_interior_rectangle using numba

lukasalexanderweber commented 1 year ago

it shouldn't reach import largestinteriorrectangle if crop is set to False. See https://github.com/OpenStitching/stitching/blob/main/stitching/cropper.py#L54. Can you debug and check why it reaches this part of the code?

lukasalexanderweber commented 1 year ago

Any updates on this?

ChanifRusydi commented 1 year ago

Sorry to keep you waiting, for now I cant give you updates on this. I guess I could give you updates tomorrow

lukasalexanderweber commented 1 year ago

I moved it into the stitching package so we only have one place for issues