private byte[,] LinqBinarize(byte[,] grayImage) { var integral = from g in grayImage from ri in Result.InitWith(0) from rq in Result.InitWith(0L) select ValueTuple.Create( ri[-1, 0] + ri[0, -1] - ri[-1, -1] + g, rq[-1, 0] + rq[0, -1] - rq[-1, -1] + g *g); var(integral_image, integral_sqimg) = integral.ToArrays(); var whalf = W / 2; var t = from g in grayImage from i in integral_image.With(OutOfBoundsStrategy.Integral(0)) from q in integral_sqimg.With(OutOfBoundsStrategy.Integral(0L)) let tl = i.Offset(-whalf - 1, -whalf - 1) let tr = i.Offset(-whalf - 1, whalf) let bl = i.Offset(whalf, -whalf - 1) let br = i.Offset(whalf, whalf) let tlq = q.Offset(-whalf - 1, -whalf - 1) let trq = q.Offset(-whalf - 1, whalf) let blq = q.Offset(whalf, -whalf - 1) let brq = q.Offset(whalf, whalf) let area = (br.X - tl.X) * (br.Y - tl.Y) let diff = br + tl - tr - bl let sqdiff = brq.Value + tlq.Value - trq.Value - blq.Value let mean = (double)diff / area let std = Math.Sqrt((sqdiff - diff * mean) / (area - 1)) let threshold = mean * (1 + K * ((std / 128) - 1)) select g > threshold ? (byte)255 : (byte)0; return(t.ToArray()); }
static void Main(string[] args) { var WHalf = 6; var K = 0.3; var integrateQuery = from d in new byte[0, 0] from rl in Result.InitWith(0) from rq in Result.InitWith(0L) select ValueTuple.Create( rl[-1, 0] + rl[0, -1] - rl[-1, -1] + d, rq[-1, 0] + rq[0, -1] - rq[-1, -1] + d *d); var thresholdQuery = from i in new int[0, 0].With(OutOfBoundsStrategy.Integral(0)) from q in new long[0, 0].With(OutOfBoundsStrategy.Integral(0L)) let itl = i.Offset(-WHalf - 1, -WHalf - 1) let itr = i.Offset(-WHalf - 1, WHalf) let ibl = i.Offset(WHalf, -WHalf - 1) let ibr = i.Offset(WHalf, WHalf) let sum = ibr + itl - itr - ibl let qtl = q.Offset(-WHalf - 1, -WHalf - 1) let qtr = q.Offset(-WHalf - 1, WHalf) let qbl = q.Offset(WHalf, -WHalf - 1) let qbr = q.Offset(WHalf, WHalf) let sumsq = qbr + qtl - qtr - qbl let area = (ibr.X - itl.X) * (ibr.Y - itl.Y) let mean = (double)sum / area let std = Math.Sqrt((sumsq - sum * mean) / (area - 1)) select(byte)(mean * (1 + K * ((std / 128) - 1))); var detectQuery = from d in new byte[0, 0] from t in new byte[0, 0] select d > t ? byte.MaxValue : byte.MinValue; var integrate = integrateQuery.Transform; var getThreshold = thresholdQuery.Transform; var detect = detectQuery.Transform; foreach (var fileName in args) { var(data, palette) = IO.ReadImage(fileName); data = (from d in data select palette[d]).ToArray(); Array2d.TryVectorize = true; var(s, sq) = integrate(data); var t = getThreshold(s, sq); var r = detect(data, t); IO.WriteImage(Path.ChangeExtension(fileName, ".threshold.bmp"), t); IO.WriteImage(Path.ChangeExtension(fileName, ".linq.bmp"), r); } }
public void TestSteps(int h, int w, byte seed) { var grayImage = ArrayHelper.InitAllRand(h, w, seed); var integral = from g in grayImage from ri in Result.InitWith(0) from rq in Result.InitWith((square)0) select ValueTuple.Create( ri[-1, 0] + ri[0, -1] - ri[-1, -1] + g, rq[-1, 0] + rq[0, -1] - rq[-1, -1] + g *g); var(integral_image_linq, integral_sqimg_linq) = integral.ToArrays(); var(integral_image, integral_sqimg) = DoubleIntegrateSlow(h, w, grayImage); TestHelper.AssertEqual(integral_image, integral_image_linq); TestHelper.AssertEqual(integral_sqimg, integral_sqimg_linq); var whalf = W / 2; var area = from i in integral_image_linq.With(OutOfBoundsStrategy.Integral(0)) let tl = i.Offset(-whalf - 1, -whalf - 1) let br = i.Offset(whalf, whalf) select(br.X - tl.X) * (br.Y - tl.Y); var areaA = area.ToArray(); TestHelper.AssertEqual(CalculateArea(grayImage, whalf), area.ToArray()); var diff = from i in integral_image_linq.With(OutOfBoundsStrategy.Integral(0)) let tl = i.Offset(-whalf - 1, -whalf - 1) let tr = i.Offset(-whalf - 1, whalf) let bl = i.Offset(whalf, -whalf - 1) let br = i.Offset(whalf, whalf) select br.Value + tl.Value - tr.Value - bl.Value; var diffA = diff.ToArray(); TestHelper.AssertEqual(CalculateDiff(integral_image_linq, whalf), diff.ToArray()); var sqdiff = from i in integral_sqimg_linq.With(OutOfBoundsStrategy.Integral(0L)) let tl = i.Offset(-whalf - 1, -whalf - 1) let tr = i.Offset(-whalf - 1, whalf) let bl = i.Offset(whalf, -whalf - 1) let br = i.Offset(whalf, whalf) select br.Value + tl.Value - tr.Value - bl.Value; TestHelper.AssertEqual(CalculateDiff(integral_sqimg_linq, whalf), sqdiff.ToArray()); var mean = from d in diffA from a in areaA select(double) d / a; TestHelper.AssertEqual(CalculateMean(diffA, areaA), mean.ToArray()); var std = from sqd in sqdiff.ToArray() from d in diffA from a in areaA from m in mean.ToArray() select Math.Sqrt((sqd - d *m) / (a - 1)); TestHelper.AssertEqual(CalculateStd(sqdiff.ToArray(), diffA, areaA, mean.ToArray()), std.ToArray()); var thresh = from m in mean.ToArray() from s in std.ToArray() select m *(1 + K * ((s / 128) - 1)); TestHelper.AssertEqual(CalculateThreshold(mean.ToArray(), std.ToArray()), thresh.ToArray()); }