Esempio n. 1
0
        public static IImageStatistics Create(ImageProperties imageProperties, ushort[] array)
        {
            using (MyStopWatch.Measure()) {
                long   sum            = 0;
                long   squareSum      = 0;
                int    count          = array.Count();
                ushort min            = ushort.MaxValue;
                ushort oldmin         = min;
                ushort max            = 0;
                ushort oldmax         = max;
                long   maxOccurrences = 0;
                long   minOccurrences = 0;

                /* Array mapping: pixel value -> total number of occurrences of that pixel value */
                int[] pixelValueCounts = new int[ushort.MaxValue + 1];
                for (var i = 0; i < array.Length; i++)
                {
                    ushort val = array[i];

                    sum       += val;
                    squareSum += (long)val * val;

                    pixelValueCounts[val]++;

                    min = Math.Min(min, val);
                    if (min != oldmin)
                    {
                        minOccurrences = 0;
                    }
                    if (val == min)
                    {
                        minOccurrences += 1;
                    }

                    max = Math.Max(max, val);
                    if (max != oldmax)
                    {
                        maxOccurrences = 0;
                    }
                    if (val == max)
                    {
                        maxOccurrences += 1;
                    }

                    oldmin = min;
                    oldmax = max;
                }

                double mean     = sum / (double)count;
                double variance = (squareSum - count * mean * mean) / (count);
                double stdev    = Math.Sqrt(variance);

                var    occurrences = 0;
                double median = 0d;
                int    median1 = 0, median2 = 0;
                var    medianlength = array.Length / 2.0;

                /* Determine median out of histogram array */
                for (ushort i = 0; i < ushort.MaxValue; i++)
                {
                    occurrences += pixelValueCounts[i];
                    if (occurrences > medianlength)
                    {
                        median1 = i;
                        median2 = i;
                        break;
                    }
                    else if (occurrences == medianlength)
                    {
                        median1 = i;
                        for (int j = i + 1; j <= ushort.MaxValue; j++)
                        {
                            if (pixelValueCounts[j] > 0)
                            {
                                median2 = j;
                                break;
                            }
                        }
                        break;
                    }
                }
                median = (median1 + median2) / 2.0;

                /* Determine median Absolute Deviation out of histogram array and previously determined median
                 * As the histogram already has the values sorted and we know the median,
                 * we can determine the mad by beginning from the median and step up and down
                 * By doing so we will gain a sorted list automatically, because MAD = DetermineMedian(|xn - median|)
                 * So starting from the median will be 0 (as median - median = 0), going up and down will increment by the steps
                 */

                var medianAbsoluteDeviation = 0.0d;
                occurrences = 0;
                var idxDown = median1;
                var idxUp   = median2;
                while (true)
                {
                    if (idxDown >= 0 && idxDown != idxUp)
                    {
                        occurrences += pixelValueCounts[idxDown] + pixelValueCounts[idxUp];
                    }
                    else
                    {
                        occurrences += pixelValueCounts[idxUp];
                    }

                    if (occurrences > medianlength)
                    {
                        medianAbsoluteDeviation = Math.Abs(idxUp - median);
                        break;
                    }

                    idxUp++;
                    idxDown--;
                    if (idxUp > ushort.MaxValue)
                    {
                        break;
                    }
                }

                var maxPossibleValue = (ushort)((1 << imageProperties.BitDepth) - 1);
                var factor           = (double)HISTOGRAMRESOLUTION / maxPossibleValue;
                var histogram        = pixelValueCounts
                                       .Select((value, index) => new { Index = index, Value = value })
                                       .GroupBy(
                    x => Math.Floor((double)Math.Min(maxPossibleValue, x.Index) * factor),
                    x => x.Value)
                                       .Select(g => new OxyPlot.DataPoint(g.Key, g.Sum()))
                                       .OrderBy(item => item.X).ToImmutableList();

                var statistics = new ImageStatistics();
                statistics.StDev  = stdev;
                statistics.Mean   = mean;
                statistics.Median = median;
                statistics.MedianAbsoluteDeviation = medianAbsoluteDeviation;
                statistics.Max            = max;
                statistics.MaxOccurrences = maxOccurrences;
                statistics.Min            = min;
                statistics.MinOccurrences = minOccurrences;
                statistics.Histogram      = histogram;
                return(statistics);
            }
        }
Esempio n. 2
0
 public ImageData(IImageArray imageArray, int width, int height, int bitDepth, bool isBayered, ImageMetaData metaData)
 {
     this.Data                  = imageArray;
     this.MetaData              = metaData;
     isBayered                  = metaData.Camera.SensorType != SensorType.Monochrome ? true : isBayered;
     this.Properties            = new ImageProperties(width: width, height: height, bitDepth: bitDepth, isBayered: isBayered, gain: metaData.Camera.Gain);
     this.StarDetectionAnalysis = new StarDetectionAnalysis();
     this.Statistics            = new Nito.AsyncEx.AsyncLazy <IImageStatistics>(async() => await Task.Run(() => ImageStatistics.Create(this)));
 }