public static Image <Rgb24> FrameZoomSpectrogram(Image <Rgb24> bmp1, Image <Rgb24> titleBar, TimeSpan startOffset, TimeSpan xAxisPixelDuration, TimeSpan xAxisTicInterval, int nyquist, int herzInterval)
        {
            TimeSpan fullDuration = TimeSpan.FromTicks(xAxisPixelDuration.Ticks * bmp1.Width);

            // init frequency scale
            int frameSize = bmp1.Height * 2; // THIS MIGHT BECOME A BUG ONE DAY!!!!!
            var freqScale = new FrequencyScale(nyquist, frameSize, herzInterval);

            SpectrogramTools.DrawGridLinesOnImage((Image <Rgb24>)bmp1, startOffset, fullDuration, xAxisTicInterval, freqScale);
            int trackHeight = 20;

            // put start offset into a datetime object.
            var dto = default(DateTimeOffset);

            dto = dto + startOffset;

            Image <Rgb24> timeBmp = ImageTrack.DrawTimeTrack(fullDuration, dto, bmp1.Width, trackHeight);
            int           imageHt = bmp1.Height + titleBar.Height + trackHeight + 1;

            Image <Rgb24> compositeBmp = new Image <Rgb24>(bmp1.Width, imageHt); //get canvas for entire image

            compositeBmp.Mutate(gr =>
            {
                gr.Clear(Color.Black);
                int offset = 0;
                gr.DrawImage(titleBar, 0, offset); //draw in the top time scale
                offset += titleBar.Height;
                gr.DrawImage(bmp1, 0, offset);     //draw
                offset += bmp1.Height;
                gr.DrawImage(timeBmp, 0, offset);  //draw
            });

            return(compositeBmp);
        }
Esempio n. 2
0
        public static Image <Rgb24> FrameSliceOf3DSpectrogram_DayOfYear(Image <Rgb24> bmp1, Image <Rgb24> titleBar, int year, int dayOfYear, TimeSpan xInterval, int herzValue, FileInfo sunriseSetData, int nyquistFreq)
        {
            Image <Rgb24> suntrack = SunAndMoon.AddSunTrackToImage(bmp1.Width, sunriseSetData, year, dayOfYear);

            bmp1.Mutate(g =>
            {
                Pen pen        = new Pen(Color.White, 1);
                var stringFont = Drawing.Arial12;

                //Font stringFont = Drawing.Tahoma9;

                DateTime theDate  = new DateTime(year, 1, 1).AddDays(dayOfYear - 1);
                string dateString = $"{year} {DataTools.MonthNames[theDate.Month - 1]} {theDate.Day:d2}";
                g.DrawText(dateString, stringFont, Color.Wheat, new PointF(10, 3));
            });

            TimeSpan xAxisPixelDuration = TimeSpan.FromSeconds(60);
            var      minuteOffset       = TimeSpan.Zero;
            double   secondsDuration    = xAxisPixelDuration.TotalSeconds * bmp1.Width;
            TimeSpan fullDuration       = TimeSpan.FromSeconds(secondsDuration);

            // init frequency scale
            int herzInterval = 1000;
            int frameSize    = bmp1.Height;
            var freqScale    = new DSP.FrequencyScale(nyquistFreq, frameSize, herzInterval);

            SpectrogramTools.DrawGridLinesOnImage((Image <Rgb24>)bmp1, minuteOffset, fullDuration, xInterval, freqScale);

            int trackHeight      = 20;
            int imageHt          = bmp1.Height + trackHeight + trackHeight + trackHeight;
            var xAxisTicInterval = TimeSpan.FromMinutes(60); // assume 60 pixels per hour
            var timeScale24Hour  = ImageTrack.DrawTimeTrack(fullDuration, minuteOffset, xAxisTicInterval, bmp1.Width, trackHeight, "hours");

            var imageList = new List <Image <Rgb24> >
            {
                titleBar,
                timeScale24Hour,
                suntrack,
                bmp1,
                timeScale24Hour
            };
            var compositeBmp = ImageTools.CombineImagesVertically(imageList);

            // trackHeight = compositeBmp.Height;
            // Image<Rgb24> timeScale12Months = ImageTrack.DrawYearScaleVertical(40, trackHeight);
            // Image<Rgb24> freqScale = DrawFreqScale_vertical(40, trackHeight, HerzValue, nyquistFreq);

            imageList = new List <Image <Rgb24> >();

            // imageList.Add(timeScale12Months);
            imageList.Add(compositeBmp);

            // imageList.Add(freqScale);
            compositeBmp = ImageTools.CombineImagesInLine(imageList.ToArray());

            return(compositeBmp);
        }
