imagej / imagej-ops

ImageJ Ops: "Write once, run anywhere" image processing
https://imagej.net/libs/imagej-ops
BSD 2-Clause "Simplified" License
89 stars 42 forks source link

Add morphological ops #62

Closed ctrueden closed 8 years ago

ctrueden commented 10 years ago

This includes dilate, erode, open and close.

And we want them to work on arbitrary structuring elements.

ctrueden commented 10 years ago

From Gabriel Landini:

Not sure if this is relevant but just in case... if there are any plans to change the code of the erosion operator from the current IJ algorithm, please can say that it is extremely important not to change or lose the Binary Option of "pad edges" that allows or not to erode image borders. I.e., for a completely filled image, if you apply an erosion, you could consider that the border of the image is the end of the universe (and it gets eroded, as outside it is 0), or you can asume that this is a window in a much larger universe (and so you assume it is filled) and remains not eroded. Some might not worry too much about this detail, but there are good reasons for dealing with those distinct 2 cases, it would break a large amount of our code if that is changed.

tinevez commented 9 years ago

Dear all, In the past I have been working on building some morphological operators n imglib2. The WPI can be found in the morphologyops (outdated) branch of the imglib2, forked before imglib2 github repo was split in sub-repos. An example file from last year: https://github.com/imglib/imglib2/blob/morphologyops/algorithms/core/src/main/java/net/imglib2/algorithm/morphology/MorphologicalOperations.java

I am willing to resume this work, but wanted to ask first:

dietzc commented 9 years ago

Hi @tinevez,

I would somehow use imagej-ops for this implementation, due to the following reasons: If you use ImageJ-Ops, you will have all the benefits (multi-threading, replace implementationsreplacable, directly usable in combination with other existing ops etc).

On ImgLib2-Side everything related to Shape, Neighborhood etc should be used or extended. For example arbitrary structuring elements (i.e. shapes) are one open issue which we will tackle at the upcoming hackathon when it comes to ROIs (correct me if I'm wrong @tpietzsch ).

On Ops side you can already reuse some existing operations, for example https://github.com/imagej/imagej-ops/blob/master/src/main/java/net/imagej/ops/neighborhood/MapNeighborhood.java. The TODOs in the operations seem to be not valid anymore, as each neighborhood is automatically run in parallel since internally the ParallelMap is used.

The cool thing is, if you use MapNeighborhood, your MorphOperation will automatically benefit if someone writes e.g. a super fast version of MapNeighborhood for 2d ArrayImgs (as an example).

To conclude my suggestions here (and again, @tpietzsch @ctrueden @hinerm etc) may correct me if I'm wrong: Everything related to Neighborhood and Shape should really be done in imglib2. The MorphOp itself should live in imagej-ops.

Btw @iarganda also wanted to implement some MorphOps. Maybe you can join forces here.

ctrueden commented 9 years ago

@tinevez I added you to the OPS developer team on GitHub. Please let us know if you need anything else to support this work.

ctrueden commented 9 years ago

@iarganda I invited you too.

tinevez commented 9 years ago

Hi all. Thank for all of this. I probably overlooked the problem a bit: last year I started an imglib2 package that could do morp-ops. I am porting it back to modern imglib2, but this will take me time. You can find it here: https://github.com/tinevez/imglib2-algorithm/tree/morphology

WARNING DOES NOT COMPILE YET It relies on the Shape interface by @tpietzsch for the structuring elements, so right now this part will live in imglib2-algorithm.

After this, there are two classes that offer static utils

I guess the imagej-ops class can be based on the imglib2 classes rather than the opposite, no?

dietzc commented 9 years ago

All the Shape and Neighborhood should really live in imglib2-ROI or imglib2-algorithm or somewhere in the imglib2 domain (this is up to @tpietzsch :-)). I think extending Shapes to work with arbitrary StructuringElements or better implementing a Shape which can do that is a good approach.

In imagej-ops I would put the actual implementations of morphological ops, based on Shapes/Neighborhoods. This means offering interfaces and implementations for Erode / Dilate / Open / Close etc. based on the Shapes in imglib2, such that someone can call for exampleops.run("erode", image, stucturingElement). If those implementations make use of other imagej-ops (for example MapNeighborhood) then they directly benefit from all the multi-threading and optimization taking place underneath the hood and you don't have to care about multi-threading at all. Additionally, if you use the imagej-ops class hierarchy, you also can apply your algorithm on arbitrary dimension combinations in your input images (e.g. run the morphological op plane-wise in a video etc. see: HyperSlice and the corresponding JUnits tests for examples).

But to answer your question: Yes. ImageJ-Ops can also just be wrappers for imglib2-algorithms (e.g. as we do it with Gauss).

tinevez commented 9 years ago

Ok @dietzc, There will be high-level calls both for ops and imglib2, that both call the imglib2 strels, but are independent. Ok?

dietzc commented 9 years ago

Sure, sounds like a plan. I think as soon as the Shape can take arbitrary StructuringElements, the rest will be straight-foward. So I agree, most of the effort has to be spend on imglib2 side I guess. Because once you have that, you can write simple Ops (e.g. erode, dilate) which are then consumed by the Map op.

Let me know if I can support you somehow!

iarganda commented 9 years ago

Thanks @ctrueden!

tinevez commented 9 years ago

Hi all,

WIP:

What is missing:

What is not here:

Opinions as what should be done next is welcome. JY

dietzc commented 9 years ago

Hi @tinevez, this looks great. I just have some minor suggestions/questions:

Again, thats great stuff. I'm really looking forward to see it in ops/imagej2/knime/fiji etc :-)

tinevez commented 9 years ago

Thanks @dietzc

  1. Ok for the OutOfBounds strategy. Anyway I have to rewrite the MorphologicalOperations class and split it in individual operations. Right now, the methods are not imglibiesque enough. As @tpietzsch, @StephanPreibisch and @Squareys advised, there should also be methods that take a RandomAccessible as source and write results in a provided IterableInterval.
  2. Binary image optimization: great idea.
  3. ImageJ ops version: Ok!
  4. The neighborhood is @tpietzsch design, after I think several iterations. I do not know what's his plan for imglib2-roi.

Thank again!

ctrueden commented 9 years ago

I just browsed the Imglib2 Morphological Operations wiki page, and holy cow has a lot of work gone into this over the past two years. And it's still not merged to master anywhere? What are the obstacles there? Is there anything a student at LOCI or Uni Konstanz could do to help?

dietzc commented 9 years ago

@tibuch will work on this after he finishes the view stuff. Should be ready end of August.

ctrueden commented 8 years ago

@landinig wrote:

you could consider that the border of the image is the end of the universe (and it gets eroded, as outside it is 0), or you can asume that this is a window in a much larger universe (and so you assume it is filled) and remains not eroded. Some might not worry too much about this detail, but there are good reasons for dealing with those distinct 2 cases, it would break a large amount of our code if that is changed.

Just wanted to comment that both of those cases are fully covered in ImgLib2 by the use of "out of bounds strategies". So I think there is no problem here. There is even an out of bounds strategy which extends the edge according to the border values, which might be nice in some cases here too.

ctrueden commented 8 years ago

Addressed in #358.