public void TestPixelTransferWithTransform2(bool useBilinear) { var imgPath = System.IO.Path.Combine(TestContext.CurrentContext.TestDirectory, "Resources", "dog.jpeg"); var img = Graphics.Bitmaps.MemoryBitmap <BGR24> .Load(imgPath); if (!img.AsSpanBitmap().TryGetAsSpanTensor(out var src)) { throw new InvalidOperationException(); } var dst = new SpanTensor2 <BGR24>(384, 384); var dst2 = new SpanTensor2 <System.Numerics.Vector3>(384, 384); var srcX = System.Numerics.Matrix3x2.CreateScale(0.4f) * System.Numerics.Matrix3x2.CreateRotation(0.3f); srcX.Translation = new System.Numerics.Vector2(15, 35); var time = System.Diagnostics.Stopwatch.StartNew(); dst.AsTensorBitmap(Imaging.ColorEncoding.Undefined).FillPixels(src.AsBitmapSampler(Imaging.ColorEncoding.BGR), (srcX, MultiplyAdd.Identity, useBilinear)); time.Stop(); TestContext.WriteLine($"{time.Elapsed.TotalMilliseconds}"); time = System.Diagnostics.Stopwatch.StartNew(); dst2.AsTensorBitmap(Imaging.ColorEncoding.Undefined).FillPixels(src.AsBitmapSampler(Imaging.ColorEncoding.BGR), (srcX, MultiplyAdd.Identity, useBilinear)); time.Stop(); TestContext.WriteLine($"{time.Elapsed.TotalMilliseconds}"); dst.AttachToCurrentTest($"tensorTransform-{useBilinear}.png"); }
public static TensorIndices2 IndexOfMax <T>(this SpanTensor2 <T> tensor, IComparer <T> comparer = null) where T : unmanaged, IEquatable <T> { var span = tensor._Buffer; if (span.Length == 0) { return(TensorIndices2.Invalid); } if (comparer == null) { comparer = Comparer <T> .Default; } T max = span[0]; var idx = 0; for (int i = 1; i < span.Length; ++i) { var item = span[i]; if (comparer.Compare(max, item) > 0) { max = item; idx = i; } } return(tensor._Dimensions.GetDecomposedIndex(idx)); }
public void TestPixelTransferWithTransform1() { var src = new SpanTensor2 <BGR24>(16, 16); var dst = new SpanTensor2 <BGR24>(50, 50); for (int y = 0; y < src.Dimensions[0]; y++) { var row = src[y]; for (int x = 0; x < src.Dimensions[1]; x++) { row[x] = (y * 16, x * 16, x + y * 2); } } var srcX = System.Numerics.Matrix3x2.CreateScale(1) * System.Numerics.Matrix3x2.CreateRotation(0.3f); srcX.Translation = new System.Numerics.Vector2(-15, -35); dst.AsTensorBitmap(Imaging.ColorEncoding.Undefined).FillPixels(src.AsBitmapSampler(Imaging.ColorEncoding.BGR), (srcX, MultiplyAdd.Identity)); // dst.FitPixels(src, MultiplyAdd.Identity, true); dst.AttachToCurrentTest("tensorTransform.png"); }
public static TensorIndices2 IndexOf <T>(this SpanTensor2 <T> tensor, T value) where T : unmanaged, IEquatable <T> { var idx = tensor._Buffer.IndexOf(value); if (idx < 0) { return(TensorSize2.Invalid); } return(tensor._Dimensions.GetDecomposedIndex(idx)); }
public void PointCloudFitting() { // https://github.com/ClayFlannigan/icp/blob/master/icp.py // create original point cloud var ppp0 = new Vector3[16]; var rnd = new Random(117); for (int i = 0; i < ppp0.Length; ++i) { var x = (float)rnd.NextDouble() * 16 - 8; var y = (float)rnd.NextDouble() * 16 - 8; var z = (float)rnd.NextDouble() * 16 - 8; ppp0[i] = new Vector3(x, y, z); } // create rotated point clound var rot = Matrix4x4.CreateFromYawPitchRoll(1, 2, 3); Matrix4x4.Invert(rot, out Matrix4x4 irot); var ppp1 = new Vector3[ppp0.Length]; for (int i = 0; i < ppp0.Length; ++i) { ppp1[i] = Vector3.Transform(ppp0[i], rot); } // original point cloud tensor var t0 = SpanTensor.Wrap(ppp0); var t0t = new SpanTensor2 <float>(t0.Dimensions[1], t0.Dimensions[0]); SpanTensor.Transpose(t0, t0t); // rotated point cloud tensor var t1 = SpanTensor.Wrap(ppp1); var t1t = new SpanTensor2 <float>(t1.Dimensions[1], t1.Dimensions[0]); SpanTensor.Transpose(t1, t1t); // multiplied var combined = new SpanTensor2 <float>(3, 3); SpanTensor.MatrixMultiply(t1t, t0, combined); // decomposition var v = new SpanTensor2 <float>(3, 3); var w = new float[3]; combined.SVD(w, v); }
public void CopyTo <Tout>(SpanTensor2 <Tout> masterOut, TensorSize2 kernelSize, Kernel2Copy <T, Tout> kernel, TensorIndices2 margin = default) where Tout : unmanaged { var tmpSrc = new SpanTensor2 <T>(kernelSize); var tmpDst = new SpanTensor2 <Tout>(kernelSize); var stepSize = kernelSize - margin - margin; for (int i0 = 0; i0 < masterOut.Dimensions[0]; i0 += stepSize[0]) { for (int i1 = 0; i1 < masterOut.Dimensions[1]; i1 += stepSize[1]) { var offset = new TensorIndices2(i0, i1); this.CopyTo(offset, tmpSrc, default, kernelSize);
public static void SetGrayPixels(SpanTensor2 <Single> dst, PointerBitmap src, Single offset, Single scale) { if (src.Size != dst.BitmapSize) { throw new ArgumentException(nameof(dst.BitmapSize)); } var dstSpan = dst.AsSpanBitmap(); var srcSpan = src.AsSpanBitmap(); if (srcSpan.PixelFormat.ByteCount == 1) { SpanBitmap.CopyPixels(srcSpan.OfType <Byte>(), dstSpan, (offset, scale), (0, 1)); } }
public static TensorIndices2 IndexOf <T>(this SpanTensor2 <T> tensor, Predicate <T> predicate) where T : unmanaged, IEquatable <T> { var span = tensor._Buffer; for (int i = 0; i < span.Length; ++i) { if (predicate(span[i])) { return(tensor._Dimensions.GetDecomposedIndex(i)); } } return(TensorIndices2.Invalid); }
public void CopyTo(TensorIndices2 srcOffset, SpanTensor2 <T> dst, TensorIndices2 dstOffset, TensorSize2 size) { size = TensorSize2.Min(size, TensorSize2.ExclusiveUnion(this.Dimensions, ref srcOffset, dst.Dimensions, ref dstOffset)); for (int i0 = 0; i0 < size[0]; ++i0) { var srcSpan = this[srcOffset[0] + i0].Span.Slice(srcOffset[1]); var dstSpan = dst[dstOffset[0] + i0].Span.Slice(dstOffset[1]); var l1 = Math.Min(srcSpan.Length, dstSpan.Length); l1 = Math.Min(l1, size[1]); srcSpan.Slice(0, l1).CopyTo(dstSpan); } }
public static void ApplySoftMax(this SpanTensor2 <float> tensor) { SpanTensor.ApplySoftMax(tensor.Span); }
public static int SVD(this SpanTensor2 <float> a, float[] w, SpanTensor2 <float> v) { int flag, jj, l = 0, nm = 0; float c, f, h, s, x, y, z; float anorm = 0f, g = 0f, scale = 0f; int m = a.Dimensions[0]; // not sure if it's 0 or 1 int n = a.Dimensions[1]; // not sure if it's 0 or 1 if (m < n) { // fprintf(stderr, "#rows must be > #cols \n"); return(0); } var rv1 = new float[n]; // use stackalloc /* Householder reduction to bidiagonal form */ for (int i = 0; i < n; i++) { /* left-hand reduction */ l = i + 1; rv1[i] = scale * g; g = s = scale = 0f; if (i < m) { for (int k = i; k < m; k++) { scale += Math.Abs(a[k, i]); } if (scale != 0) { for (int k = i; k < m; k++) { a[k, i] = (a[k, i] / scale); s += (a[k, i] * a[k, i]); } f = a[i, i]; g = -_Sign((float)Math.Sqrt(s), f); h = f * g - s; a[i, i] = (f - g); if (i != n - 1) { for (int j = l; j < n; j++) { s = 0; for (int k = i; k < m; k++) { s += (a[k, i] * a[k, j]); } f = s / h; for (int k = i; k < m; k++) { a[k, j] += (f * a[k, i]); } } } for (int k = i; k < m; k++) { a[k, i] = (a[k, i] * scale); } } } w[i] = (scale * g); /* right-hand reduction */ g = s = scale = 0f; if (i < m && i != n - 1) { for (int k = l; k < n; k++) { scale += Math.Abs(a[i, k]); } if (scale != 0) { for (int k = l; k < n; k++) { a[i, k] = (a[i, k] / scale); s += (a[i, k] * a[i, k]); } f = a[i, l]; g = -_Sign((float)Math.Sqrt(s), f); h = f * g - s; a[i, l] = (f - g); for (int k = l; k < n; k++) { rv1[k] = a[i, k] / h; } if (i != m - 1) { for (int j = l; j < m; j++) { s = 0; for (int k = l; k < n; k++) { s += (a[j, k] * a[i, k]); } for (int k = l; k < n; k++) { a[j, k] += s * rv1[k]; } } } for (int k = l; k < n; k++) { a[i, k] = (a[i, k] * scale); } } } anorm = Math.Max(anorm, (Math.Abs(w[i]) + Math.Abs(rv1[i]))); } /* accumulate the right-hand transformation */ for (int i = n - 1; i >= 0; i--) { if (i < n - 1) { if (g != 0) { for (int j = l; j < n; j++) { v[j, i] = ((a[i, j] / a[i, l]) / g); } /* double division to avoid underflow */ for (int j = l; j < n; j++) { s = 0; for (int k = l; k < n; k++) { s += (a[i, k] * v[k, j]); } for (int k = l; k < n; k++) { v[k, j] += (s * v[k, i]); } } } for (int j = l; j < n; j++) { v[i, j] = v[j, i] = 0f; } } v[i, i] = 1f; g = rv1[i]; l = i; } /* accumulate the left-hand transformation */ for (int i = n - 1; i >= 0; i--) { l = i + 1; g = w[i]; if (i < n - 1) { for (int j = l; j < n; j++) { a[i, j] = 0f; } } if (g != 0) { g = 1f / g; if (i != n - 1) { for (int j = l; j < n; j++) { s = 0; for (int k = l; k < m; k++) { s += (a[k, i] * a[k, j]); } f = (s / a[i, i]) * g; for (int k = i; k < m; k++) { a[k, j] += (f * a[k, i]); } } } for (int j = i; j < m; j++) { a[j, i] = (a[j, i] * g); } } else { for (int j = i; j < m; j++) { a[j, i] = 0f; } } ++a[i, i]; } /* diagonalize the bidiagonal form */ for (int k = n - 1; k >= 0; k--) { /* loop over singular values */ for (int its = 0; its < 30; its++) { /* loop over allowed iterations */ flag = 1; for (l = k; l >= 0; l--) { /* test for splitting */ nm = l - 1; if (Math.Abs(rv1[l]) + anorm == anorm) { flag = 0; break; } if (Math.Abs(w[nm]) + anorm == anorm) { break; } } if (flag != 0) { c = 0f; s = 1f; for (int i = l; i <= k; i++) { f = s * rv1[i]; if (Math.Abs(f) + anorm != anorm) { g = w[i]; h = _Pythagoras(f, g); w[i] = h; h = 1f / h; c = g * h; s = -f * h; for (int j = 0; j < m; j++) { y = a[j, nm]; z = a[j, i]; a[j, nm] = y * c + z * s; a[j, i] = z * c - y * s; } } } } z = w[k]; if (l == k) { /* convergence */ if (z < 0f) { /* make singular value nonnegative */ w[k] = -z; for (int j = 0; j < n; j++) { v[j, k] = (-v[j, k]); } } break; } if (its >= 30) { // fprintf(stderr, "No convergence after 30,000! iterations \n"); return(0); } /* shift from bottom 2 x 2 minor */ x = w[l]; nm = k - 1; y = w[nm]; g = rv1[nm]; h = rv1[k]; f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2f * h * y); g = _Pythagoras(f, 1f); f = ((x - z) * (x + z) + h * ((y / (f + _Sign(g, f))) - h)) / x; /* next QR transformation */ c = s = 1f; for (int j = l; j <= nm; j++) { int i = j + 1; g = rv1[i]; y = w[i]; h = s * g; g = c * g; z = _Pythagoras(f, h); rv1[j] = z; c = f / z; s = h / z; f = x * c + g * s; g = g * c - x * s; h = y * s; y *= c; for (jj = 0; jj < n; jj++) { x = v[jj, j]; z = v[jj, i]; v[jj, j] = x * c + z * s; v[jj, i] = z * c - x * s; } z = _Pythagoras(f, h); w[j] = z; if (z != 0) { z = 1f / z; c = f * z; s = h * z; } f = (c * g) + (s * y); x = (c * y) - (s * g); for (jj = 0; jj < m; jj++) { y = a[jj, j]; z = a[jj, i]; a[jj, j] = y * c + z * s; a[jj, i] = z * c - y * s; } } rv1[l] = 0f; rv1[k] = f; w[k] = x; } } return(1); }