Esempio n. 3
0
        public static Image FrameSliceOf3DSpectrogram_DayOfYear(Image bmp1, Image titleBar, int year, int dayOfYear, TimeSpan xInterval, int herzValue, FileInfo sunriseSetData, int nyquistFreq)
        {
            Bitmap suntrack = SunAndMoon.AddSunTrackToImage(bmp1.Width, sunriseSetData, year, dayOfYear);

            Graphics g          = Graphics.FromImage(bmp1);
            Pen      pen        = new Pen(Color.White);
            Font     stringFont = new Font("Arial", 12);

            //Font stringFont = new Font("Tahoma", 9);

            DateTime theDate    = new DateTime(year, 1, 1).AddDays(dayOfYear - 1);
            string   dateString = string.Format("{0} {1} {2:d2}", year, DataTools.MonthNames[theDate.Month - 1], theDate.Day);

            g.DrawString(dateString, stringFont, Brushes.Wheat, new PointF(10, 3));

            TimeSpan xAxisPixelDuration = TimeSpan.FromSeconds(60);
            var      minuteOffset       = TimeSpan.Zero;
            double   secondsDuration    = xAxisPixelDuration.TotalSeconds * bmp1.Width;
            TimeSpan fullDuration       = TimeSpan.FromSeconds(secondsDuration);

            // init frequency scale
            int herzInterval = 1000;
            int frameSize    = bmp1.Height;
            var freqScale    = new DSP.FrequencyScale(nyquistFreq, frameSize, herzInterval);

            SpectrogramTools.DrawGridLinesOnImage((Bitmap)bmp1, minuteOffset, fullDuration, xInterval, freqScale);

            int trackHeight      = 20;
            int imageHt          = bmp1.Height + trackHeight + trackHeight + trackHeight;
            var xAxisTicInterval = TimeSpan.FromMinutes(60); // assume 60 pixels per hour
            var timeScale24Hour  = ImageTrack.DrawTimeTrack(fullDuration, minuteOffset, xAxisTicInterval, bmp1.Width, trackHeight, "hours");

            var imageList = new List <Image>();

            imageList.Add(titleBar);
            imageList.Add(timeScale24Hour);
            imageList.Add(suntrack);
            imageList.Add(bmp1);
            imageList.Add(timeScale24Hour);
            Image compositeBmp = ImageTools.CombineImagesVertically(imageList.ToArray());

            // trackHeight = compositeBmp.Height;
            // Bitmap timeScale12Months = ImageTrack.DrawYearScaleVertical(40, trackHeight);
            // Bitmap freqScale = DrawFreqScale_vertical(40, trackHeight, HerzValue, nyquistFreq);

            imageList = new List <Image>();

            // imageList.Add(timeScale12Months);
            imageList.Add(compositeBmp);

            // imageList.Add(freqScale);
            compositeBmp = ImageTools.CombineImagesInLine(imageList.ToArray());

            return(compositeBmp);
        }
        // #######################################################################################################################################
        // ### ABOVE METHODS DRAW TIME GRID LINES ON SPECTROGRAMS ####################################################################################
        // #######################################################################################################################################

        public static Image <Rgb24> GetImageFullyAnnotated(Image <Rgb24> image, string title, int[,] gridLineLocations, TimeSpan duration)
        {
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            FrequencyScale.DrawFrequencyLinesOnImage((Image <Rgb24>)image, gridLineLocations, includeLabels: true);

            var titleBar       = LDSpectrogramRGB.DrawTitleBarOfGrayScaleSpectrogram(title, image.Width);
            var timeBmp        = ImageTrack.DrawTimeTrack(duration, image.Width);
            var compositeImage = ImageTools.CombineImagesVertically(titleBar, timeBmp, image, timeBmp);

            return(compositeImage);
        }
