Skip to content

Commit

Permalink
Write one unit test for overlay of hit scores
Browse files Browse the repository at this point in the history
Issue #300
Write one unit test for overlay of sonogram with matrix of score/hits.
Remove duplicated method RecognizerBase.WriteSpectrumIndicesFiles()
Rewrite method for drawing of event rectangles.
  • Loading branch information
towsey authored and atruskie committed Mar 20, 2020
1 parent b05bbb0 commit 5a3f9af
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 45 deletions.
29 changes: 0 additions & 29 deletions src/AnalysisPrograms/Recognizers/Base/RecognizerBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -336,35 +336,6 @@ protected virtual Image DrawSonogram(
double eventThreshold)
{
var image = SpectrogramTools.GetSonogramPlusCharts(sonogram, predictedEvents, scores, hits);

//const bool doHighlightSubband = false;
//const bool add1KHzLines = true;
//var image = new Image_MultiTrack(sonogram.GetImage(doHighlightSubband, add1KHzLines, doMelScale: false));
//image.AddTrack(ImageTrack.GetTimeTrack(sonogram.Duration, sonogram.FramesPerSecond));
//image.AddTrack(ImageTrack.GetSegmentationTrack(sonogram));

//if (scores != null)
//{
// foreach (var plot in scores)
// {
// image.AddTrack(ImageTrack.GetNamedScoreTrack(plot.data, 0.0, 1.0, plot.threshold, plot.title));
// }
//}

//if (hits != null)
//{
// image.OverlayRedTransparency(hits);
//}

//if (predictedEvents != null && predictedEvents.Count > 0)
//{
// image.AddEvents(
// predictedEvents,
// sonogram.NyquistFrequency,
// sonogram.Configuration.FreqBinCount,
// sonogram.FramesPerSecond);
//}

return image;
}

Expand Down
3 changes: 2 additions & 1 deletion src/AudioAnalysisTools/AcousticEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,7 @@ public void DrawEvent<T>(Image<T> imageToReturn, double framesPerSecond, double
if (duration >= 0.0 && framesPerSecond >= 0.0)
{
t1 = (int)Math.Round(this.TimeStart * framesPerSecond);

t2 = (int)Math.Round(this.TimeEnd * framesPerSecond);
}
else if (this.Oblong != null)
Expand All @@ -426,7 +427,7 @@ public void DrawEvent<T>(Image<T> imageToReturn, double framesPerSecond, double
t2 = this.Oblong.RowBottom;
}

imageToReturn.Mutate(g => g.DrawRectangle(borderPen, t1, y1, t2, y2));
imageToReturn.Mutate(g => g.DrawRectangle(borderPen, t1, y1, t2 - t1 + 1, y2 - y1 + 1));

if (this.HitElements != null)
{
Expand Down
81 changes: 68 additions & 13 deletions src/AudioAnalysisTools/StandardSpectrograms/Image_MultiTrack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -353,42 +353,97 @@ public Image<Rgb24> OverlayRedTransparency(Image<Rgb24> bmp)
}

/// <summary>
/// superimposes a matrix of scores on top of a sonogram.
/// TODO: WARNING: THIS METHOD IS YET TO BE DEBUGGED SINCE TRANSITION TO SIX-LABOURS, FEB 2020.
/// It is assumed that the spectrogram image is grey scale.
/// NOTE: The score matrix must consist of reals in [0.0, 1.0].
/// NOTE: The image and the score matrix must have the same number of rows and columns.
/// In case of a spectrogram, it is assumed that the rows are frequency bins and the columns are individual spectra.
/// </summary>
/// <param name="bmp">the spectrogram image.</param>
/// <param name="hits">the matrix of scores or hits.</param>
public static Image<Rgb24> OverlayScoresAsRedTransparency(Image<Rgb24> bmp, double[,] hits)
{
Image<Rgb24> newBmp = (Image<Rgb24>)bmp.Clone();
int rows = hits.GetLength(0);
int cols = hits.GetLength(1);
int imageHt = bmp.Height - 1; //subtract 1 because indices start at zero

//traverse columns - skip DC column
for (int c = 1; c < cols; c++)
if (rows != bmp.Height || cols != bmp.Width)
{
for (int r = 0; r < rows; r++)
LoggedConsole.WriteErrorLine("ERROR: Image and hits matrix do not have the same dimensions.");
return bmp;
}

for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
{
if (hits[r, c] == 0.0)
if (hits[r, c] <= 0.0)
{
continue;
}

var pixel = bmp[r, imageHt - c];
if (pixel.R == 255)
if (hits[r, c] > 1.0)
{
continue; // white
hits[r, c] = 1.0;
}

newBmp[r, imageHt - c] = Color.FromRgb(255, pixel.G, pixel.B);
var pixel = bmp[r, c];
byte value = (byte)Math.Floor(hits[r, c] * 255);
newBmp[r, c] = Color.FromRgb(value, pixel.G, pixel.B);
}
}

return newBmp;
}

