172 lines
4.5 KiB
C#
172 lines
4.5 KiB
C#
using Common.Extensions;
|
|
using ReportGenerator.Models;
|
|
using System.Text;
|
|
|
|
namespace ReportGenerator.Table
|
|
{
|
|
public class ReportGenerator
|
|
{
|
|
private ICollection<ImageStats> Images { get; }
|
|
|
|
private readonly StringBuilder _sb = new();
|
|
|
|
private ReportGenerator(IEnumerable<ImageStats> stats) => Images = stats.ToArray();
|
|
|
|
/// <inheritdoc />
|
|
public override string ToString() => _sb.ToString();
|
|
|
|
#region Fluent definition
|
|
|
|
public ReportGenerator WithTitle(string text)
|
|
{
|
|
_sb.AppendHeading(1, text);
|
|
return this;
|
|
}
|
|
|
|
public ReportGenerator WithFullStatistic(string title)
|
|
{
|
|
_sb.AppendHeading(2, title);
|
|
|
|
foreach (var stat in Images)
|
|
{
|
|
_sb.AppendHeading(3, stat.ImageName);
|
|
_sb.AppendParagraph(HtmlImage(Path.Combine("img", stat.ImageName), 350, 350));
|
|
|
|
AppendRow(stat
|
|
.Reference
|
|
.Prepend("Image")
|
|
.Prepend("CER (avg)")
|
|
.Prepend("WER")
|
|
.Prepend("Elapsed")
|
|
.Prepend("Processor")
|
|
);
|
|
|
|
AppendRowSeparator(stat.Reference.Count + 5);
|
|
|
|
var processors = stat.Processors
|
|
.OrderBy(s => s.Distance)
|
|
.ThenBy(s => s.ProcessingTime);
|
|
|
|
foreach (var processor in processors)
|
|
{
|
|
var imgPath = Path.Combine("results", $"{processor.Name}.00.{stat.ImageName}.png");
|
|
|
|
AppendRow(processor.Words
|
|
.Select(s => s.ToString() ?? string.Empty)
|
|
.Prepend(HtmlImage(imgPath, 150, 150))
|
|
.Prepend(processor.Words.Average(s => s.Distance).ToString("F2"))
|
|
.Prepend($"{processor.Distance * 100:F1}%")
|
|
.Prepend($"{processor.ProcessingTime * 1000:F1}ms")
|
|
.Prepend(processor.Name)
|
|
);
|
|
}
|
|
|
|
_sb.AppendLine();
|
|
_sb.AppendParagraph(
|
|
$"*Comparison data generated based on {stat.Reference.Count} tagged words.*"
|
|
);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
|
|
public ReportGenerator WithBestOf(string title, int context = 5)
|
|
{
|
|
_sb.AppendHeading(2, title);
|
|
|
|
var lookup = Images
|
|
.SelectMany(s => s.Processors)
|
|
.ToLookup(p => p.Name);
|
|
|
|
// Compare time across all images
|
|
var byTime = lookup
|
|
.Select(g => (Name: g.Key, Value: g.Average(p => p.ProcessingTime) * 1000))
|
|
.OrderBy(g => g.Value);
|
|
|
|
// Compare WER across all images
|
|
var byWer = lookup
|
|
.Select(g => (Name: g.Key, Value: g.Average(p => p.Distance) * 100))
|
|
.OrderBy(g => g.Value);
|
|
|
|
// Compare CER across all images
|
|
var byCer = lookup
|
|
.Select(g => (Name: g.Key, Value: g.Average(p => p.Words.Average(w => w.Distance))))
|
|
.OrderBy(g => g.Value);
|
|
|
|
// Print
|
|
AppendComparison(3, "Time", byTime, " ms");
|
|
AppendComparison(3, "WER", byWer, " %");
|
|
AppendComparison(3, "CER", byCer, " changes");
|
|
|
|
return this;
|
|
|
|
void AppendComparison(
|
|
int level,
|
|
string tableTitle,
|
|
IEnumerable<(string, double)> values,
|
|
string valueUnit = ""
|
|
)
|
|
{
|
|
var tValues = values.ToArray();
|
|
var tContext = Math.Min(tValues.Length / 2, context);
|
|
|
|
_sb.AppendHeading(level, tableTitle);
|
|
|
|
AppendRow(new[] { "Processor", "Average" });
|
|
AppendRowSeparator(2);
|
|
AppendRows(tValues.Take(tContext).Select(v => new[]
|
|
{
|
|
v.Item1,
|
|
v.Item2.ToString("F2") + valueUnit
|
|
}));
|
|
AppendRowSeparator(2, "...");
|
|
AppendRows(tValues.TakeLast(tContext).Select(v => new[]
|
|
{
|
|
v.Item1,
|
|
v.Item2.ToString("F2") + valueUnit
|
|
}));
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Helpers
|
|
|
|
private void AppendRow(IEnumerable<string> row)
|
|
{
|
|
const string separator = " | ";
|
|
_sb.AppendLine(separator + string.Join(" | ", row) + separator);
|
|
}
|
|
|
|
private void AppendRows(IEnumerable<IEnumerable<string>> rows)
|
|
{
|
|
foreach (var row in rows)
|
|
{
|
|
AppendRow(row);
|
|
}
|
|
}
|
|
|
|
private static string HtmlImage(string path, int maxWidth, int maxHeight)
|
|
{
|
|
if (!path.EndsWith(".png"))
|
|
{
|
|
path += ".png";
|
|
}
|
|
|
|
return $"<img src=\"{path}\" style=\"max-width:{maxWidth}px;max-height:{maxHeight}px;\" />";
|
|
}
|
|
|
|
private void AppendRowSeparator(int columns, string content = "---") =>
|
|
AppendRow(Enumerable.Range(0, columns).Select(_ => content));
|
|
|
|
#endregion
|
|
|
|
#region Factory Methods
|
|
|
|
public static ReportGenerator FromData(IEnumerable<ImageStats> stats) => new(stats);
|
|
|
|
#endregion
|
|
}
|
|
}
|