Ticket #1384 (closed enhancement: wontfix)
Opened 2012-08-10T18:35:13-05:00
Last modified 2013-12-06T17:45:59-06:00
Create ImageStatistics class
Reported by: | aivar | Owned by: | aivar |
---|---|---|---|
Priority: | minor | Milestone: | imagej2-b8-analysis |
Component: | ImgLib2 | Version: | |
Severity: | minor | Keywords: | |
Cc: | Blocked By: | ||
Blocking: | #794 |
Description (last modified by aivar)
Need to get statistics on an image with the minimal number of passes through the image.
For example it might include methods:
request certain things ahead of time
doMinMax();
doHistogram(int bins);
[or doHistogram(int bins, double min, double max);]
doMean();
do minimal number of passes through the image
process();
get accumulated results
double[] getMinMax();
long[] getHistogram();
double getMean;
Here if you don't specify a min/max for doHistogram the code has to take an initial pass to get min/max then another to build the histogram using that min/max.
Change History
comment:6 Changed 2012-09-07T13:06:01-05:00 by aivar
- Blocking 1128 added; 1386 removed
- Milestone changed from imagej-2.0.0-beta4 to imagej-2.0.0-beta5
comment:8 Changed 2012-10-12T12:34:34-05:00 by bdezonia
I think using the MeasurmentService all this can be accomplished. We should discuss actual examples so we can try.
(Later edit: I may have misspoke. The MeasurementService is pretty simple. Users need to provide aggregating classes to reuse computations.)
comment:9 Changed 2012-10-12T13:28:18-05:00 by aivar
Here's some simplistic pseudo-code for the sort of approach I had in mind:
class MeanFunction extends AbstractBaseFunction { double sum; int count; double mean; @Override preprocess() { // called before any pixel processing sum = 0.0; count = 0; } @Override processPixel(T pixel) { // processes pixels one by one sum += T.getRealDouble(); ++count; } @Override postprocess() { // called after all pixel processing double mean = sum / count; } getMean() { return mean; } } class AbstractBaseFunction implements Function { Function next; @Override chain(Function next) { // builds a chain of functions this.next = next; } @Override chainedPreprocess() { // preprocess the chain preprocess(); if (null != next) { next.chainedPreprocess(); } @Override chainedProcessPixel(T pixel) { // process pixel through the chain processPixel(pixel); if (null != next) { next.chainedProcessPixel(pixel); } } @Override chainedPostprocess() { // postprocess the chain postprocess(); if (null != next) { next.postprocess(); } } abstract preprocess(); abstract postprocess(); abstract processPixel(); } // usage MeanFunction meanFunction = new MeanFunction(); MinMaxFunction minMaxFunction = new MinMaxFunction(); meanFunction.chain(minMaxFunction); process(iterator, meanFunction); System.out.println("Mean is " + meanFunction.getMean()); System.out.println("Min is " + minMaxFunction.getMin() + " max is " + minMaxFunction.getMax()); . . . void process(PointSetIterator iterator, Function function) { function.chainedPreprocess(); while (iterator.hasNext()) { point = iterator.next(); function.chainedProcessPixel(point); } function.chainedPostprocess(); }
comment:10 Changed 2012-10-12T13:42:36-05:00 by aivar
This doesn't handle re-use of computations. Perhaps the chain could be a doubly-linked list, then in the preprocess( ) method you could look back up the chain for the Function you need results from (using a common helper method). Then in processPixel( ) you can call that Function's getters.
comment:11 Changed 2012-10-17T16:29:06-05:00 by curtis
I think this chaining approach is unnecessarily complex. If you have a computation (we'll call it a "module") that could benefit from the outputs of another module, there are a couple of ways of dealing with that to manage efficiency:
1) Create two modules, one that takes e.g. a Dataset and a Histogram, and computes results based on those.
2) Create one module that takes a required Dataset and an optional Histogram, and uses the Histogram results if present (or if not, just computes what is needed on the fly from the Dataset itself).
comment:12 Changed 2012-10-23T14:34:36-05:00 by bdezonia
I've implemented some ideas in the measure-engine branch of Imlib2.
Related fiji email available at: ( https://groups.google.com/forum/?fromgroups=#!topic/fiji-devel/AnYq_caJA1M)
Note that after posting my email dscho chimed in that the KNIME developers have a good start on a measurement engine that they will release to Imglib.
comment:13 Changed 2013-03-05T12:28:37-06:00 by bdezonia
- Blocking 1128 removed
(In #1128) I have been doing some work on this for our most recent beta on imglib's histogram-stuff branch. Soon I'll share with others and solicit feedback.
comment:14 Changed 2013-06-07T16:07:52-05:00 by bdezonia
- Milestone changed from imagej2-b7-ndim-data to imagej2-b8-analysis
comment:15 Changed 2013-12-06T17:45:59-06:00 by aivar
- Status changed from new to closed
- Resolution set to wontfix
My original motivation for the 'minimal number of passes' was based on the case of a huge image that is possibly paged in/out. Other situations might require other optimizations.