Skip to content
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

FrequencyBandImageFilter accepts lambdas for filtering frequencies #149

Merged
merged 2 commits into from
Nov 13, 2018

Conversation

dzenanz
Copy link
Member

@dzenanz dzenanz commented Nov 7, 2018

This filter should enable custom filtering via the functor, e.g. implementing Butterworth algorithm.

@blowekamp
Copy link
Member

Should FrequencyBandImageFilter be derived from the UnaryGeneratorFilter?

Copy link
Contributor

@phcerdan phcerdan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great!!! Functors working with frequencies... the dream.

I wonder if we could refactor all the functor love into a base class.
And the old behavior (the boxFunctor), just out in its own header as a functor struct (a class with operator() and the options RadialBand etc, as members)

@dzenanz
Copy link
Member Author

dzenanz commented Nov 7, 2018

@blowekamp maybe it should. I was busy trying to get the functionality, It didn't even occur to me that I could derive it from UnaryGenerator. But since the functor should take the FrequencyIterator instead of just the pixel value, I am afraid deriving from UnaryGenerator might be more trouble than it is worth.

Also, UnaryFunctor filter existed when FrequencyBandImageFilter was originally written. It must have made some sense not to derive it from UnaryFunctor.

@phcerdan
Copy link
Contributor

phcerdan commented Nov 7, 2018

The great lambdas/functor work of @blowekamp in UnaryGenerator was posterior to the development of this filter.

@dzenanz
Copy link
Member Author

dzenanz commented Nov 7, 2018

@phcerdan Do not confuse UnaryGenerator filter which is pretty new, and UnaryFunctor filter which is very old.

@dzenanz
Copy link
Member Author

dzenanz commented Nov 7, 2018

@phcerdan If backwards compatibility is not a major issue, we could refactor the filter as you propose. What do others think? @thewtex @hjmjohnson @blowekamp

@blowekamp
Copy link
Member

+1 for separating the FrequencyBandImageFilter into a "Frequency Generator Filter" base class and a "Box Functor". They could come together into the current class similar to the "AddImageFilter" combines the BinaryGeneratorImageFilter and the AddFunctor.

@phcerdan
Copy link
Contributor

phcerdan commented Nov 7, 2018

I think the only module using it (heaviliy) is ITKIsotropicWavelets, and I can fix that when needed. Also, to avoid breakage of backwards compatibility, we can create the functor, and then create a FrequencyBandImageFilter just plugging together the base class and the new boxFunctor.

@phcerdan
Copy link
Contributor

phcerdan commented Nov 7, 2018

It seems I agree with @blowekamp 😄 (submitted the comment almost at the same time)

@thewtex
Copy link
Member

thewtex commented Nov 7, 2018

I don't think the frequency classes have been in a final release, so there should not be backwards compatibility concerns. 🆕

@dzenanz
Copy link
Member Author

dzenanz commented Nov 7, 2018

Great! Let me verify that this works as intended, then I can polish it per suggestions.

@phcerdan
Copy link
Contributor

phcerdan commented Nov 7, 2018

By the way, BandPassFunctor should be a better name.

@dzenanz
Copy link
Member Author

dzenanz commented Nov 7, 2018

A better name for what is now known as BoxFunctor, or for what is now known as FrequencyBandImageFilter?

Edit: Butterworth is also a BandPassFunctor.

@phcerdan
Copy link
Contributor

phcerdan commented Nov 7, 2018

A better name for BoxFunctor.

And maybe we can change the name from FrequencyBandImageFilter to FrequencyBandPassImageFilter. I like the name with ...Pass but could be misleading because it works as well as a BandBlock depending on options...

@hjmjohnson
Copy link
Member

Thanks all. This is good work.

@blowekamp
Copy link
Member

With the new GitHub workflow hopefully it is easier to manage topic branches. Please separate the nice documentation improvement in itkUnaryGeneratorFilter into separate commit to help keep a clear history.

@dzenanz
Copy link
Member Author

dzenanz commented Nov 8, 2018

This is working as expected. I will refactor this patch to separate the box functor into its own class and add additional Butterworth functor.

@dzenanz
Copy link
Member Author

dzenanz commented Nov 8, 2018

In the end I did not add Butterworth filter here, but as its implementation is short it can be defined in appropriately adjusted form by the user.

Copy link
Member

@blowekamp blowekamp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks really good!

Copy link
Contributor

