public FloatImage Convolve(FloatImage k) { var kw = k.Width; var kh = k.Height; var kxs = kw >> 1; var kys = kh >> 1; var r = new FloatImage(_Width, _Height); float total = k.Sum(); for (var dy = 0; dy < _Height; dy++) { for (var dx = 0; dx < _Width; dx++) { var v = 0f; var sum = 0f; for (var ky = 0; ky < kh; ky++) { var sy = dy + ky - kys; if (sy < 0 || _Height <= sy) { continue; } for (var kx = 0; kx < kh; kx++) { var sx = dx + kx - kxs; if (sx < 0 || _Width <= sx) { continue; } var sv = this[sx, sy]; var kv = k[kx, ky]; v += sv * kv; sum += kv; } } r[dx, dy] = total == sum ? v : (v * total / sum); } } return(r); }
public void Test(int seed, int width) { _Output.WriteLine("Vector<float>.Count: {0}", Vector <float> .Count); _Output.WriteLine("Vector.IsHardwareAccelerated: {0}", Vector.IsHardwareAccelerated); var r = new Random(seed); var src = new ByteImage(1280, 720); r.NextBytes(src.Array); var ker = new FloatImage(width, 10); var sum = 0f; for (var i = 0; i < ker.Array.Length; i++) { sum += ker.Array[i] = (float)r.NextDouble(); } ker.MultiplyInplace(1 / sum); var wrapper = new ByteImageWrapper(src); var sw = new Stopwatch(); sw.Start(); var expected = ByteImageOperations <ByteImageWrapper> .ConvolveSingle(wrapper, ker, ker.Width, ker.Height); sw.Stop(); _Output.WriteLine("interface: " + sw.ElapsedMilliseconds + "ms"); sw.Reset(); sw.Start(); var actual = new ByteImageOperations <ByteImageWrapper>().Convolve(wrapper, ker); sw.Stop(); _Output.WriteLine("Vector<float>: " + sw.ElapsedMilliseconds + "ms"); for (var i = 0; i < expected.Array.Length; i++) { Assert.Equal( 0, (expected.Array[i] - actual.Array[i]) / expected.Array[i], 4); } }
internal static FloatImage ConvolveSingle(T image, FloatImage kernel, int kernelWidth, int kernelHeight) { var kernelXRadius = kernel.Width >> 1; var kernelYRadius = kernelHeight >> 1; var r = new FloatImage(image.Width, image.Height); float total = kernel.Sum(); for (var dy = 0; dy < image.Height; dy++) { for (var dx = 0; dx < image.Width; dx++) { var v = 0f; var sum = 0f; for (var ky = 0; ky < kernelHeight; ky++) { var sy = dy + ky - kernelYRadius; if (sy < 0 || image.Height <= sy) { continue; } for (var kx = 0; kx < kernelWidth; kx++) { var sx = dx + kx - kernelXRadius; if (sx < 0 || image.Width <= sx) { continue; } var sv = image[sx, sy]; var kv = kernel[kx, ky]; v += sv * kv; sum += kv; } } r[dx, dy] = total == sum ? v : (v * total / sum); } } return(r); }
public void MultiplyInplaceTest(int width) { _Output.WriteLine("Vector<float>.Count: {0}", Vector <float> .Count); _Output.WriteLine("Vector.IsHardwareAccelerated: {0}", Vector.IsHardwareAccelerated); var src = new FloatImage(width, 1); for (var i = 0; i < src.Array.Length; i++) { src.Array[i] = i + 1; } src.MultiplyInplace(2); for (var i = 0; i < src.Array.Length; i++) { Assert.Equal(src.Array[i], 2 * (i + 1), 7); } }
public FloatImage Resize(int w, int h) { // TODO:bilinearにする var r = new FloatImage(w, h); var xr = w / (float)_Width; var yr = h / (float)_Height; for (var sy = 0; sy < _Height; sy++) { var dy = (int)Math.Max(0, Math.Min(sy * yr, h - 1)); for (var sx = 0; sx < _Width; sx++) { var dx = (int)Math.Max(0, Math.Min(sx * xr, w - 1)); r[dx, dy] += this[sx, sy]; } } return(r); }
FloatImage IByteImageOperations.Convolve(IByteImageWrapper image, FloatImage kernel) => Convolve((T)image, kernel);
public FloatImage Blur(double sigma) => Convolve(FloatImage.CreateGaussian(3, sigma));
public Projections(int regionWidth, int regionHeight, int lineCount) { Region = new Imaging.FloatImage(regionWidth, regionHeight); PixelsPerLine = new int[lineCount]; }