修复注释乱码

This commit is contained in:
李伟
2026-04-14 17:11:31 +08:00
parent b8bcefc84b
commit cd03e30bb8
58 changed files with 761 additions and 767 deletions
@@ -1,24 +1,25 @@
// ============================================================================
// Copyright © 2026 Hexagon Technology Center GmbH. All Rights Reserved.
// ? SuperResolutionProcessor.cs
// 讛膩: 瘛勗漲摮虫摮?
// 文件名: SuperResolutionProcessor.cs
// 描述: 基于深度学习的超分辨率算子
// 功能:
// - EDSR ?FSRCNN 颲函璅∪嚗㇉NNX 嚗?
// - 2x?x?x 曉之
// - 支持 EDSR FSRCNN 超分辨率模型(ONNX 格式)
// - 支持 2x、3x、4x 放大倍率
// - 灰度图像自动转换为三通道输入,推理后转回灰度
// - 模型文件自动搜索,支持自定义路径
// - 使用 Microsoft.ML.OnnxRuntime 进行推理
// 算法: EDSR (Enhanced Deep Residual SR) / FSRCNN (Fast SR CNN)
// 雿𡏭? 𦒘 wei.lw.li@hexagon.com
// 作者: 李伟 wei.lw.li@hexagon.com
// ============================================================================
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using XP.ImageProcessing.Core;
using Microsoft.ML.OnnxRuntime;
using Microsoft.ML.OnnxRuntime.Tensors;
using Serilog;
using XP.ImageProcessing.Core;
using System.IO;
namespace XP.ImageProcessing.Processors;
@@ -29,9 +30,8 @@ public class SuperResolutionProcessor : ImageProcessorBase
{
private static readonly ILogger _logger = Log.ForContext<SuperResolutionProcessor>();
// 隡朞蝻枏嚗屸憭滚頧?
// 会话缓存,避免重复加载
private static InferenceSession? _cachedSession;
private static string _cachedModelKey = string.Empty;
public SuperResolutionProcessor()
@@ -76,17 +76,17 @@ public class SuperResolutionProcessor : ImageProcessorBase
{
_logger.Error("Model file not found: {Model}_x{Scale}.onnx", model, scale);
throw new FileNotFoundException(
$"颲函璅∪芣𪄳? {model}_x{scale}.onnx\n" +
$"超分辨率模型文件未找到: {model}_x{scale}.onnx\n" +
$"请将模型文件放置到以下任一目录:\n" +
$" 1. 程序目录/Models/\n" +
$" 2. 程序目录/\n" +
$"璅∪閬?ONNX n" +
$"臭蝙?tf2onnx 隞?.pb 頧祆揢:\n" +
$"模型需要 ONNX 格式。\n" +
$"可使用 tf2onnx .pb 转换:\n" +
$" pip install tf2onnx\n" +
$" python -m tf2onnx.convert --input {model}_x{scale}.pb --output {model}_x{scale}.onnx --inputs input:0 --outputs output:0");
}
// 㰘蝸霂?
// 加载或复用会话
string modelKey = $"{model}_{scale}";
InferenceSession session;
if (_cachedModelKey == modelKey && _cachedSession != null)
@@ -111,7 +111,7 @@ public class SuperResolutionProcessor : ImageProcessorBase
session = new InferenceSession(modelPath, options);
_cachedSession = session;
_cachedModelKey = modelKey;
// 霈啣摰鮋雿輻鍂?Execution Provider
// 记录实际使用的 Execution Provider
var providers = session.ModelMetadata?.CustomMetadataMap;
_logger.Information("Loaded ONNX model: {ModelPath}, Providers: {Providers}",
modelPath, string.Join(", ", session.GetType().Name));
@@ -134,7 +134,7 @@ public class SuperResolutionProcessor : ImageProcessorBase
}
/// <summary>
/// 閙活 FSRCNN嚗?
/// 单次推理(小图或 FSRCNN
/// </summary>
private Image<Gray, byte> ProcessSingle(InferenceSession session, Image<Gray, byte> inputImage, int scale)
{
@@ -145,8 +145,8 @@ public class SuperResolutionProcessor : ImageProcessorBase
string inputName = session.InputMetadata.Keys.First();
var inputMeta = session.InputMetadata[inputName];
int[] dims = inputMeta.Dimensions;
// dims : [1, H, W, C] (NHWC)嚗龦 ?1 ?3
int inputChannels = dims[^1]; // 𦒘蝏湔糓𡁻?
// dims 格式: [1, H, W, C] (NHWC)C 可能是 1 或 3
int inputChannels = dims[^1]; // 最后一维是通道数
// 构建输入 tensor: [1, H, W, C] (NHWC)
// 使用底层数组 + Parallel.For 避免逐元素索引开销
@@ -178,7 +178,7 @@ public class SuperResolutionProcessor : ImageProcessorBase
for (int x = 0; x < w; x++)
{
int px = rowOffset + x * 3;
buf[px] = imgData[y, x, 0];
buf[px] = imgData[y, x, 0];
buf[px + 1] = imgData[y, x, 1];
buf[px + 2] = imgData[y, x, 2];
}
@@ -195,13 +195,13 @@ public class SuperResolutionProcessor : ImageProcessorBase
using var results = session.Run(inputs);
var outputTensor = results.First().AsTensor<float>();
// 颲枏枂 shape: [1, C, H*scale, W*scale] (NCHW嚗峕芋餈?Transpose)
// 输出 shape: [1, C, H*scale, W*scale] (NCHW,模型输出经过 Transpose)
var shape = outputTensor.Dimensions;
int outC = shape[1];
int outH = shape[2];
int outW = shape[3];
// 頧祆揢銝箇摨血㦛?
// 转换为灰度图像
// 使用 Parallel.For + 直接内存操作
Image<Gray, byte> result;
if (outC == 1)
@@ -217,7 +217,7 @@ public class SuperResolutionProcessor : ImageProcessorBase
}
else
{
// EDSR: 銝厰𡁻颲枏枂 [1, 3, outH, outW] ?啣漲
// EDSR: 三通道输出 [1, 3, outH, outW] → 灰度
// 直接计算灰度值,跳过中间 BGR 图像分配
result = new Image<Gray, byte>(outW, outH);
var outData = result.Data;
@@ -241,13 +241,13 @@ public class SuperResolutionProcessor : ImageProcessorBase
}
/// <summary>
/// ?EDSR嚗㚁𣂼急綫潭𦻖
/// 分块推理(大图 EDSR),将图像切成小块分别推理后拼接
/// </summary>
private Image<Gray, byte> ProcessTiled(InferenceSession session, Image<Gray, byte> inputImage, int scale, int tileSize)
{
int h = inputImage.Height;
int w = inputImage.Width;
int overlap = 8; // 撠烐𣄽亥器蝻䀝憚敶?
int overlap = 8; // 重叠像素,减少拼接边缘伪影
var result = new Image<Gray, byte>(w * scale, h * scale);
@@ -290,7 +290,7 @@ public class SuperResolutionProcessor : ImageProcessorBase
}
/// <summary>
/// 交𪄳璅∪辣嚗峕隡睃蝥扳蝝W銝芰𤌍敶𤏪.onnx 嚗?
/// 查找模型文件,按优先级搜索多个目录(.onnx 格式)
/// </summary>
private static string FindModelFile(string model, int scale)
{