onnx-tensor-math
Provides a high-performance workflow for converting PDF images into normalized float32 tensors for ONNX RT-DETR models.
Install
mkdir -p .claude/skills/onnx-tensor-math && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/13792" && unzip -o skill.zip -d .claude/skills/onnx-tensor-math && rm skill.zipInstalls to .claude/skills/onnx-tensor-math
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Reference guide and workflow for highly optimized image-to-tensor preprocessing for ONNX models (specifically RT-DETR) in .NET.Key capabilities
- →Resize bitmaps to a target size of 640x640
- →Convert SKBitmap to DenseTensor<float> efficiently
- →Normalize pixel values from [0, 255] to [0.0, 1.0]
- →Apply mean and standard deviation normalization to RGB channels
- →Handle color type differences (BGRA vs RGBA) in SkiaSharp
- →Descaling bounding box coordinates back to original image dimensions
How it works
The skill resizes the input bitmap to 640x640, then uses unsafe pointers to directly access pixel memory and convert it into a DenseTensor<float>, applying RT-DETR specific normalization.
Inputs & outputs
When to use onnx-tensor-math
- →Implementing layout inference pipelines
- →Optimizing image-to-tensor conversion
- →Reducing latency in ONNX inference stages
About this skill
onnx-tensor-math Skill
Context
Slice 7 requires extracting a PDF page as an image and converting it into a normalized [1, 3, H, W] float32 tensor for ONNX inference (RT-DETR). Image processing in .NET can be a massive performance bottleneck if done naively (e.g., GetPixel()). This skill defines the strict, high-performance workflow for creating these tensors.
Trigger
Use this skill when implementing the apply_layout_inference pipeline stage, specifically when building the image extraction and tensor normalization logic for OnnxLayoutProvider.
The RT-DETR Preprocessing Specification
According to the upstream preprocessor_config.json for docling-layout-heron-onnx:
- Target Size:
H = 640,W = 640 - Format: RGB (Channels First:
[Batch, Channel, Height, Width]) - Rescale Factor:
1/255.0(Scale pixel values from[0, 255]to[0.0, 1.0]) - Mean (RGB):
[0.485, 0.456, 0.406] - Std (RGB):
[0.229, 0.224, 0.225] - Padding: None (
do_pad = false) - Formula:
tensor_val = ((pixel_val / 255.0) - mean) / std
Workflow
1. Choose the Image Library
Do NOT use System.Drawing.Common (it is Windows-only and slow).
DO use SkiaSharp. It is cross-platform, fast, and provides direct memory access.
2. The Vectorized Extraction Pattern
To convert a SKBitmap to a DenseTensor<float> efficiently, you must use unsafe pointers to bypass bounds checking and object allocation overhead.
// Example high-performance pattern
using SkiaSharp;
using Microsoft.ML.OnnxRuntime.Tensors;
public static DenseTensor<float> CreateNormalizedTensor(SKBitmap bitmap)
{
// 1. Resize to target (640x640)
using var resized = bitmap.Resize(new SKImageInfo(640, 640), SKFilterQuality.Medium);
// Ensure format is exactly 8888 (RGBA or BGRA)
// ...
var tensor = new DenseTensor<float>(new[] { 1, 3, 640, 640 });
// Pre-calculate constants
const float scale = 1f / 255f;
float meanR = 0.485f, meanG = 0.456f, meanB = 0.406f;
float stdR = 0.229f, stdG = 0.224f, stdB = 0.225f;
int width = 640;
int height = 640;
int channelStride = width * height;
unsafe
{
// 2. Get direct pointer to pixel memory
byte* srcPtr = (byte*)resized.GetPixels().ToPointer();
// 3. Get direct pointer to tensor memory (using Span/MemoryMarshal or indexing)
// ... (Implementation specific)
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
// Calculate source index (assuming 4 bytes per pixel: R, G, B, A)
int srcIdx = (y * width + x) * 4;
// Extract R, G, B (Handling BGRA vs RGBA depending on Skia platform defaults!)
byte r = srcPtr[srcIdx]; // (Or srcIdx+2 if BGRA)
byte g = srcPtr[srcIdx + 1];
byte b = srcPtr[srcIdx + 2]; // (Or srcIdx if BGRA)
// Normalize and assign to contiguous channel planes
int destIdxR = 0 * channelStride + (y * width + x);
int destIdxG = 1 * channelStride + (y * width + x);
int destIdxB = 2 * channelStride + (y * width + x);
// Assuming tensor is backed by a 1D array we can index into
// tensorBuffer[destIdxR] = ((r * scale) - meanR) / stdR;
}
}
}
return tensor;
}
3. Critical Edge Cases to Validate
- Color Type (BGRA vs RGBA):
SkiaSharpdefaults toSKColorType.Bgra8888on Windows butRgba8888on Android/Linux. Always explicitly checkbitmap.ColorTypeor convert it to a known type before blindly indexing[srcIdx + 2]. - Memory Leaks: Always
Dispose()or useusingstatements forSKBitmap,SKImage, andSKData. - Bounding Box Descaling: The ONNX model will output bounding boxes relative to the
[640, 640]space. You must multiply these coordinates by(OriginalWidth / 640.0)and(OriginalHeight / 640.0)to map them back to the PDF's native coordinate system before passing them to theLayoutPostprocessor.
When not to use it
- →When the target model is not RT-DETR
- →When the application is not in .NET
- →When high-performance image-to-tensor preprocessing is not required
Prerequisites
Limitations
- →The skill is specifically for RT-DETR preprocessing specifications.
- →It requires handling color type differences (BGRA vs RGBA) explicitly.
- →Bounding box descaling is required after ONNX inference.
How it compares
This workflow uses SkiaSharp with unsafe pointer access for direct memory manipulation, providing a highly optimized conversion that avoids the performance bottlenecks of naive image processing methods like GetPixel().
Compared to similar skills
onnx-tensor-math side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| onnx-tensor-math (this skill) | 0 | 5mo | No flags | Advanced |
| dotnet-native-aot | 0 | 5mo | Review | Advanced |
| technology-selection | 0 | 3mo | Review | Advanced |
| csharp-async | 0 | 2mo | No flags | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by sparkeh9
View all by sparkeh9 →You might also like
dotnet-native-aot
rudironsoni
>-
technology-selection
digablesolutions
Guides technology selection and implementation of AI and ML features in .NET 8+ applications using ML.NET, Microsoft.Extensions.AI (MEAI), Microsoft Agent Framework (MAF), GitHub Copilot SDK, ONNX Runtime, and OllamaSharp. Covers the full spectrum from classic ML through modern LLM orchestration to
csharp-async
artcava
Use when implementing or reviewing async C# code in XPoster: Task-based APIs, cancellation, timeout handling, and sync-over-async avoidance in Azure Functions isolated workflows.
runtime-skills
llama-farm
Universal Runtime best practices for PyTorch inference, Transformers models, and FastAPI serving. Covers device management, model loading, memory optimization, and performance tuning.
csharp-developer
zenobi-us
Expert C# developer specializing in modern .NET development, ASP.NET Core, and cloud-native applications. Masters C# 12 features, Blazor, and cross-platform development with emphasis on performance and clean architecture.
csharp-pro
sickn33
Write modern C# code with advanced features like records, pattern matching, and async/await. Optimizes .NET applications, implements enterprise patterns, and ensures comprehensive testing. Use PROACTIVELY for C# refactoring, performance optimization, or complex .NET solutions.