void _kernel(SpanTensor2 <Pixel.RGB24> src, SpanTensor2 <Pixel.Luminance8> dst) { // src & dst dimensions must be 512x512 var workingTensor = _Session.GetInputTensor <float>(0) .AsSpanTensor4() .GetSubTensor(0) .VerifyDimensions(3, 512, 512); SpanTensor.Copy(src.DownCast <Byte>(), workingTensor[0], workingTensor[1], workingTensor[2], MultiplyAdd.CreateMul(255).GetInverse()); // increase image contrast (optional) var imagePreprocessor = new ImageProcessor <Pixel.RGB96F>(); imagePreprocessor.ColorTransform = MultiplyAdd.CreateAdd(-0.5f).ConcatMul(1.7f); imagePreprocessor.ColorTransform.ApplyTransformTo(workingTensor.Span); _Session.Inference(); var result = _Session.GetOutputTensor <float>(0) .AsSpanTensor4() .GetSubTensor(0) .VerifyDimensions(1, 512, 512) .GetSubTensor(0); SpanTensor.Copy(result, dst.Cast <Byte>(), MultiplyAdd.CreateMul(255)); }
// https://github.com/Kazuhito00/YuNet-ONNX-TFLite-Sample/blob/main/yunet/yunet_onnx.py // MIN_SIZES = [[10, 16, 24], [32, 48], [64, 96], [128, 192, 256]] // STEPS = [8, 16, 32, 64] // VARIANCE = [0.1, 0.2] public static SpanTensor2 <System.Numerics.Vector4> priorbox( int feature_width, int feature_height, int img_width, int img_height, int step, int num_sizes, float[] pWinSizes) { var outputData = new SpanTensor2 <System.Numerics.Vector4>(feature_height, feature_width); for (int r = 0; r < outputData.Dimensions[1]; r++) { for (int c = 0; c < outputData.Dimensions[0]; c++) { //priorbox for (int s = 0; s < num_sizes; s++) { float min_size_ = pWinSizes[s]; float center_x = (c + 0.5f) * step; float center_y = (r + 0.5f) * step; var xmin = (center_x - min_size_ / 2f) / img_width; var ymin = (center_y - min_size_ / 2f) / img_height; var xmax = (center_x + min_size_ / 2f) / img_width; var ymax = (center_y + min_size_ / 2f) / img_height; outputData[c, r] = new System.Numerics.Vector4(xmin, ymin, xmax, ymax); } } } return(outputData); }
public static unsafe BitmapSampler <TPixel> From(SpanTensor2 <TPixel> tensor, ColorEncoding encoding) { var w = tensor.BitmapSize.Width; var h = tensor.BitmapSize.Height; var b = MMARSHALL.Cast <TPixel, byte>(tensor.Span); var e = encoding; return(new BitmapSampler <TPixel>(b, w * sizeof(TPixel), w, h, e)); }
public TensorBitmap(SpanTensor2 <T> tensor, ColorEncoding encoding) { _ChannelX = tensor.Span; _ChannelY = default; _ChannelZ = default; _ChannelW = default; _Channels = 1; _Width = tensor.Dimensions[1]; _Height = tensor.Dimensions[0]; _Encoding = encoding; }
public void Filter(SpanBitmap srcImage, ref MemoryBitmap <Pixel.Luminance8> dstImage) { var srcTensor = new SpanTensor2 <Pixel.RGB24>(srcImage.Height, srcImage.Width); srcTensor.AsSpanBitmap().AsTypeless().SetPixels(0, 0, srcImage); var stats = srcTensor.Statistics as Statistics.Vector3; var dstTensor = new SpanTensor2 <Pixel.Luminance8>(srcImage.Height, srcImage.Width); // use a fixed 512x512 kernel to iterate through the image, processing small chunks srcTensor.CopyTo(dstTensor, new TensorSize2(512, 512), _kernel, new TensorIndices2(32, 32)); // copy the tensor data back to the dst image dstTensor.AsTensorBitmap(Tensors.Imaging.ColorEncoding.L).CopyTo(ref dstImage); }
// https://github.com/atksh/onnx-facial-lmk-detector public static FullStackFaceInfo[] Parse(SpanTensor1 <float> scores, SpanTensor2 <Int64> bboxes, SpanTensor3 <Pixel.BGR24> align_imgs, SpanTensor3 <Int64> lmks) { var result = new FullStackFaceInfo[scores.Dimensions[0]]; for (int i = 0; i < scores.Dimensions[0]; ++i) { result[i].Score = scores[i]; var bbox = bboxes[i]; result[i].BoundingBox = new System.Drawing.Rectangle((int)bbox[0], (int)bbox[1], (int)bbox[2], (int)bbox[3]); MemoryBitmap <Pixel.BGR24> bmp = default; align_imgs[i].AsTensorBitmap(Tensors.Imaging.ColorEncoding.RGB).CopyTo(ref bmp); result[i].AlignedImage = bmp; var lmarks = lmks[i].ToArray(); } return(result); }
public static void DrawPixelLine <TPixel>(this SpanTensor2 <TPixel> bitmap, XY a, XY b, TPixel color) where TPixel : unmanaged { var bounds = bitmap.Dimensions; var ab = b - a; if (Math.Abs(ab.X) <= 1 && Math.Abs(ab.Y) <= 1) // can't loop; draw a single pixel { int x = (int)a.X; int y = (int)a.Y; if (bounds.ContainsIndices(y, x)) { bitmap[y].Span[x] = color; } return; } if (Math.Abs(ab.X) > Math.Abs(ab.Y)) // loop from left to right { var ptr = a; var max = b.X; if (ab.X < 0) { ab = -ab; ptr = b; max = a.X; } var d = new XY(1, ab.Y / ab.X); while (ptr.X <= max) { int x = (int)ptr.X; int y = (int)ptr.Y; if (bounds.ContainsIndices(y, x)) { bitmap[y].Span[x] = color; } ptr += d; } } else // loop from top to bottom { var ptr = a; var max = b.Y; if (ab.Y < 0) { ab = -ab; ptr = b; max = a.Y; } var d = new XY(ab.X / ab.Y, 1); while (ptr.Y <= max) { int x = (int)ptr.X; int y = (int)ptr.Y; if (bounds.ContainsIndices(y, x)) { bitmap[y].Span[x] = color; } ptr += d; } } }