namespace OcrDaemon; using System.Text.Json.Serialization; class Request { [JsonPropertyName("cmd")] public string? Cmd { get; set; } [JsonPropertyName("region")] public RegionRect? Region { get; set; } [JsonPropertyName("path")] public string? Path { get; set; } [JsonPropertyName("cols")] public int Cols { get; set; } [JsonPropertyName("rows")] public int Rows { get; set; } [JsonPropertyName("threshold")] public int Threshold { get; set; } [JsonPropertyName("minCellSize")] public int MinCellSize { get; set; } [JsonPropertyName("maxCellSize")] public int MaxCellSize { get; set; } [JsonPropertyName("file")] public string? File { get; set; } [JsonPropertyName("debug")] public bool Debug { get; set; } [JsonPropertyName("targetRow")] public int TargetRow { get; set; } = -1; [JsonPropertyName("targetCol")] public int TargetCol { get; set; } = -1; [JsonPropertyName("engine")] public string? Engine { get; set; } [JsonPropertyName("preprocess")] public string? Preprocess { get; set; } [JsonPropertyName("params")] public DiffOcrParams? Params { get; set; } } class RegionRect { [JsonPropertyName("x")] public int X { get; set; } [JsonPropertyName("y")] public int Y { get; set; } [JsonPropertyName("width")] public int Width { get; set; } [JsonPropertyName("height")] public int Height { get; set; } } class ReadyResponse { [JsonPropertyName("ok")] public bool Ok => true; [JsonPropertyName("ready")] public bool Ready => true; } class OkResponse { [JsonPropertyName("ok")] public bool Ok => true; } class ErrorResponse(string message) { [JsonPropertyName("ok")] public bool Ok => false; [JsonPropertyName("error")] public string Error => message; } class OcrResponse { [JsonPropertyName("ok")] public bool Ok => true; [JsonPropertyName("text")] public string Text { get; set; } = ""; [JsonPropertyName("lines")] public List Lines { get; set; } = []; } class DiffOcrResponse { [JsonPropertyName("ok")] public bool Ok => true; [JsonPropertyName("text")] public string Text { get; set; } = ""; [JsonPropertyName("lines")] public List Lines { get; set; } = []; [JsonPropertyName("region")] public RegionRect? Region { get; set; } } class OcrLineResult { [JsonPropertyName("text")] public string Text { get; set; } = ""; [JsonPropertyName("words")] public List Words { get; set; } = []; } class OcrWordResult { [JsonPropertyName("text")] public string Text { get; set; } = ""; [JsonPropertyName("x")] public int X { get; set; } [JsonPropertyName("y")] public int Y { get; set; } [JsonPropertyName("width")] public int Width { get; set; } [JsonPropertyName("height")] public int Height { get; set; } } class CaptureResponse { [JsonPropertyName("ok")] public bool Ok => true; [JsonPropertyName("image")] public string Image { get; set; } = ""; } class GridResponse { [JsonPropertyName("ok")] public bool Ok => true; [JsonPropertyName("cells")] public List> Cells { get; set; } = []; [JsonPropertyName("items")] public List? Items { get; set; } [JsonPropertyName("matches")] public List? Matches { get; set; } } class GridItem { [JsonPropertyName("row")] public int Row { get; set; } [JsonPropertyName("col")] public int Col { get; set; } [JsonPropertyName("w")] public int W { get; set; } [JsonPropertyName("h")] public int H { get; set; } } class GridMatch { [JsonPropertyName("row")] public int Row { get; set; } [JsonPropertyName("col")] public int Col { get; set; } [JsonPropertyName("similarity")] public double Similarity { get; set; } } class DetectGridResponse { [JsonPropertyName("ok")] public bool Ok => true; [JsonPropertyName("detected")] public bool Detected { get; set; } [JsonPropertyName("region")] public RegionRect? Region { get; set; } [JsonPropertyName("cols")] public int Cols { get; set; } [JsonPropertyName("rows")] public int Rows { get; set; } [JsonPropertyName("cellWidth")] public double CellWidth { get; set; } [JsonPropertyName("cellHeight")] public double CellHeight { get; set; } } class TemplateMatchResponse { [JsonPropertyName("ok")] public bool Ok => true; [JsonPropertyName("found")] public bool Found { get; set; } [JsonPropertyName("x")] public int X { get; set; } [JsonPropertyName("y")] public int Y { get; set; } [JsonPropertyName("width")] public int Width { get; set; } [JsonPropertyName("height")] public int Height { get; set; } [JsonPropertyName("confidence")] public double Confidence { get; set; } } class DiffOcrParams { [JsonPropertyName("diffThresh")] public int DiffThresh { get; set; } = 20; [JsonPropertyName("rowThreshDiv")] public int RowThreshDiv { get; set; } = 40; [JsonPropertyName("colThreshDiv")] public int ColThreshDiv { get; set; } = 8; [JsonPropertyName("maxGap")] public int MaxGap { get; set; } = 20; [JsonPropertyName("trimCutoff")] public double TrimCutoff { get; set; } = 0.4; [JsonPropertyName("kernelSize")] public int KernelSize { get; set; } = 41; [JsonPropertyName("upscale")] public int Upscale { get; set; } = 2; [JsonPropertyName("useBackgroundSub")] public bool UseBackgroundSub { get; set; } = true; [JsonPropertyName("dimPercentile")] public int DimPercentile { get; set; } = 40; [JsonPropertyName("textThresh")] public int TextThresh { get; set; } = 60; [JsonPropertyName("softThreshold")] public bool SoftThreshold { get; set; } = false; [JsonPropertyName("ocrPad")] public int OcrPad { get; set; } = 10; [JsonPropertyName("usePerLineOcr")] public bool UsePerLineOcr { get; set; } = false; [JsonPropertyName("lineGapTolerance")] public int LineGapTolerance { get; set; } = 10; [JsonPropertyName("linePadY")] public int LinePadY { get; set; } = 20; [JsonPropertyName("psm")] public int Psm { get; set; } = 6; public DiffOcrParams Clone() => (DiffOcrParams)MemberwiseClone(); public override string ToString() => UseBackgroundSub ? $"bgSub dimPct={DimPercentile} textThresh={TextThresh} soft={SoftThreshold} ocrPad={OcrPad} perLine={UsePerLineOcr} lineGap={LineGapTolerance} linePadY={LinePadY} psm={Psm} diffThresh={DiffThresh} rowThreshDiv={RowThreshDiv} colThreshDiv={ColThreshDiv} maxGap={MaxGap} trimCutoff={TrimCutoff:F2} upscale={Upscale}" : $"topHat kernelSize={KernelSize} ocrPad={OcrPad} perLine={UsePerLineOcr} lineGap={LineGapTolerance} linePadY={LinePadY} psm={Psm} diffThresh={DiffThresh} rowThreshDiv={RowThreshDiv} colThreshDiv={ColThreshDiv} maxGap={MaxGap} trimCutoff={TrimCutoff:F2} upscale={Upscale}"; } class TestCase { [JsonPropertyName("id")] public string Id { get; set; } = ""; [JsonPropertyName("image")] public string Image { get; set; } = ""; [JsonPropertyName("fullImage")] public string FullImage { get; set; } = ""; [JsonPropertyName("expected")] public List Expected { get; set; } = []; } class TestCaseResult { [JsonPropertyName("id")] public string Id { get; set; } = ""; [JsonPropertyName("passed")] public bool Passed { get; set; } [JsonPropertyName("score")] public double Score { get; set; } [JsonPropertyName("matched")] public List Matched { get; set; } = []; [JsonPropertyName("missed")] public List Missed { get; set; } = []; [JsonPropertyName("extra")] public List Extra { get; set; } = []; } class TestResponse { [JsonPropertyName("ok")] public bool Ok => true; [JsonPropertyName("passed")] public int Passed { get; set; } [JsonPropertyName("failed")] public int Failed { get; set; } [JsonPropertyName("total")] public int Total { get; set; } [JsonPropertyName("results")] public List Results { get; set; } = []; } class TuneResponse { [JsonPropertyName("ok")] public bool Ok => true; [JsonPropertyName("bestScore")] public double BestScore { get; set; } [JsonPropertyName("bestParams")] public DiffOcrParams BestParams { get; set; } = new(); [JsonPropertyName("iterations")] public int Iterations { get; set; } }