public static void Sum_Avx(NativeImage <float> img1, NativeImage <float> img2, NativeImage <float> res) { var w8 = res.Width / 8 * 8; for (var j = 0; j < res.Height; j++) { var p1 = img1.PixelAddr(0, j); var p2 = img2.PixelAddr(0, j); var r = res.PixelAddr(0, j); for (var i = 0; i < w8; i += 8) { Avx.StoreAligned(r, Avx.Add(Avx.LoadAlignedVector256(p1), Avx.LoadAlignedVector256(p2))); p1 += 8; p2 += 8; r += 8; } for (var i = w8; i < res.Width; i++) { *r++ = *p1++ + *p2++; } } }
public static void Sum_RefMethod(NativeImage <float> img1, NativeImage <float> img2, NativeImage <float> res) { for (var j = 0; j < res.Height; j++) { for (var i = 0; i < res.Width; i++) { res.Pixel(i, j) = img1.Pixel(i, j) + img2.Pixel(i, j); } } }
public static void Sum_GetSetMethods(NativeImage <float> img1, NativeImage <float> img2, NativeImage <float> res) { for (var j = 0; j < res.Height; j++) { for (var i = 0; i < res.Width; i++) { res.SetUnsafe(i, j, img1.GetUnsafe(i, j) + img2.GetUnsafe(i, j)); } } }
public static void Sum_ThisProperty(NativeImage <float> img1, NativeImage <float> img2, NativeImage <float> res) { for (var j = 0; j < res.Height; j++) { for (var i = 0; i < res.Width; i++) { res[i, j] = img1[i, j] + img2[i, j]; } } }
public Median(NativeImage <float> src, int rad, NativeImage <float> res) { this.src = src; this.rad = rad; this.res = res; diam = 2 * rad + 1; N = diam * diam; arr = new float[N]; w1 = src.Width - 1; h1 = src.Height - 1; }
public Convolution(NativeImage <float> img, NativeImage <float> kernel, NativeImage <float> res) { this.img = img; this.kernel = kernel; this.res = res; ofsx = kernel.Width / 2; ofsy = kernel.Height / 2; kw1 = kernel.Width - 1; kh1 = kernel.Height - 1; iw1 = img.Width - 1; ih1 = img.Height - 1; }
public static void Rotate180(NativeImage <float> src, NativeImage <float> dst) { var w = src.Width - 1; var h = src.Height - 1; for (var j = 0; j <= h; j++) { for (var i = 0; i <= w; i++) { dst[w - i, h - j] = src[i, j]; } } }
public static void Rotate180_Optimized(NativeImage <float> src, NativeImage <float> dst) { var w = src.Width; for (var j = 0; j < src.Height; j++) { var s = src.PixelAddr(0, j); var d = dst.PixelAddr(src.Width, j); for (var i = 0; i < w; i++) { *--d = *s++; } } }
public void TestConvolve() { var img = Shape(3, 4, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f); var kernel = Shape(2, 3, 1.0f, 0.0f, 0.0f, 2.0f, 3.0f, 1.0f); var expected = Shape(3, 4, 10.0f, 14.0f, 21.0f, 19.0f, 23.0f, 30.0f, 40.0f, 44.0f, 51.0f, 58.0f, 62.0f, 69.0f); var res = new NativeImage <float>(3, 4); ImageOperations.Convolve(img, kernel, res); Assert.True(BitmapEquals(res, expected)); ImageOperations.Convolve_Optimized(img, kernel, res); Assert.True(BitmapEquals(res, expected)); ImageOperations.Convolve_Avx(img, kernel, res); Assert.True(BitmapEquals(res, expected)); }
static NativeImage <T> Shape <T>(int w, int h, params T[] data) where T : unmanaged { var res = new NativeImage <T>(w, h); for (int j = 0; j < h; j++) { for (int i = 0; i < w; i++) { var k = j * w + i; res[i, j] = k < data.Length ? data[k] : default; } } return(res); }
public static void Sum_Optimized(NativeImage <float> img1, NativeImage <float> img2, NativeImage <float> res) { var w = res.Width; for (var j = 0; j < res.Height; j++) { var p1 = img1.PixelAddr(0, j); var p2 = img2.PixelAddr(0, j); var r = res.PixelAddr(0, j); for (var i = 0; i < w; i++) { r[i] = p1[i] + p2[i]; } } }
static bool BitmapEquals <T>(NativeImage <T> img1, NativeImage <T> img2) where T : unmanaged { if (img1.Width != img2.Width || img1.Height != img2.Height) { return(false); } for (int j = 0; j < img1.Height; j++) { for (int i = 0; i < img1.Width; i++) { if (!EqualityComparer <T> .Default.Equals(img1[i, j], img2[i, j])) { return(false); } } } return(true); }
public void TestSum() { var img1 = Shape(2, 3, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f); var img2 = Shape(2, 3, 2.0f, 4.0f, 1.0f, 5.0f, 3.0f, 7.0f); var img3 = Shape(2, 3, 3.0f, 6.0f, 4.0f, 9.0f, 8.0f, 13.0f); var res = new NativeImage <float>(2, 3); ImageOperations.Sum_GetSetMethods(img1, img2, res); Assert.True(BitmapEquals(img3, res)); ImageOperations.Sum_RefMethod(img1, img2, res); Assert.True(BitmapEquals(img3, res)); ImageOperations.Sum_ThisProperty(img1, img2, res); Assert.True(BitmapEquals(img3, res)); ImageOperations.Sum_Avx(img1, img2, res); Assert.True(BitmapEquals(img3, res)); ImageOperations.Sum_Optimized(img1, img2, res); Assert.True(BitmapEquals(img3, res)); }
public static void Rotate180_Avx(NativeImage <float> src, NativeImage <float> dst) { var w8 = src.Width / 8 * 8; for (var j = 0; j < src.Height; j++) { var s = src.PixelAddr(0, j); var d = dst.PixelAddr(src.Width, j); for (var i = 0; i < w8; i += 8) { var v = Avx.Permute(Avx.LoadAlignedVector256(s), 0x1b); s += 8; d -= 8; Avx.Store(d, Avx.Permute2x128(v, v, 1)); } for (var i = w8; i < src.Width; i++) { *--d = *s++; } } }
public Benchmarks() { img1 = new NativeImage <float>(size, size); img2 = new NativeImage <float>(size, size); kernel = new NativeImage <float>(7, 7); res = new NativeImage <float>(size, size); for (var j = 0; j < res.Height; j++) { for (var i = 0; i < res.Width; i++) { img1[i, j] = 1.0f; img2[i, j] = 2.0f; } } for (var j = 0; j < kernel.Height; j++) { for (var i = 0; i < kernel.Width; i++) { kernel[i, j] = 1.0f; } } }
public static void MedianFilter(NativeImage <float> src, int rad, NativeImage <float> res) { new Median(src, rad, res).Perform(); }
public static void Convolve_AvxIsolated(NativeImage <float> img, NativeImage <float> kernel, NativeImage <float> res) { using var tmp = new NativeImage <float>(kernel.Width, kernel.Height); Rotate180(kernel, tmp); new Convolution(img, tmp, res).PerformVectorIsolated(); }