@phcerdan phcerdan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BoxFunctor should be changed to the more descriptive BandPassFunctor. Box is not describing what the functor is doing.

@dzenanz dzenanz changed the title WIP: FrequencyBandImageFilter accepts lambdas for filtering frequencies FrequencyBandImageFilter accepts lambdas for filtering frequencies Nov 9, 2018
@dzenanz
Copy link
Member Author

dzenanz commented Nov 9, 2018

I think this is ready for merging. Can you re-review please?

Copy link
Contributor

@phcerdan phcerdan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great, thanks!!

@blowekamp
Copy link
Member

Looks good!

Does this class of filters support streaming? If not then EnlargeOutputRequestedRegion should be overloaded to make the output the largest possible.

@dzenanz
Copy link
Member Author

dzenanz commented Nov 9, 2018

@blowekamp why should the OutputRequestedRegion be enlarged?

@blowekamp
Copy link
Member

The default behavior of the ITK pipeline (e.g. ImageToImageFilter) is to have the requested region of the output be copied to the inputs. This enables streaming for basic filters like the unary functors etc.. This filter operates with frequency space, I believe an output pixel needs more information than just the corresponding input pixel.

One way to disable streaming is to overload EnlargeOutputRequestedRegion to set the produced region to always be the largest possible region. By default the output region gets copied to the input. This is done when the filter only works on the whole image.

Other options depend on if and how the filter can stream.

@dzenanz
Copy link
Member Author

dzenanz commented Nov 9, 2018

This filter is templated over the frequency iterator. The iterator uses the meta-information to know the frequency of the currently iterated pixel. And a reference to this iterator is passed to the functor, so it can access the frequency etc. Which means that this filter should probably be able to stream. I haven't tested that, though.

@blowekamp
Copy link
Member

This filter is templated over the frequency iterator. The iterator uses the meta-information to know the frequency of the currently iterated pixel. And a reference to this iterator is passed to the functor, so it can access the frequency etc. Which means that this filter should probably be able to stream. I haven't tested that, though.

If the filter only has part of the input, then the boundary conditions would likely cause difference frequencies to be processes by the iterator.

It may be that the filter can produce an arbitrary output but needs the full input. In that case the GenerateInputRequestedRegion should be overloaded to set the input's requested region to the largest possible.

@dzenanz
Copy link
Member Author

dzenanz commented Nov 9, 2018

This is essentially a per-pixel filter. The only complication is that the iterator "knows" the frequency/index of the pixel, which is used as a criteria for modifying the value. I don't think the input's region needs to be expanded.

@blowekamp
Copy link
Member

Ok, I got how the iterator operate now. Thanks!

@phcerdan
Copy link
Contributor

phcerdan commented Nov 9, 2018

For me, it helps to think that the input and output images are already in the frequency domain. The only role of the frequency iterators is to avoid the change of the algorithms depending on the Fourier transform or frequency layout.
So the developer thinks directly in frequencies, instead of what indices correspond to what frequencies.

Copy link
Member

@thewtex thewtex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some warnings identified by the macOS build:

https://open.cdash.org/viewBuildError.php?type=1&buildid=5622223

@dzenanz
Copy link
Member Author

dzenanz commented Nov 10, 2018

@thewtex I fixed that with the latest push. All checks are now passing.

Copy link
Member

@thewtex thewtex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice @dzenanz !

Some minor issues noted inline.

}
else // Cut-off box taking into account max absolute frequency.
{
w = freqIt.GetFrequency();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

w?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wector frequency? uv? @phcerdan might give the answer 😄

* This filter is templated over a TFrequencyIterator depending on the
* frequency layout of the input image.
* Images in the dual space can be acquired experimentally, from scattering exaperiments or other techniques.
* The layout of these images is the same as spatial domain images. Use \ref FrequencyImageRegionIteratorWithIndex
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the meaning of this sentence? Can it be reworded to clarify that meaning?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reworded it. @phcerdan could double-check.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

UnaryFrequencyDomainFilter accepts lambdas for filtering frequencies.
Functor setting is modeled after UnaryGeneratorImageFilter.
@dzenanz dzenanz merged commit fc23208 into InsightSoftwareConsortium:master Nov 13, 2018
@phcerdan
Copy link
Contributor

Sorry, I was unplugged on the weekend, sorry for not answering on time. But I would have approved, scalarFrequency is a way better name than the old w. Thanks @dzenanz

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants