Checkpoint
@@ -32,7 +32,7 @@ public class CompactCliTaskMonitor : TaskMonitor
|
||||
sb.Append(task.Exception is not null ? 'X' : StatusMap[status].First());
|
||||
}
|
||||
|
||||
sb.AppendLine($" ({completed}/{total - 1})");
|
||||
sb.AppendLine($" ({completed}/{total})");
|
||||
|
||||
Console.Clear();
|
||||
Console.Write(sb.ToString());
|
||||
|
||||
@@ -26,12 +26,12 @@ public class Program
|
||||
[SuppressMessage("ReSharper", "ArrangeObjectCreationWhenTypeNotEvident")]
|
||||
private static IEnumerable<EvaluationProcessor> MakeThresholdVariations()
|
||||
{
|
||||
for (int i = 0; i <= 24; i += 2)
|
||||
for (int i = 4; i <= 24; i += 4)
|
||||
{
|
||||
yield return new(new ThresholdAdaptiveProcessor(i));
|
||||
}
|
||||
|
||||
for (int i = 0; i <= 100; i += 10)
|
||||
for (int i = 20; i <= 80; i += 10)
|
||||
{
|
||||
yield return new(new ThresholdProcessor(i));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace Common.Extensions;
|
||||
|
||||
public static class EnumerableExtensions
|
||||
{
|
||||
public static double Median(this IEnumerable<double> values)
|
||||
{
|
||||
var tValues = values.ToArray();
|
||||
return tValues
|
||||
.OrderBy(x => x)
|
||||
.Skip(tValues.Length / 2)
|
||||
.First();
|
||||
}
|
||||
|
||||
public static double Median<T>(this IEnumerable<T> items, Func<T, double> selector) =>
|
||||
items.Select(selector).Median();
|
||||
}
|
||||
@@ -40,6 +40,6 @@ public class HtmlDocumentGenerator : DocumentGeneratorBase
|
||||
|
||||
private static string GetStyle() =>
|
||||
HtmlTools.Wrap("style",
|
||||
"html,body{width:100%;height:100%;overflow:scroll;} td,th{border:1px solid #777;padding:.5rem;text-align:center}table{border-collapse:collapse}tbody tr:nth-child(odd){background:#eee}caption{font-size:.8rem}"
|
||||
"td,th{border:1px solid #777;padding:.5rem;text-align:center}table{border-collapse:collapse}tbody tr:nth-child(odd){background:#eee}caption{font-size:.8rem}"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,10 +18,11 @@ internal static class Program
|
||||
Console.WriteLine("Generating report");
|
||||
var scans = Scan(tagFileInfos, scanFileInfos);
|
||||
|
||||
new ReportGenerator(scans, new HtmlDocumentGenerator())
|
||||
.WithTitle("OCR Report")
|
||||
.WithBestOf("Best of")
|
||||
.WithFullStatistic("Statistic")
|
||||
new ReportGenerator("OCR Report", new HtmlDocumentGenerator(), scans)
|
||||
.AddComparison("Processing summary (Average)", v => v.Average())
|
||||
// .AddComparison("Processing summary (Median)", v => v.Median())
|
||||
.AddImageStats("Image summary")
|
||||
.AddImageStatsFull("Scan Results")
|
||||
.ToFile("report");
|
||||
|
||||
Console.WriteLine("Completed");
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using ReportGenerator.Generator.Abstract;
|
||||
using Common.Extensions;
|
||||
using ReportGenerator.Generator;
|
||||
using ReportGenerator.Generator.Abstract;
|
||||
using ReportGenerator.Generator.Interface;
|
||||
using ReportGenerator.Generator.Model;
|
||||
using ReportGenerator.Models;
|
||||
@@ -7,19 +9,35 @@ namespace ReportGenerator;
|
||||
|
||||
public class ReportGenerator : FileSerializableBase
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string FileExtension => Document.FileExtension;
|
||||
|
||||
private IDocumentGenerator Document { get; }
|
||||
|
||||
private ICollection<ImageStats> Images { get; }
|
||||
|
||||
public ReportGenerator(IEnumerable<ImageStats> stats, IDocumentGenerator document)
|
||||
public ReportGenerator(
|
||||
IDocumentGenerator document,
|
||||
IEnumerable<ImageStats> data
|
||||
)
|
||||
{
|
||||
Images = stats.ToArray();
|
||||
Document = document;
|
||||
Images = data.ToArray();
|
||||
}
|
||||
|
||||
public ReportGenerator(
|
||||
string title,
|
||||
IDocumentGenerator document,
|
||||
IEnumerable<ImageStats> data
|
||||
) : this(document, data)
|
||||
{
|
||||
WithTitle(title);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string ToString() => Document.ToString();
|
||||
|
||||
#region Fluent definition
|
||||
#region Report content generation
|
||||
|
||||
public ReportGenerator WithTitle(string text)
|
||||
{
|
||||
@@ -27,7 +45,7 @@ public class ReportGenerator : FileSerializableBase
|
||||
return this;
|
||||
}
|
||||
|
||||
public ReportGenerator WithFullStatistic(string title)
|
||||
public ReportGenerator AddImageStatsFull(string title)
|
||||
{
|
||||
Document.AppendHeading(2, title);
|
||||
|
||||
@@ -77,73 +95,125 @@ public class ReportGenerator : FileSerializableBase
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public ReportGenerator WithBestOf(string title, int context = 5)
|
||||
public ReportGenerator AddImageStats(string title)
|
||||
{
|
||||
Document.AppendHeading(2, title);
|
||||
|
||||
foreach (var image in Images)
|
||||
{
|
||||
Document
|
||||
.AppendHeading(3, image.ImageName)
|
||||
.AppendLine(HtmlTools.FormatImage(
|
||||
Path.Combine("img", image.ImageName),
|
||||
new Bounds(0, 300)
|
||||
));
|
||||
|
||||
var byWer = image
|
||||
.Processors
|
||||
.Select(p => (p.Name, p.Distance))
|
||||
.OrderBy(t => t.Item2);
|
||||
Document.AppendHeading(4, "WER");
|
||||
AppendComparison(("Error", "%"), byWer);
|
||||
|
||||
var byCerAvg = image
|
||||
.Processors
|
||||
.Select(p => (p.Name, p.Words.Average(w => w.Distance)))
|
||||
.OrderBy(t => t.Item2);
|
||||
Document.AppendHeading(4, "CER (Average)");
|
||||
AppendComparison(("Changes", string.Empty), byCerAvg);
|
||||
|
||||
var byCerMedian = image
|
||||
.Processors
|
||||
.Select(p => (p.Name, p.Words.Median(w => w.Distance)))
|
||||
.OrderBy(t => t.Item2);
|
||||
Document.AppendHeading(4, "CER (Median)");
|
||||
AppendComparison(("Changes", string.Empty), byCerMedian);
|
||||
|
||||
var byTime = image
|
||||
.Processors
|
||||
.Select(p => (p.Name, p.ProcessingTime))
|
||||
.OrderBy(t => t.Item2);
|
||||
Document.AppendHeading(4, "Time");
|
||||
AppendComparison(("Time", "ms"), byTime);
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public ReportGenerator AddComparison(
|
||||
string title,
|
||||
Func<IEnumerable<double>, double> evaluationFunc
|
||||
)
|
||||
{
|
||||
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);
|
||||
Document.AppendHeading(2, title);
|
||||
|
||||
// Compare WER across all images
|
||||
var byWer = lookup
|
||||
.Select(g => (Name: g.Key, Value: g.Average(p => p.Distance) * 100))
|
||||
.Select(g => (
|
||||
Name: g.Key,
|
||||
Value: evaluationFunc(g.Select(p => p.Distance)) * 100
|
||||
))
|
||||
.OrderBy(g => g.Value);
|
||||
Document.AppendHeading(3, "WER");
|
||||
AppendComparison(("Error", "%"), byWer);
|
||||
|
||||
// Compare CER across all images
|
||||
var byCer = lookup
|
||||
.Select(g => (Name: g.Key, Value: g.Average(p => p.Words.Average(w => w.Distance))))
|
||||
.Select(g => (
|
||||
Name: g.Key,
|
||||
Value: evaluationFunc(g.SelectMany(p => p.Words, (_, word) => word.Distance))
|
||||
))
|
||||
.OrderBy(g => g.Value);
|
||||
Document.AppendHeading(3, "CER");
|
||||
AppendComparison(("Changes", string.Empty), byCer);
|
||||
|
||||
// Print
|
||||
AppendComparison(3, "Time", byTime, " ms");
|
||||
AppendComparison(3, "WER", byWer, " %");
|
||||
AppendComparison(3, "CER", byCer, " changes");
|
||||
var byTime = lookup
|
||||
.Select(g => (
|
||||
Name: g.Key,
|
||||
Value: evaluationFunc(g.Select(p => p.ProcessingTime)) * 1000
|
||||
))
|
||||
.OrderBy(g => g.Value);
|
||||
Document.AppendHeading(3, "Time");
|
||||
AppendComparison(("Time", "ms"), byTime);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
void AppendComparison(
|
||||
int level,
|
||||
string title,
|
||||
IEnumerable<(string, double)> values,
|
||||
string valueUnit = ""
|
||||
)
|
||||
|
||||
private void AppendComparison(
|
||||
(string name, string unit)? valueInfo,
|
||||
IEnumerable<(string, double)> values
|
||||
)
|
||||
{
|
||||
const int context = 5;
|
||||
|
||||
var tValues = values.ToArray();
|
||||
var tContext = Math.Min(tValues.Length / 2, context);
|
||||
|
||||
Document.AppendTable(2, table =>
|
||||
{
|
||||
var tValues = values.ToArray();
|
||||
var tContext = Math.Min(tValues.Length / 2, context);
|
||||
|
||||
Document
|
||||
.AppendHeading(level, title)
|
||||
.AppendTable(2, table => table
|
||||
.AppendHeader(new[] { "Processor", "Average" })
|
||||
.AppendRows(tValues
|
||||
.Take(tContext).Select(v => new[]
|
||||
{
|
||||
v.Item1,
|
||||
v.Item2.ToString("F2") + valueUnit
|
||||
}))
|
||||
.AppendRow("...")
|
||||
.AppendRows(tValues.TakeLast(tContext).Select(v => new[]
|
||||
{
|
||||
v.Item1,
|
||||
v.Item2.ToString("F2") + valueUnit
|
||||
}))
|
||||
table
|
||||
.AppendHeader(new[] { "Processor", valueInfo?.name ?? "Value" })
|
||||
.AppendRows(tValues
|
||||
.Take(tContext)
|
||||
.Select(MakeRow))
|
||||
.AppendRow("...")
|
||||
.AppendRows(
|
||||
tValues
|
||||
.TakeLast(tContext)
|
||||
.Select(MakeRow)
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
string[] MakeRow((string, double) v) =>
|
||||
new[] { v.Item1, v.Item2.ToString("F2") + valueInfo?.unit };
|
||||
});
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Overrides of FileSerializableBase
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string FileExtension => Document.FileExtension;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 889 B After Width: | Height: | Size: 889 B |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 9.9 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.8 KiB |