From b7f74c4c63b74f55f2975d7e3cf0d8a0d05d3ebe Mon Sep 17 00:00:00 2001 From: towsey Date: Fri, 12 Jun 2020 14:43:21 +1000 Subject: [PATCH] Finished Boobook Owl debug and test Issue #321 --- .../Towsey.NinoxBoobook.yml | 45 +++------ .../Recognizers/Birds/NinoxBoobook.cs | 99 +++++-------------- 2 files changed, 37 insertions(+), 107 deletions(-) diff --git a/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.NinoxBoobook.yml b/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.NinoxBoobook.yml index b7bb59db3..1db253235 100644 --- a/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.NinoxBoobook.yml +++ b/src/AnalysisConfigFiles/RecognizerConfigFiles/Towsey.NinoxBoobook.yml @@ -1,5 +1,6 @@ --- +# Boobook Owl = Towsey.NinoxBoobook # Resample rate must be 2 X the desired Nyquist #ResampleRate: 22050 # SegmentDuration: units=seconds; @@ -7,9 +8,6 @@ SegmentDuration: 60 # SegmentOverlap: units=seconds; SegmentOverlap: 0 -# Preprocessing of the recording segment -IgnoreHighAmplitudeClippedRecordingSegments: true - # Each of these profiles will be analyzed # This profile is required for the species-specific recogniser and must have the current name. Profiles: @@ -19,7 +17,6 @@ Profiles: FrameSize: 1024 FrameStep: 256 WindowFunction: HANNING - BgNoiseThreshold: 0.0 # min and max of the freq band to search MinHertz: 400 MaxHertz: 1100 @@ -31,7 +28,7 @@ Profiles: # A: First post-processing steps are to combine overlapping/proximal/sequential events # 1: Combine overlapping events -#CombineOverlappingEvents: false +CombineOverlappingEvents: true # 2: Combine each pair of Boobook syllables as one event # Can also use this to "mop up" events in neighbourhood - these can be removed later. @@ -39,41 +36,25 @@ CombinePossibleSyllableSequence: true SyllableStartDifference: 0.6 SyllableHertzGap: 350 -# B: Select or remove event types. -# 3: Select wanted event types. -#SelectEventsOfType: !ChirpEvent - -# 4: Remove unwanted event types. -#RemoveEventsOfType: !ChirpEvent - -# C: Remaining post-processing steps are to filter out over and/or undersized events -# 5: Filter the events for duration in seconds -RemoveEventsHavingWrongDuration: true - -# 6: Filter the events for bandwidth in Hertz -RemoveEventsHavingWrongBandwidth: true - -# 7: Filter the events for excess activity in upper buffer zone -RemoveEventsHavingExcessActivityInUpperBufferZone: true - -# 8: Filter the events for excess activity in lower buffer zone -RemoveEventsHavingExcessActivityInLowerBufferZone: true +# B: Filter the events for excess activity in their upper and lower buffer zones +NeighbourhoodLowerHertzBuffer: 150 +NeighbourhoodUpperHertzBuffer: 400 +NeighbourhoodDbThreshold: 9.0 # C: Options to save results files -# 9: Available options for saving data files (case-sensitive): [False/Never | True/Always | WhenEventsDetected] -SaveIntermediateWavFiles: Never -SaveIntermediateCsvFiles: false -# Available options (case-sensitive): [False/Never | True/Always | WhenEventsDetected] +# 4: Available options for saving spectrograms (case-sensitive): [False/Never | True/Always | WhenEventsDetected] # "True" is useful when debugging but "WhenEventsDetected" is required for operational use. - -# 10: Available options for saving #SaveSonogramImages: True SaveSonogramImages: WhenEventsDetected -# DisplayCsvImage is obsolete - ensure it remains set to: false + +# 5: Available options for saving data files (case-sensitive): [False/Never | True/Always | WhenEventsDetected] +SaveIntermediateWavFiles: Never +SaveIntermediateCsvFiles: false + +# 6: DisplayCsvImage is obsolete - ensure it remains set to: false DisplayCsvImage: false ## End section for AnalyzeLongRecording # Other config files to reference - HighResolutionIndicesConfig: "../Towsey.Acoustic.HiResIndicesForRecognisers.yml" ... \ No newline at end of file diff --git a/src/AnalysisPrograms/Recognizers/Birds/NinoxBoobook.cs b/src/AnalysisPrograms/Recognizers/Birds/NinoxBoobook.cs index ffe68fa6f..2dec4eeca 100644 --- a/src/AnalysisPrograms/Recognizers/Birds/NinoxBoobook.cs +++ b/src/AnalysisPrograms/Recognizers/Birds/NinoxBoobook.cs @@ -96,85 +96,17 @@ public override RecognizerResults Recognize( //var newEvents = spectralEvents.Cast().ToList(); //var spectralEvents = events.Select(x => (SpectralEvent)x).ToList(); - // 1: Pull out the chirp events and calculate their frequency profiles. - var (chirpEvents, others) = combinedResults.NewEvents.FilterForEventType(); - - // Uncomment the next line when want to obtain the event frequency profiles. - // WriteFrequencyProfiles(chirpEvents); - - foreach (var ev in chirpEvents) - { - // Calculate frequency profile score for event - SetFrequencyProfileScore((ChirpEvent)ev); - } - if (combinedResults.NewEvents.Count == 0) { BoobookLog.Debug($"Return zero events."); return combinedResults; } - // 2: Combine overlapping events. If the dB threshold is set low, may get lots of little events. - combinedResults.NewEvents = CompositeEvent.CombineOverlappingEvents(chirpEvents.Cast().ToList()); - BoobookLog.Debug($"Event count after combining overlaps = {combinedResults.NewEvents.Count}"); - - // 3: Combine proximal events. If the dB threshold is set low, may get lots of little events. - if (genericConfig.CombinePossibleSyllableSequence) - { - // Convert events to spectral events for combining of possible sequences. - // Can also use this parameter to combine events that are in the upper or lower neighbourhood. - // Such combinations will increase bandwidth of the event and this property can be used later to weed out unlikely events. - var spectralEvents1 = combinedResults.NewEvents.Cast().ToList(); - var startDiff = genericConfig.SyllableStartDifference; - var hertzDiff = genericConfig.SyllableHertzGap; - combinedResults.NewEvents = CompositeEvent.CombineProximalEvents(spectralEvents1, TimeSpan.FromSeconds(startDiff), (int)hertzDiff); - BoobookLog.Debug($"Event count after combining proximals = {combinedResults.NewEvents.Count}"); - } - + // 1: Filter the events for duration in seconds // Get the BoobookSyllable config. const string profileName = "BoobookSyllable"; var configuration = (NinoxBoobookConfig)genericConfig; var chirpConfig = (ForwardTrackParameters)configuration.Profiles[profileName]; - - // 4: Filter events on the amount of acoustic activity in their upper and lower neighbourhoods - their buffer zone. - // The idea is that an unambiguous event should have some acoustic space above and below. - // The filter requires that the average acoustic activity in each frame and bin of the upper and lower buffer zones should not exceed the user specified decibel threshold. - // The bandwidth of these two neighbourhoods is determined by the following parameters. - // ########## These parameters could be specified by user in config.yml file. - var upperHertzBuffer = 400; - var lowerHertzBuffer = 150; - - // The decibel threshold is currently set 5/6ths of the user specified threshold. - // THIS IS TO BE WATCHED. IT MAY PROVE TO BE INAPPROPRIATE TO HARD-CODE. - // Want the activity in buffer zones to be "somewhat" less than the user-defined threshold. - var neighbourhoodDbThreshold = chirpConfig.DecibelThreshold.Value * 0.8333; - - if (upperHertzBuffer > 0 || lowerHertzBuffer > 0) - { - var spectralEvents2 = combinedResults.NewEvents.Cast().ToList(); - combinedResults.NewEvents = EventExtentions.FilterEventsOnNeighbourhood( - spectralEvents2, - combinedResults.Sonogram, - lowerHertzBuffer, - upperHertzBuffer, - segmentStartOffset, - neighbourhoodDbThreshold); - - BoobookLog.Debug($"Event count after filtering on neighbourhood = {combinedResults.NewEvents.Count}"); - } - - if (combinedResults.NewEvents.Count == 0) - { - BoobookLog.Debug($"Return zero events."); - return combinedResults; - } - - // 5: Filter on COMPONENT COUNT in Composite events. - int maxComponentCount = 2; - combinedResults.NewEvents = EventExtentions.FilterEventsOnCompositeContent(combinedResults.NewEvents, maxComponentCount); - BoobookLog.Debug($"Event count after filtering on component count = {combinedResults.NewEvents.Count}"); - - // 6: Filter the events for duration in seconds var minimumEventDuration = chirpConfig.MinDuration; var maximumEventDuration = chirpConfig.MaxDuration; if (genericConfig.CombinePossibleSyllableSequence) @@ -186,13 +118,35 @@ public override RecognizerResults Recognize( combinedResults.NewEvents = EventExtentions.FilterOnDuration(combinedResults.NewEvents, minimumEventDuration.Value, maximumEventDuration.Value); BoobookLog.Debug($"Event count after filtering on duration = {combinedResults.NewEvents.Count}"); - // 7: Filter the events for bandwidth in Hertz + // 2: Filter the events for bandwidth in Hertz double average = 280; double sd = 40; double sigmaThreshold = 3.0; combinedResults.NewEvents = EventExtentions.FilterOnBandwidth(combinedResults.NewEvents, average, sd, sigmaThreshold); BoobookLog.Debug($"Event count after filtering on bandwidth = {combinedResults.NewEvents.Count}"); + // 3: Filter on COMPONENT COUNT in Composite events. + int maxComponentCount = 2; + combinedResults.NewEvents = EventExtentions.FilterEventsOnCompositeContent(combinedResults.NewEvents, maxComponentCount); + BoobookLog.Debug($"Event count after filtering on component count = {combinedResults.NewEvents.Count}"); + + // 4: Pull out the chirp events and calculate their frequency profiles. + var (chirpEvents, others) = combinedResults.NewEvents.FilterForEventType(); + + // Uncomment the next line when want to obtain the event frequency profiles. + // WriteFrequencyProfiles(chirpEvents); + foreach (var ev in chirpEvents) + { + // Calculate frequency profile score for event + SetFrequencyProfileScore((ChirpEvent)ev); + } + + if (combinedResults.NewEvents.Count == 0) + { + BoobookLog.Debug($"Return zero events."); + return combinedResults; + } + //UNCOMMENT following line if you want special debug spectrogram, i.e. with special plots. // NOTE: Standard spectrograms are produced by setting SaveSonogramImages: "True" or "WhenEventsDetected" in UserName.SpeciesName.yml config file. //GenericRecognizer.SaveDebugSpectrogram(territorialResults, genericConfig, outputDirectory, audioRecording.BaseName); @@ -315,11 +269,6 @@ public override void SummariseResults( /// /> public class NinoxBoobookConfig : GenericRecognizerConfig, INamedProfiles { - public bool CombinePossibleSyllableSequence { get; set; } = false; - - public double SyllableStartDifference { get; set; } = 0.5; - - public double SyllableHertzGap { get; set; } = 200; } } }