Esempio n. 5
0
        public static Image FrameSliceOf3DSpectrogram_ConstantFreq(Image bmp1, Image titleBar, TimeSpan xInterval, int herzValue, FileInfo sunriseSetData, int nyquistFreq)
        {
            SunAndMoon.AddSunRiseSetLinesToImage((Bitmap)bmp1, sunriseSetData, 0, 365, 1); // assume full year and 1px/day

            var g          = Graphics.FromImage(bmp1);
            var pen        = new Pen(Color.White);
            var stringFont = new Font("Arial", 12);
            var str        = $"Freq = {herzValue} Hz";

            g.DrawString(str, stringFont, Brushes.Wheat, new PointF(10, 7));

            var    xAxisPixelDuration = TimeSpan.FromSeconds(60);
            var    startOffset        = TimeSpan.Zero;
            double secondsDuration    = xAxisPixelDuration.TotalSeconds * bmp1.Width;
            var    fullDuration       = TimeSpan.FromSeconds(secondsDuration);

            // init frequency scale
            int herzInterval = 1000;
            int frameSize    = bmp1.Height;
            var freqScale    = new DSP.FrequencyScale(nyquistFreq, frameSize, herzInterval);

            SpectrogramTools.DrawGridLinesOnImage((Bitmap)bmp1, startOffset, fullDuration, xInterval, freqScale);

            int trackHeight      = 20;
            var xAxisTicInterval = TimeSpan.FromMinutes(60); // assume 60 pixels per hour
            var timeScale24Hour  = ImageTrack.DrawTimeTrack(fullDuration, startOffset, xAxisTicInterval, bmp1.Width, trackHeight, "hours");

            var imageList = new List <Image> {
                titleBar, timeScale24Hour, bmp1, timeScale24Hour
            };
            var compositeBmp = ImageTools.CombineImagesVertically(imageList.ToArray());

            if (compositeBmp == null)
            {
                throw new ArgumentNullException(nameof(compositeBmp));
            }

            trackHeight = compositeBmp.Height;
            Bitmap timeScale12Months = ImageTrack.DrawYearScaleVertical(40, trackHeight);
            Bitmap freqScaleImage    = DrawFreqScale_vertical(40, trackHeight, herzValue, nyquistFreq);

            imageList = new List <Image> {
                timeScale12Months, compositeBmp, freqScaleImage
            };
            compositeBmp = ImageTools.CombineImagesInLine(imageList.ToArray());

            return(compositeBmp);
        }
Esempio n. 6
0
        public Image <Rgb24> GetImageFullyAnnotated(Image <Rgb24> image, string title, int[,] gridLineLocations, Color?tag = null)
        {
            if (image == null)
            {
                throw new ArgumentNullException(nameof(image));
            }

            FrequencyScale.DrawFrequencyLinesOnImage(image, gridLineLocations, includeLabels: true);

            var titleBar = DrawTitleBarOfGrayScaleSpectrogram(title, image.Width, tag);
            var timeBmp  = ImageTrack.DrawTimeTrack(this.Duration, image.Width);
            var list     = new List <Image <Rgb24> > {
                titleBar, timeBmp, image, timeBmp
            };
            var compositeImage = ImageTools.CombineImagesVertically(list);

            return(compositeImage);
        }
