private Line nextLine(IOIOMatrix image, int numAttempts, Point startPoint) { Line bestLine = new Line(Point.Empty, Point.Empty); double bestScore = double.NegativeInfinity; double bestAvgCover = double.NegativeInfinity; for (int i = 0; i < numAttempts; ++i) { Line line = generateRandomLine(image.Width, image.Height, startPoint); double score = image.Average(line); double avgCover = score / line.Length; if (UseIOIO2) { if (avgCover > bestAvgCover * 0.95 && score > bestScore) { bestScore = score; bestAvgCover = avgCover; bestLine = line; } } else { if (score > bestScore) { bestScore = score; bestAvgCover = avgCover; bestLine = line; } } } image.Subtract(bestLine, GRAY_RESOLUTION); return(bestLine); }
public string Process(string uri, Action <double> callback) { Bitmap _original = null; IOIOMatrix original = null; using (MemoryStream ms = new MemoryStream(Convert.FromBase64String(uri))) { _original = new Bitmap(ms); original = new IOIOMatrix(_original); } // Resize to native resolution. float scale = (float)NATIVE_RESOLUTION / original.Width; var _preview = ResizeImage(_original, scale); var preview = new IOIOMatrix(_preview); // Down-sample. var _inp = ResizeImage(_preview, (float)SCALE); var inp = new IOIOMatrix(_inp); inp.Invert(); inp.Multiply(GRAY_RESOLUTION / SCALE / 255); // Now is the actual algorithm! Point lastP = Point.Empty; double residualDarkness = inp.Average() / GRAY_RESOLUTION * SCALE; double totalLength = 0; List <Line> lines = new List <Line>(); double deltaDarkness = residualDarkness - THRESHOLD; while (residualDarkness > THRESHOLD) { Line bestLine = nextLine(inp, NUM_CANDIDATES, lastP); Line scaledLine = scaleLine(bestLine, 1 / SCALE); lastP = bestLine.B; Line line = new Line( new Point(scaledLine.A.X, scaledLine.A.Y), new Point(scaledLine.B.X, scaledLine.B.Y)); totalLength += line.Length; lines.Add(line); residualDarkness = inp.Average() / GRAY_RESOLUTION * SCALE; callback?.Invoke(1 - (residualDarkness - THRESHOLD) / deltaDarkness); } return(GetImage(preview.Width, preview.Height, lines)); }