-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add auto-tiling and fix weighting after merging #7
Conversation
Great job! I very sorry I am slow to respond, but I promise to thoroughly go through all your changes this week. Thank you for your work! |
> add calculate_minimal_overlap >fix data_orig_shape use in merger
Thank you very much and take your time. I think there are still several errors in there as well as points to be discussed. I just added a function for automatic calculation of a minimal overlap (if no overlap is given), but it is not yet implemented in the init of Tiler class. Further, I fixed some small errors in the merger function. |
I was moving to a new apartment. Sorry you had to wait for so long, but I've finally had a chance to look it over! In addition to making sure it's ndimensional/docstring/edge cases/tests/cleanups/etc, some more discussion points:
I was thinking about this last two evenings and to be honest I think I only got more confused :D
Again, thanks for your work, glad to see that it's not just me who wants something like that :) Would you mind to push the last version of what you have right now? Also, if you are busy, I'd be willing to continue this myself. Let me know! |
No worries. I was quite busy last week as well and hence kept you waiting with my answer as well. I think I pushed my latest version of the box already, so there is right now no improvement yet. To your points:
Totally agreed. For all functions I newly implemented I wanted to make sure that it can be used as more general functions for different tasks as well and hence I gave them the option to pass elements. But you are right. From viewpoint of the toolbox these are not necessary and typically users would not want to use these functions in different contexts. So let's do it as you suggest.
That's actually the salt in the soup. What we want to achieve is the following:
If you just normalize by the amount of visits step 4 is only true if each weight already satisfies I am back on normal track this week and would like to support you integrating what still needs to be done. So my suggestion: Would you mind to fix docstrings, check for ndimensionality of the code I suggested and add your suggested changes for passed elements and privacy of the functions? Once it's online I will check it and add what needs to be done. What do you think? |
Hey, I've finally got around to work on tiler. Sorry it takes me so long :( There were a lot of changes in master branch, so I merged it here and also did some new general changes (latter by mistake, but that's fine since I still want to merge this back to master eventually). I am now looking over your code/PR more thoroughly and want to finish this weekend.
I agree! But that shouldn't be default, rather a flag parameter in
Sure, will focus on that now. A question from me: |
Hiho, no worries. I wanted to answer already two weeks ago but somehow didn't manage. Thank you for the merge and comments.
Actually, the function Tiler. On another note: |
… dtype in merge()
I have pushed a big pack of commits. I have refactored your code to be a bit more end user friendly and consistent, hope you don't mind. I've added/modified tests, documentation, fixed CI on pull requests, and generally added few new features (sorry for doing that in your fork, but hopefully I can merge it back very soon!). Now padding is applied through Here's the adjusted code to your code examples and figures with the new changes: Under spoilerimport numpy as np
from tiler import Tiler, Merger
import matplotlib.pyplot as plt
# %% Test example for online
# parameter
data_shape = [1, 256, 256]
tile_shape = np.array([1, 64, 64])
overlap = np.array([0, 7, 20])
tiler_mode = 'wrap'
windows_supported = ['boxcar', 'triang', 'blackman', 'hamming', 'hann', 'bartlett', 'parzen', 'bohman',
'blackmanharris', 'nuttall', 'barthann', 'overlap-tile']
# image
xy = np.ogrid[0:data_shape[-2], 0:data_shape[-1]]
xy = np.sqrt(xy[0] * np.transpose(xy[0]) + xy[1] * np.transpose(xy[1]))
im = np.cos(4 * xy * np.pi / np.max(xy))[np.newaxis]
merged_images = [im, ]
# tile me
tiler = Tiler(data_shape=data_shape, tile_shape=tile_shape, overlap=overlap, channel_dimension=0)
new_shape, padding = tiler.calculate_padding()
tiler.recalculate(data_shape=new_shape)
im_padded = np.pad(im, padding, mode="reflect")
weights_sums = [np.ones(im.shape), ]
for mwin in windows_supported:
merger = Merger(tiler, window=mwin)
for tile_id, tile in tiler(im_padded):
processed_tile = tile # lambda x: x
merger.add(tile_id, processed_tile)
imf = merger.merge(extra_padding=padding)
merged_images.append(imf)
weights_sums.append(merger._unpad(merger.weights_sum, padding))
# plot images
merged_images = np.array(merged_images)[:, 0]
fig, ax = plt.subplots(nrows=4, ncols=4, figsize=[14, 14])
plt_titles = ['reference', ] + windows_supported
axm = ax.flatten()
for m, mim in enumerate(merged_images):
ima = axm[m].imshow(mim, interpolation='None')
axm[m].set_title(plt_titles[m])
plt.suptitle('Resulting Images')
plt.tight_layout()
plt.show()
# plot images
weights_sums = np.array(weights_sums)
fig2, ax2 = plt.subplots(nrows=4, ncols=4, figsize=[14, 14])
plt_titles = ['reference', ] + windows_supported
axm = ax2.flatten()
with np.errstate(divide='ignore', invalid='ignore'):
inv_weights = np.nan_to_num(weights_sums[0] / weights_sums)
inv_weights /= np.max(inv_weights, axis=(-2, -1), keepdims=True)
for m, invm in enumerate(inv_weights):
ima = axm[m].imshow(invm[0] ** 0.002, interpolation='None')
axm[m].set_title(plt_titles[m])
plt.suptitle('Inverse Weights-maps **0.002 (for display)')
plt.tight_layout()
plt.show()
# differences
for m, mim in enumerate(merged_images):
print(f"All close for window_func={plt_titles[m]}?\t {np.allclose(mim, im[0])}")
===
After thinking about it some more, I believe you are right, thank you for defending the on point! On the first thought I thought it would not work when window is not specified, but it all works out nicely even then.
I actually like the idea! I was thinking about creating few Tiler class methods for auto overlap calculation and for auto tile shape calculation. |
Hey, thank you for all your efforts. Now the code looks way nicer. :) |
I see how wrapping For example, in segmentation tasks you can have many "layers" of the same data, e.g. RGB image and class mask. In my workflow, I'd create one Tiler object and apply calculated padding to all images and with different padding modes, essentially making So I'd prefer to just explicitly return padding in the form that is easy to plug into I will merge this all into main branch later today and make a new version soon! Thank you very much for your help and discussions! |
I just briefly checked into the mechanism of the toolbox and added some-functions which might do the intended trick for:
. The code is implemented for 3D-images (hence for a 2D-image eg [1,y,x] could be provided) and needs to be slightly adjusted to work for 2D or ND.
Things to be done:
Further points are mentioned in the opened issue. :)