Esempio n. 7
0
        /// <summary>
        /// Can be used for visual checking and debugging purposes.
        /// </summary>
        public static void DrawNormalisedIndexMatrices(DirectoryInfo dir, string baseName, Dictionary <string, double[, ]> dictionary)
        {
            var list = new List <Image>();

            foreach (string key in ContentSignatures.IndexNames)
            {
                var bmp = ImageTools.DrawReversedMatrixWithoutNormalisation(dictionary[key]);

                // need to rotate spectrogram to get correct orientation.
                bmp.RotateFlip(RotateFlipType.Rotate270FlipNone);

                // draw grid lines and add axis scales
                var xAxisPixelDuration = TimeSpan.FromSeconds(60);
                var fullDuration       = TimeSpan.FromTicks(xAxisPixelDuration.Ticks * bmp.Width);
                var freqScale          = new FrequencyScale(11025, 512, 1000);
                SpectrogramTools.DrawGridLinesOnImage((Bitmap)bmp, TimeSpan.Zero, fullDuration, xAxisPixelDuration, freqScale);
                const int trackHeight        = 20;
                var       recordingStartDate = default(DateTimeOffset);
                var       timeBmp            = ImageTrack.DrawTimeTrack(fullDuration, recordingStartDate, bmp.Width, trackHeight);
                var       array = new Image[2];
                array[0] = bmp;
                array[1] = timeBmp;
                var image = ImageTools.CombineImagesVertically(array);

                // add a header to the spectrogram
                var      header = new Bitmap(image.Width, 20);
                Graphics g      = Graphics.FromImage(header);
                g.Clear(Color.LightGray);
                g.SmoothingMode     = SmoothingMode.AntiAlias;
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.PixelOffsetMode   = PixelOffsetMode.HighQuality;
                g.DrawString(key, new Font("Tahoma", 9), Brushes.Black, 4, 4);
                list.Add(ImageTools.CombineImagesVertically(new List <Image>(new[] { header, image })));
            }

            // save the image - the directory for the path must exist
            var path       = Path.Combine(dir.FullName, baseName + "__Towsey.Acoustic.GreyScaleImages.png");
            var indexImage = ImageTools.CombineImagesInLine(list);

            indexImage?.Save(path);
        }
        /// <summary>
        /// Can be used for visual checking and debugging purposes.
        /// </summary>
        public static void DrawNormalisedIndexMatrices(DirectoryInfo dir, string baseName, Dictionary <string, double[, ]> dictionary)
        {
            var list = new List <Image <Rgb24> >();

            foreach (string key in ContentSignatures.IndexNames)
            {
                var bmp = ImageTools.DrawReversedMatrixWithoutNormalisation(dictionary[key]);

                // need to rotate spectrogram to get correct orientation.
                bmp.RotateFlip(RotateFlipType.Rotate270FlipNone);

                // draw grid lines and add axis scales
                var xAxisPixelDuration = TimeSpan.FromSeconds(60);
                var fullDuration       = TimeSpan.FromTicks(xAxisPixelDuration.Ticks * bmp.Width);
                var freqScale          = new FrequencyScale(11025, 512, 1000);
                SpectrogramTools.DrawGridLinesOnImage((Image <Rgb24>)bmp, TimeSpan.Zero, fullDuration, xAxisPixelDuration, freqScale);
                const int trackHeight        = 20;
                var       recordingStartDate = default(DateTimeOffset);
                var       timeBmp            = ImageTrack.DrawTimeTrack(fullDuration, recordingStartDate, bmp.Width, trackHeight);

                var image = ImageTools.CombineImagesVertically(bmp, timeBmp);

                // add a header to the spectrogram
                var header = Drawing.NewImage(image.Width, 20, Color.LightGray);
                header.Mutate(g =>
                {
                    g.DrawText(key, Drawing.Tahoma9, Color.Black, new PointF(4, 4));
                    list.Add(ImageTools.CombineImagesVertically(header, image));
                });
            }

            // save the image - the directory for the path must exist
            var path       = Path.Combine(dir.FullName, baseName + "__Towsey.Acoustic.GreyScaleImages.png");
            var indexImage = ImageTools.CombineImagesInLine(list);

            indexImage?.Save(path);
        }
        /// <summary>
        /// This method draws a spectrogram with other useful information attached.
        /// </summary>
        /// <param name="sonogram">of BaseSonogram class.</param>
        /// <param name="events">a list of acoustic events.</param>
        /// <param name="plots">a list of plots relevant to the spectrogram scores.</param>
        /// <param name="hits">not often used - can be null.</param>
        public static Image <Rgb24> GetSonogramPlusCharts(
            BaseSonogram sonogram,
            List <AcousticEvent> events,
            List <Plot> plots,
            double[,] hits)
        {
            var spectrogram = sonogram.GetImage(doHighlightSubband: false, add1KHzLines: true, doMelScale: false);

            Contract.RequiresNotNull(spectrogram, nameof(spectrogram));

            var height    = spectrogram.Height;
            var frameSize = sonogram.Configuration.WindowSize;

            // init with linear frequency scale and draw freq grid lines on image
            int hertzInterval = 1000;

            if (height < 200)
            {
                hertzInterval = 2000;
            }

            var freqScale = new FrequencyScale(sonogram.NyquistFrequency, frameSize, hertzInterval);

            FrequencyScale.DrawFrequencyLinesOnImage(spectrogram, freqScale.GridLineLocations, includeLabels: true);

            // draw event outlines onto spectrogram.
            if (events != null && events.Count > 0)
            {
                // set colour for the events
                foreach (AcousticEvent ev in events)
                {
                    ev.BorderColour = AcousticEvent.DefaultBorderColor;
                    ev.ScoreColour  = AcousticEvent.DefaultScoreColor;
                    ev.DrawEvent(spectrogram, sonogram.FramesPerSecond, sonogram.FBinWidth, height);
                }
            }

            // now add in hits to the spectrogram image.
            if (hits != null)
            {
                spectrogram = Image_MultiTrack.OverlayScoresAsRedTransparency(spectrogram, hits);

                // following line needs to be reworked if want to call OverlayRainbowTransparency(hits);
                //image.OverlayRainbowTransparency(hits);
            }

            int pixelWidth = spectrogram.Width;
            var titleBar   = LDSpectrogramRGB.DrawTitleBarOfGrayScaleSpectrogram("TITLE", pixelWidth);
            var timeTrack  = ImageTrack.DrawTimeTrack(sonogram.Duration, pixelWidth);

            var imageList = new List <Image <Rgb24> >
            {
                titleBar,
                timeTrack,
                spectrogram,
                timeTrack,
            };

            if (plots != null)
            {
                foreach (var plot in plots)
                {
                    // Next line assumes plot data normalised in 0,1
                    var plotImage = plot.DrawAnnotatedPlot(ImageTrack.DefaultHeight);

                    // the following draws same plot without the title.
                    //var plotImage = ImageTrack.DrawScoreArrayTrack(plot.data, plot.threshold, pixelWidth);
                    imageList.Add(plotImage);
                }
            }

            var compositeImage = ImageTools.CombineImagesVertically(imageList);

            return(compositeImage);
        }
