Beispiel #1
0
        /// <inheritdoc/>
        public override RecognizerResults Recognize(
            AudioRecording audioRecording,
            Config genericConfig,
            TimeSpan segmentStartOffset,
            Lazy <IndexCalculateResult[]> getSpectralIndexes,
            DirectoryInfo outputDirectory,
            int?imageWidth)
        {
            var configuration = (GenericRecognizerConfig)genericConfig;

            if (configuration.Profiles?.Count < 1)
            {
                throw new ConfigFileException(
                          "The generic recognizer needs at least one profile set. 0 were found.");
            }

            int count   = configuration.Profiles.Count;
            var message = $"Found {count} analysis profile(s): " + configuration.Profiles.Keys.Join(", ");

            Log.Info(message);

            var allResults = new RecognizerResults()
            {
                Events     = new List <AcousticEvent>(),
                NewEvents  = new List <EventCommon>(),
                Hits       = null,
                ScoreTrack = null,
                Plots      = new List <Plot>(),
                Sonogram   = null,
            };

            // Now process each of the profiles
            foreach (var(profileName, profileConfig) in configuration.Profiles)
            {
                Log.Info("Processing profile: " + profileName);

                //List<AcousticEvent> acousticEvents;
                List <EventCommon> spectralEvents;
                var plots = new List <Plot>();
                SpectrogramStandard sonogram;

                Log.Debug($"Using the {profileName} algorithm... ");
                if (profileConfig is CommonParameters parameters)
                {
                    if (profileConfig is BlobParameters ||
                        profileConfig is OscillationParameters ||
                        profileConfig is OnebinTrackParameters ||
                        profileConfig is HarmonicParameters ||
                        profileConfig is ForwardTrackParameters ||
                        profileConfig is UpwardTrackParameters ||
                        profileConfig is OneframeTrackParameters)
                    {
                        sonogram = new SpectrogramStandard(ParametersToSonogramConfig(parameters), audioRecording.WavReader);

                        if (profileConfig is BlobParameters bp)
                        {
                            //get the array of intensity values minus intensity in side/buffer bands.
                            //i.e. require silence in side-bands. Otherwise might simply be getting part of a broader band acoustic event.
                            var decibelArray = SNR.CalculateFreqBandAvIntensityMinusBufferIntensity(
                                sonogram.Data,
                                bp.MinHertz.Value,
                                bp.MaxHertz.Value,
                                bp.BottomHertzBuffer.Value,
                                bp.TopHertzBuffer.Value,
                                sonogram.NyquistFrequency);

                            // prepare plot of resultant blob decibel array.
                            var plot = PreparePlot(decibelArray, $"{profileName} (Blob:db Intensity)", bp.DecibelThreshold.Value);
                            plots.Add(plot);

                            // iii: CONVERT blob decibel SCORES TO ACOUSTIC EVENTS.
                            // Note: This method does NOT do prior smoothing of the dB array.
                            var acEvents = AcousticEvent.GetEventsAroundMaxima(
                                decibelArray,
                                segmentStartOffset,
                                bp.MinHertz.Value,
                                bp.MaxHertz.Value,
                                bp.DecibelThreshold.Value,
                                TimeSpan.FromSeconds(bp.MinDuration.Value),
                                TimeSpan.FromSeconds(bp.MaxDuration.Value),
                                sonogram.FramesPerSecond,
                                sonogram.FBinWidth);
                            spectralEvents = acEvents.ConvertAcousticEventsToSpectralEvents();
                        }
                        else if (profileConfig is OnebinTrackParameters wp)
                        {
                            //get the array of intensity values minus intensity in side/buffer bands.
                            double[] decibelArray;
                            (spectralEvents, decibelArray) = OnebinTrackAlgorithm.GetOnebinTracks(
                                sonogram,
                                wp,
                                segmentStartOffset);

                            var plot = PreparePlot(decibelArray, $"{profileName} (Whistle:dB Intensity)", wp.DecibelThreshold.Value);
                            plots.Add(plot);
                        }
                        else if (profileConfig is ForwardTrackParameters tp)
                        {
                            double[] decibelArray;
                            (spectralEvents, decibelArray) = ForwardTrackAlgorithm.GetForwardTracks(
                                sonogram,
                                tp,
                                segmentStartOffset);

                            var plot = PreparePlot(decibelArray, $"{profileName} (Chirps:dB Intensity)", tp.DecibelThreshold.Value);
                            plots.Add(plot);
                        }
                        else if (profileConfig is OneframeTrackParameters cp)
                        {
                            double[] decibelArray;
                            (spectralEvents, decibelArray) = OneframeTrackAlgorithm.GetOneFrameTracks(
                                sonogram,
                                cp,
                                segmentStartOffset);

                            var plot = PreparePlot(decibelArray, $"{profileName} (Clicks:dB Intensity)", cp.DecibelThreshold.Value);
                            plots.Add(plot);
                        }
                        else if (profileConfig is UpwardTrackParameters vtp)
                        {
                            double[] decibelArray;
                            (spectralEvents, decibelArray) = UpwardTrackAlgorithm.GetUpwardTracks(
                                sonogram,
                                vtp,
                                segmentStartOffset);

                            var plot = PreparePlot(decibelArray, $"{profileName} (VerticalTrack:dB Intensity)", vtp.DecibelThreshold.Value);
                            plots.Add(plot);
                        }
                        else if (profileConfig is HarmonicParameters hp)
                        {
                            double[] decibelMaxArray;
                            double[] harmonicIntensityScores;
                            (spectralEvents, decibelMaxArray, harmonicIntensityScores) = HarmonicParameters.GetComponentsWithHarmonics(
                                sonogram,
                                hp.MinHertz.Value,
                                hp.MaxHertz.Value,
                                sonogram.NyquistFrequency,
                                hp.DecibelThreshold.Value,
                                hp.DctThreshold.Value,
                                hp.MinDuration.Value,
                                hp.MaxDuration.Value,
                                hp.MinFormantGap.Value,
                                hp.MaxFormantGap.Value,
                                segmentStartOffset);

                            var plot = PreparePlot(harmonicIntensityScores, $"{profileName} (Harmonics:dct intensity)", hp.DctThreshold.Value);
                            plots.Add(plot);
                        }
                        else if (profileConfig is OscillationParameters op)
                        {
                            Oscillations2012.Execute(
                                sonogram,
                                op.MinHertz.Value,
                                op.MaxHertz.Value,
                                op.DctDuration,
                                op.MinOscillationFrequency,
                                op.MaxOscillationFrequency,
                                op.DctThreshold,
                                op.EventThreshold,
                                op.MinDuration.Value,
                                op.MaxDuration.Value,
                                out var scores,
                                out var oscillationEvents,
                                out var hits,
                                segmentStartOffset);

                            spectralEvents = new List <EventCommon>(oscillationEvents);

                            //plots.Add(new Plot($"{profileName} (:OscillationScore)", scores, op.EventThreshold));
                            var plot = PreparePlot(scores, $"{profileName} (:OscillationScore)", op.EventThreshold);
                            plots.Add(plot);
                        }
                        else
                        {
                            throw new InvalidOperationException();
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException();
                    }

                    //iV add additional info to the acoustic events
                    spectralEvents.ForEach(ae =>
                    {
                        ae.FileName = audioRecording.BaseName;
                        ae.Name     = parameters.SpeciesName;
                        ae.Profile  = profileName;

                        //ae.SegmentDurationSeconds = audioRecording.Duration.TotalSeconds;
                        //ae.SegmentStartSeconds = segmentStartOffset.TotalSeconds;
                        //ae.SetTimeAndFreqScales(sonogram.FrameStep, sonogram.FrameDuration, sonogram.FBinWidth);
                    });
                }
                else if (profileConfig is Aed.AedConfiguration ac)
                {
                    var config = new SonogramConfig
                    {
                        NoiseReductionType      = ac.NoiseReductionType,
                        NoiseReductionParameter = ac.NoiseReductionParameter,
                    };
                    sonogram = new SpectrogramStandard(config, audioRecording.WavReader);

                    // GET THIS TO RETURN BLOB EVENTS.
                    spectralEvents = Aed.CallAed(sonogram, ac, segmentStartOffset, audioRecording.Duration).ToList();
                }
                else
                {
                    throw new InvalidOperationException();
                }

                // combine the results i.e. add the events list of call events.
                allResults.NewEvents.AddRange(spectralEvents);
                allResults.Plots.AddRange(plots);

                // effectively keeps only the *last* sonogram produced
                allResults.Sonogram = sonogram;
                Log.Debug($"{profileName} event count = {spectralEvents.Count}");

                // DEBUG PURPOSES COMMENT NEXT LINE
                //SaveDebugSpectrogram(allResults, genericConfig, outputDirectory, "name");
            }

            return(allResults);
        }
Beispiel #2
0
        public void TestOneframeTrackAlgorithm()
        {
            // Set up the recognizer parameters.
            var parameters = new OneframeTrackParameters()
            {
                MinHertz          = 6000,
                MaxHertz          = 11000,
                MinBandwidthHertz = 100,
                MaxBandwidthHertz = 5000,
                DecibelThreshold  = 2.0,
            };

            //Set up the virtual recording.
            int    samplerate     = 22050;
            double signalDuration = 13.0; //seconds

            // set up the config for a virtual spectrogram.
            var sonoConfig = new SonogramConfig()
            {
                WindowSize              = 512,
                WindowStep              = 512,
                WindowOverlap           = 0.0, // this must be set
                WindowFunction          = WindowFunctions.HANNING.ToString(),
                NoiseReductionType      = NoiseReductionType.Standard,
                NoiseReductionParameter = 0.0,
                Duration   = TimeSpan.FromSeconds(signalDuration),
                SampleRate = samplerate,
            };

            var spectrogram = this.CreateArtificialSpectrogramToTestTracksAndHarmonics(sonoConfig);

            //var image1 = SpectrogramTools.GetSonogramPlusCharts(spectrogram, null, null, null);
            //results.Sonogram.GetImage().Save(this.outputDirectory + "\\debug.png");

            var segmentStartOffset = TimeSpan.Zero;
            var plots = new List <Plot>();

            var(spectralEvents, dBArray) = OneframeTrackAlgorithm.GetOneFrameTracks(
                spectrogram,
                parameters,
                segmentStartOffset);

            // draw a plot of max decibels in each frame
            double decibelNormalizationMax = 5 * parameters.DecibelThreshold.Value;
            var    dBThreshold             = parameters.DecibelThreshold.Value / decibelNormalizationMax;
            var    normalisedDecibelArray  = DataTools.NormaliseInZeroOne(dBArray, 0, decibelNormalizationMax);
            var    plot1 = new Plot("decibel max", normalisedDecibelArray, dBThreshold);

            plots.Add(plot1);

            var allResults = new RecognizerResults()
            {
                NewEvents  = new List <EventCommon>(),
                Hits       = null,
                ScoreTrack = null,
                Plots      = new List <Plot>(),
                Sonogram   = null,
            };

            // combine the results i.e. add the events list of call events.
            allResults.NewEvents.AddRange(spectralEvents);
            allResults.Plots.AddRange(plots);

            // effectively keeps only the *last* sonogram produced
            allResults.Sonogram = spectrogram;

            // DEBUG PURPOSES COMMENT NEXT LINE
            this.SaveTestOutput(
                outputDirectory => GenericRecognizer.SaveDebugSpectrogram(allResults, null, outputDirectory, "ClickTrack"));

            Assert.AreEqual(6, allResults.NewEvents.Count);

            var @event = (SpectralEvent)allResults.NewEvents[0];

            Assert.AreEqual(10.0, @event.EventStartSeconds, 0.1);
            Assert.AreEqual(10.1, @event.EventEndSeconds, 0.1);
            Assert.AreEqual(6450, @event.LowFrequencyHertz);
            Assert.AreEqual(10750, @event.HighFrequencyHertz);

            @event = (SpectralEvent)allResults.NewEvents[2];
            Assert.AreEqual(11.05, @event.EventStartSeconds, 0.05);
            Assert.AreEqual(11.07, @event.EventEndSeconds, 0.05);
            Assert.AreEqual(6450, @event.LowFrequencyHertz);
            Assert.AreEqual(7310, @event.HighFrequencyHertz);
        }