C# 基于模型识别图像方向并自动校正
本文包含AI辅助创作内容
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),映射关系为:
若需更精确的角度判断,可自行生成旋转文本图片作为训练数据,训练专属模型。
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();
请先 登录后发表评论 ~