Esempio n. 10
0
        /// <summary>
        /// Converts summary indices to a tracks image, one track for each index.
        /// </summary>
        public static Image <Rgb24> DrawImageOfSummaryIndices(
            Dictionary <string, IndexProperties> listOfIndexProperties,
            Dictionary <string, double[]> dictionaryOfSummaryIndices,
            string titleText,
            TimeSpan indexCalculationDuration,
            DateTimeOffset?recordingStartDate,
            List <GapsAndJoins> errors = null,
            bool verbose = true)
        {
            const int trackHeight      = DefaultTrackHeight;
            int       scaleLength      = 0;
            var       backgroundColour = Color.White;

            // init list of bitmap images to store image tracks
            var bitmapList = new List <Tuple <IndexProperties, Image <Rgb24> > >(dictionaryOfSummaryIndices.Keys.Count);

            // set up strings to store info about which indices are used
            var s1 = new StringBuilder("Indices not found:");
            var s2 = new StringBuilder("Indices not plotted:");

            // accumulate the individual tracks in a List
            foreach (string key in dictionaryOfSummaryIndices.Keys)
            {
                if (!listOfIndexProperties.ContainsKey(key))
                {
                    s1.Append(" {0},".Format2(key));
                    continue;
                }

                IndexProperties ip = listOfIndexProperties[key];
                if (!ip.DoDisplay)
                {
                    s2.Append(" {0},".Format2(key));
                    continue;
                }

                //string name = ip.Name;
                double[] array = dictionaryOfSummaryIndices[key];
                scaleLength = array.Length;

                // alternate rows have different colour to make tracks easier to read
                backgroundColour = backgroundColour == Color.LightGray ? Color.White : Color.LightGray;
                var bitmap = ip.GetPlotImage(array, backgroundColour, errors);
                bitmapList.Add(Tuple.Create(ip, bitmap));
            }

            if (verbose)
            {
                Logger.Warn(s1.ToString());
                Logger.Warn(s2.ToString());
            }

            var listOfBitmaps = bitmapList

                                //    .OrderBy(tuple => tuple.Item1.Order) // don't order because want to preserve alternating gray/white rows.
                                .Select(tuple => tuple.Item2)
                                .Where(b => b != null).ToList();

            //set up the composite image parameters
            int           x_offset   = 2;
            int           graphWidth = x_offset + scaleLength;
            int           imageWidth = x_offset + scaleLength + TrackEndPanelWidth;
            Image <Rgb24> titleBmp   = ImageTrack.DrawTitleTrack(imageWidth, trackHeight, titleText);

            TimeSpan       xAxisPixelDuration = indexCalculationDuration;
            TimeSpan       fullDuration       = TimeSpan.FromTicks(xAxisPixelDuration.Ticks * graphWidth);
            Image <Rgb24>  timeBmp1           = ImageTrack.DrawTimeRelativeTrack(fullDuration, graphWidth, trackHeight);
            Image <Rgb24>  timeBmp2           = timeBmp1;
            DateTimeOffset?dateTimeOffset     = recordingStartDate;

            if (dateTimeOffset.HasValue)
            {
                // draw extra time scale with absolute start time. AND THEN Do SOMETHING WITH IT.
                timeBmp2 = ImageTrack.DrawTimeTrack(fullDuration, dateTimeOffset, graphWidth, trackHeight);
            }

            //draw the composite bitmap
            var imageList = new List <Image <Rgb24> >
            {
                titleBmp,
                timeBmp1,
            };

            foreach (var image in listOfBitmaps)
            {
                imageList.Add(image);
            }

            imageList.Add(timeBmp2);
            var compositeBmp = (Image <Rgb24>)ImageTools.CombineImagesVertically(imageList);

            return(compositeBmp);
        }