/// <summary>
/// superimposes a matrix of scores on top of a sonogram. USES RAINBOW PALLETTE.
/// ASSUME MATRIX NORMALIZED IN [0,1].
/// Overlays a matrix of scores on an image, typically a spectrogram image.
/// It is assumed that the spectrogram image is grey scale.
/// NOTE: The score matrix must consist of integers from 0 to 255.
/// NOTE: The image and the score matrix must have the same number of rows and columns.
/// In case of a spectrogram, it is assumed that the rows are frequency bins and the columns are individual spectra.
/// </summary>
/// <param name="bmp">the spectrogram image.</param>
/// <param name="hits">the matrix of scores or hits.</param>
/// <returns>The new image with overlay of scores as red transparency.</returns>
public static Image<Rgb24> OverlayScoresAsRedTransparency(Image<Rgb24> bmp, int[,] hits)
{
Image<Rgb24> newBmp = (Image<Rgb24>)bmp.Clone();
int rows = hits.GetLength(0);
int cols = hits.GetLength(1);

if (rows != bmp.Height || cols != bmp.Width)
{
LoggedConsole.WriteErrorLine("ERROR: Image and hits matrix do not have the same dimensions.");
return bmp;
}

for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
{
if (hits[r, c] <= 0)
{
continue;
}

if (hits[r, c] > 255)
{
hits[r, c] = 255;
}

var pixel = bmp[c, r];
newBmp[c, r] = Color.FromRgb((byte)hits[r, c], pixel.G, pixel.B);
}
}

return newBmp;
}

/// <summary>
/// WARNING: THis method is yet to be debugged and tested following move to SixLabors drawing libraries.
/// superimposes a matrix of scores on top of a sonogram.
/// USES A PALLETTE of ten RAINBOW colours.
/// ASSUME MATRIX is NORMALIZED IN [0,1].
/// </summary>
public void OverlayRainbowTransparency(IImageProcessingContext g, Image<Rgb24> bmp)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,6 @@ public static Image<Rgb24> GetSonogramPlusCharts(
if (hits != null)
{
spectrogram = Image_MultiTrack.OverlayScoresAsRedTransparency(spectrogram, hits);
//OverlayRedTransparency(bmp, this.SuperimposedRedTransparency);
//this.SonogramImage = this.OverlayRedTransparency((Image<Rgb24>)this.SonogramImage);
}

int pixelWidth = spectrogram.Width;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ namespace Acoustics.Test.AudioAnalysisTools.StandardSpectrograms
using global::TowseyLibrary;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using Path = System.IO.Path;

/// <summary>
Expand Down Expand Up @@ -219,5 +220,46 @@ public void TestAnnotatedSonogramWithPlots()
Assert.AreEqual(1621, image.Width);
Assert.AreEqual(656, image.Height);
}

[TestMethod]
public void TestSonogramHitsOverlay()
{
int width = 100;
int height = 50;

// make a pretend sonogram image
var pretendSonogram = new Image<Rgb24>(width, height);

// make a pretend hits matrix with crossed diagonals
var hitsMatrix = new int[height, width];
for (int i = 0; i < width; i++)
{
int intensity = (int)Math.Floor(i / (double)width * 255);
hitsMatrix[i / 2, i] = intensity;
hitsMatrix[i / 2, width - i - 1] = intensity;
}

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

//pretendSonogram.Save("C:\\temp\\image.png");
var pixel = new Argb32(252, 0, 0);
var expectedColor = new Color(pixel);
var actualColor = pretendSonogram[0, height - 1];
Assert.AreEqual<Color>(expectedColor, actualColor);

pixel = new Argb32(127, 0, 0);
expectedColor = new Color(pixel);
actualColor = pretendSonogram[width / 2, height / 2];
Assert.AreEqual<Color>(expectedColor, actualColor);

pixel = new Argb32(0, 0, 0);
expectedColor = new Color(pixel);
actualColor = pretendSonogram[0, 0];
Assert.AreEqual<Color>(expectedColor, actualColor);
}
}
}

0 comments on commit 5a3f9af

Please sign in to comment.