当前位置:首页 > 资讯列表 >C# 实现图像方向智能识别与自动旋转校正

C# 实现图像方向智能识别与自动旋转校正

发布时间:2026-06-11 10:17:13 分类:营销学堂

C# 基于模型识别图像方向并自动校正

背景

部分接口在上传图片时,因图片方向错误导致无法正常识别图像信息(如身份证姓名等)。通常可使用大厂的大模型接口处理,但出于信息敏感要求,需使用本地代码实现图片方向判断。

实现步骤

1. 选择模型文件

使用飞桨生态中的轻量级文档方向分类模型 PP-LCNet_x1_0_doc_ori.onnx,该模型专用于 OCR 图片文档方向分类,准确率较高。

2. 引入 ONNX Runtime

dotnet add package Microsoft.ML.OnnxRuntime

3. 初始化推理会话

程序启动时初始化,全局复用:

private readonly InferenceSession _session = new("./models/PP-LCNet_x1_0_doc_ori.onnx");

4. 图片预处理

原始图片不能直接用于推理,需预处理为模型所需的输入格式 [1, 3, H, W]

// 缩放到模型输入尺寸
using var image = Resize(imageData, _inputWidth, _inputHeight);
if (image == null) return (-1, -1);

// 转为 Tensor [1, 3, H, W],归一化到 [0, 1]
var input = new DenseTensor<float>([1, 3, _inputHeight, _inputWidth]);

for (int y = 0; y < image.Height; y++)
{
    for (int x = 0; x < image.Width; x++)
    {
        var pixel = image.GetPixel(x, y);
        input[0, 0, y, x] = pixel.Red / 255f;   // R
        input[0, 1, y, x] = pixel.Green / 255f;  // G
        input[0, 2, y, x] = pixel.Blue / 255f;   // B
    }
}

5. 执行推理

var inputs = new List<NamedOnnxValue>
{
    NamedOnnxValue.CreateFromTensor("x", input)
};
using var results = _session.Run(inputs);
var output = results[0].AsTensor<float>().ToArray();
var (index, confidence) = GetMax(output);

推理结果为各方向的置信度,取最大值对应的 index(0-3),映射关系为:

index 旋转角度
0
1 90°
2 180°
3 270°
若需更精确的角度判断,可自行生成旋转文本图片作为训练数据,训练专属模型。

6. 旋转校正图片

使用 SkiaSharp 对图片进行旋转处理:

using var image = SKImage.FromEncodedData(imageData);
if (image == null) return imageData;

var width = image.Width;
var height = image.Height;
var orientation = 360 - angle; // 需要旋转的角度
double radians = Math.Abs(orientation * Math.PI / 180.0);
double cos = Math.Abs(Math.Cos(radians));
double sin = Math.Abs(Math.Sin(radians));

var newWidth = (int)Math.Ceiling(width * cos + height * sin);
var newHeight = (int)Math.Ceiling(width * sin + height * cos);

using var bitmap = new SKBitmap(newWidth, newHeight);
using var canvas = new SKCanvas(bitmap);
canvas.Clear(SKColors.Transparent);

canvas.Translate(newWidth / 2f, newHeight / 2f); // 设置旋转中心
canvas.RotateDegrees(orientation);               // 围绕中心旋转

canvas.DrawImage(image,
    new SKRect(0, 0, image.Width, image.Height),
    new SKRect(-width / 2f, -height / 2f, width / 2f, height / 2f));

using var outimage = SKImage.FromBitmap(bitmap);
var dataBytes = outimage.Encode(SKEncodedImageFormat.Jpeg, 70).ToArray();