Esempio n. 11
0
        /// <summary>
        /// Converts summary indices to a tracks image
        /// </summary>
        /// <param name="listOfIndexProperties"></param>
        /// <param name="dictionaryOfSummaryIndices"></param>
        /// <param name="titleText"></param>
        /// <param name="indexCalculationDuration"></param>
        /// <param name="recordingStartDate"></param>
        /// <param name="sunriseDataFile"></param>
        /// <param name="errors"></param>
        public static Bitmap DrawImageOfSummaryIndices(
            Dictionary <string, IndexProperties> listOfIndexProperties,
            Dictionary <string, double[]> dictionaryOfSummaryIndices,
            string titleText,
            TimeSpan indexCalculationDuration,
            DateTimeOffset?recordingStartDate,
            FileInfo sunriseDataFile   = null,
            List <GapsAndJoins> errors = null,
            bool verbose = false)
        {
            // to translate past keys into current keys
            Dictionary <string, string> translationDictionary = InitialiseIndexProperties.GetKeyTranslationDictionary();

            const int trackHeight = DefaultTrackHeight;
            int       scaleLength = 0;
            var       bitmapList  = new List <Tuple <IndexProperties, Image> >(dictionaryOfSummaryIndices.Keys.Count);

            // accumulate the individual tracks in a List
            foreach (string key in dictionaryOfSummaryIndices.Keys)
            {
                string correctKey = key;
                if (!listOfIndexProperties.ContainsKey(key))
                {
                    if (translationDictionary.ContainsKey(key))
                    {
                        correctKey = translationDictionary[key];
                        LoggedConsole.WriteWarnLine(
                            "The csv header is an unknown index <{0}>. Translated to <{1}>",
                            key,
                            correctKey);
                    }
                    else
                    {
                        if (verbose)
                        {
                            Logger.Warn(
                                "A index properties configuration could not be found for {0} (not even in the translation directory). Property is ignored and not rendered"
                                .Format2(key));
                        }

                        continue;
                    }
                }

                IndexProperties ip = listOfIndexProperties[correctKey];
                if (!ip.DoDisplay)
                {
                    continue;
                }

                string   name  = ip.Name;
                double[] array = dictionaryOfSummaryIndices[key];
                scaleLength = array.Length;
                Image bitmap = ip.GetPlotImage(array, errors);

                bitmapList.Add(Tuple.Create(ip, bitmap));
            }

            var listOfBitmaps = bitmapList
                                .OrderBy(tuple => tuple.Item1.Order)
                                .Select(tuple => tuple.Item2)
                                .Where(b => b != null).ToList();

            //set up the composite image parameters
            int      X_offset      = 2;
            int      graphWidth    = X_offset + scaleLength;
            int      imageWidth    = X_offset + scaleLength + TrackEndPanelWidth;
            TimeSpan scaleDuration = TimeSpan.FromMinutes(scaleLength);
            int      imageHt       = trackHeight * (listOfBitmaps.Count + 4); //+3 for title and top and bottom time tracks
            Bitmap   titleBmp      = ImageTrack.DrawTitleTrack(imageWidth, trackHeight, titleText);

            //Bitmap time1Bmp = ImageTrack.DrawTimeTrack(scaleDuration, TimeSpan.Zero, DrawSummaryIndices.TimeScale, graphWidth, TrackHeight, "Time (hours)");
            TimeSpan       xAxisPixelDuration = indexCalculationDuration;
            TimeSpan       fullDuration       = TimeSpan.FromTicks(xAxisPixelDuration.Ticks * graphWidth);
            Bitmap         timeBmp1           = ImageTrack.DrawTimeRelativeTrack(fullDuration, graphWidth, trackHeight);
            Bitmap         timeBmp2           = timeBmp1;
            Bitmap         suntrack           = null;
            DateTimeOffset?dateTimeOffset     = recordingStartDate;

            if (dateTimeOffset.HasValue)
            {
                // draw extra time scale with absolute start time. AND THEN Do SOMETHING WITH IT.
                timeBmp2 = ImageTrack.DrawTimeTrack(fullDuration, dateTimeOffset, graphWidth, trackHeight);
                suntrack = SunAndMoon.AddSunTrackToImage(scaleLength, dateTimeOffset, sunriseDataFile);
            }

            //draw the composite bitmap
            var imageList = new List <Image>();

            imageList.Add(titleBmp);
            imageList.Add(timeBmp1);
            for (int i = 0; i < listOfBitmaps.Count; i++)
            {
                imageList.Add(listOfBitmaps[i]);
            }

            imageList.Add(timeBmp2);
            imageList.Add(suntrack);
            Bitmap compositeBmp = (Bitmap)ImageTools.CombineImagesVertically(imageList);

            return(compositeBmp);
        }
        // ##############################################################################################################
        // ######################### ORIGINAL METHOD FOR STITCHING  Gianna Pavan's DATA (10 minutes every 30 minutes)

        /// <summary>
        /// This method stitches together spectrogram images derived from consecutive shorter recordings over a 24 hour period.
        /// Currently set for the recording protocol of Gianna Pavan (10 minutes every 30 minutes).
        ///
        /// Call this method from Sandpit or where ever!
        ///
        /// IMPORTANT NOTE: This method does NOT check to see if the images are in temporal order.
        ///                 A SORT line should be inserted somewhere
        /// </summary>
        public static void StitchPartialSpectrograms()
        {
            //######################################################
            // ********************* set the below parameters
            var    inputDirectory  = new DirectoryInfo(@"Z:\Italy_GianniPavan\output4\Towsey.Acoustic");
            string opFileStem      = "Sassofratino_24hours_v3";
            var    outputDirectory = new DirectoryInfo(@"Z:\Italy_GianniPavan\output4\");

            // a filter to select images to be stitched
            string endString = "_000.2MAPS.png";

            // recording protocol
            int      minutesBetweenRecordingStarts = 30;
            TimeSpan minOffset = TimeSpan.Zero; // assume first recording in sequence started at midnight

            // X-axis timescale
            int pixelColumnsPerHour = 60;
            int trackHeight         = IndexDisplay.DefaultTrackHeight;

            // ********************* set the above parameters
            //######################################################

            string[] fileEntries       = Directory.GetFiles(inputDirectory.FullName);
            var      images            = new List <Image>();
            bool     interpolateSpacer = true;
            var      imagePair         = new Image[2];

            TimeSpan xAxisTicInterval = TimeSpan.FromMinutes(pixelColumnsPerHour); // assume 60 pixels per hour

            // loop through all files in the required directory
            foreach (string path in fileEntries)
            {
                // filter files.
                if (!path.EndsWith(endString))
                {
                    continue;
                }

                var image       = new Bitmap(path);
                int spacerWidth = minutesBetweenRecordingStarts - image.Width;

                if (interpolateSpacer)
                {
                    var spacer = new Bitmap(spacerWidth, image.Height);
                    imagePair[0] = image;
                    imagePair[1] = spacer;
                    image        = (Bitmap)ImageTools.CombineImagesInLine(imagePair);
                }

                images.Add(image);
            }

            var compositeBmp = ImageTools.CombineImagesInLine(images.ToArray());

            var fullDuration = TimeSpan.FromMinutes(compositeBmp.Width);
            var timeBmp      = ImageTrack.DrawTimeTrack(fullDuration, minOffset, xAxisTicInterval, compositeBmp.Width, trackHeight, "hours");

            var gr         = Graphics.FromImage(compositeBmp);
            int halfHeight = compositeBmp.Height / 2;

            //add in the title bars
            string title    = $"24 hour FALSE-COLOUR SPECTROGRAM      (scale: hours x kHz)      (colour: R-G-B = BGN-AVG-CVR)         {Meta.OrganizationTag}  ";
            var    titleBmp = ImageTrack.DrawTitleTrack(compositeBmp.Width, trackHeight, title);
            int    offset   = 0;

            gr.DrawImage(titleBmp, 0, offset); //draw in the top time scale
            title    = $"24 hour FALSE-COLOUR SPECTROGRAM      (scale: hours x kHz)      (colour: R-G-B = ACI-ENT-EVN)         {Meta.OrganizationTag}  ";
            titleBmp = ImageTrack.DrawTitleTrack(compositeBmp.Width, trackHeight, title);
            offset   = halfHeight;
            gr.DrawImage(titleBmp, 0, offset); //draw in the top time scale

            //add in the timescale tracks
            offset = trackHeight;
            gr.DrawImage(timeBmp, 0, offset); //draw in the top time scale
            offset = compositeBmp.Height - trackHeight;
            gr.DrawImage(timeBmp, 0, offset); //draw in the top time scale
            offset = halfHeight - trackHeight;
            gr.DrawImage(timeBmp, 0, offset); //draw in the top time scale
            offset = halfHeight + trackHeight;
            gr.DrawImage(timeBmp, 0, offset); //draw in the top time scale

            compositeBmp.Save(Path.Combine(outputDirectory.FullName, opFileStem + ".png"));
        }
Esempio n. 13
0
        /// <summary>
        /// This method draws a spectrogram with other useful information attached.
        /// </summary>
        /// <param name="sonogram">of BaseSonogram class.</param>
        /// <param name="events">a list of acoustic events.</param>
        /// <param name="plots">a list of plots relevant to the spectrogram scores.</param>
        /// <param name="hits">not often used - can be null.</param>
        public static Image <Rgb24> GetSonogramPlusCharts(
            BaseSonogram sonogram,
            List <EventCommon> events,
            List <Plot> plots,
            double[,] hits)
        {
            var spectrogram = sonogram.GetImage(doHighlightSubband: false, add1KHzLines: true, doMelScale: false);

            Contract.RequiresNotNull(spectrogram, nameof(spectrogram));

            var height    = spectrogram.Height;
            var width     = spectrogram.Width;
            var frameSize = sonogram.Configuration.WindowSize;
            //var segmentDuration = sonogram.Duration;
            var spectrogramDuration = width * sonogram.FrameStep;

            // init with linear frequency scale and draw freq grid lines on image
            int hertzInterval = 1000;

            if (height < 200)
            {
                hertzInterval = 2000;
            }

            var nyquist   = sonogram.NyquistFrequency;
            var freqScale = new FrequencyScale(nyquist, frameSize, hertzInterval);

            FrequencyScale.DrawFrequencyLinesOnImage(spectrogram, freqScale.GridLineLocations, includeLabels: true);

            // draw event outlines onto spectrogram.
            if (events != null && events.Count > 0)
            {
                foreach (SpectralEvent ev in events)
                {
                    var options = new EventRenderingOptions(new UnitConverters(ev.SegmentStartSeconds, spectrogramDuration, nyquist, width, height));
                    spectrogram.Mutate(x => ev.Draw(x, options));
                }
            }

            // now add in hits to the spectrogram image.
            if (hits != null)
            {
                spectrogram = Image_MultiTrack.OverlayScoresAsRedTransparency(spectrogram, hits);
            }

            int pixelWidth = spectrogram.Width;
            var titleBar   = LDSpectrogramRGB.DrawTitleBarOfGrayScaleSpectrogram("TITLE", pixelWidth);
            var timeTrack  = ImageTrack.DrawTimeTrack(sonogram.Duration, pixelWidth);

            var imageList = new List <Image <Rgb24> >
            {
                titleBar,
                timeTrack,
                spectrogram,
                timeTrack,
            };

            if (plots != null)
            {
                foreach (var plot in plots)
                {
                    // Next line assumes plot data normalised in 0,1
                    var plotImage = plot.DrawAnnotatedPlot(ImageTrack.DefaultHeight);

                    // the following draws same plot without the title.
                    //var plotImage = ImageTrack.DrawScoreArrayTrack(plot.data, plot.threshold, pixelWidth);
                    imageList.Add(plotImage);
                }
            }

            var compositeImage = ImageTools.CombineImagesVertically(imageList);

            return(compositeImage);
        }