修复注释乱码
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user