using HalconDotNet;
|
using LB_VisionProcesses.Alogrithms.Halcon;
|
using Newtonsoft.Json;
|
using Newtonsoft.Json.Linq;
|
using System;
|
using System.Collections.Generic;
|
using System.Diagnostics;
|
using System.Linq;
|
using System.Text;
|
using System.Threading.Tasks;
|
using static LB_VisionProcesses.Alogrithms.Halcon.HFindModelTool;
|
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ToolTip;
|
|
namespace LB_VisionProcesses.Alogrithms.Halcon
|
{
|
[Process("Halcon2D单模板匹配工具", Category = "Halcon2D工具", Description = "创建单模板匹配工具")]
|
public class HFindModelTool : TAlgorithm
|
{
|
public enum ModelType { 各向异形模板, 局部变形模板 };
|
|
public enum SubPixel { none, interpolation };
|
|
public enum Metric { use_polarity, ignore_local_polarity };
|
|
|
public HModel ModelID = new HModel();
|
|
public HFindModelTool()
|
{
|
strProcessClass = "LB_VisionProcesses.Alogrithms.Halcon.HFindModelTool";
|
strProcessName = "Halcon2D单模板匹配工具";
|
|
Params.Inputs.Add("ModelType", ModelType.各向异形模板);
|
|
//AngleStart:搜索时的起始角度[需要转换为弧度]
|
Params.Inputs.Add("AngleStart", -5.0);
|
//AngleExtent:搜索时的角度范围,0表示无角度搜索[需要转换为弧度]
|
Params.Inputs.Add("AngleExtent", 10.0);
|
//AngleStep:角度步长--弧度[角度步长 >= 0和角度步长 <= pi / 16]
|
Params.Inputs.Add("AngleStep", "auto");
|
Params.Inputs.Add("ScaleRMin", 0.9);
|
Params.Inputs.Add("ScaleRMax", 1.1);
|
Params.Inputs.Add("ScaleCMin", 0.9);
|
Params.Inputs.Add("ScaleCMax", 1.1);
|
//MinScore:被找到的模板最小分数
|
Params.Inputs.Add("MinScore", 0.5);
|
//NumMatches:要找到的模板最多的实例数,0则找到所有可能的匹配
|
Params.Inputs.Add("NumMatches", 0);
|
//MaxOverlap:允许找到的模型实例的最大重叠比例, 建议值:0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0
|
Params.Inputs.Add("MaxOverlap", 0.2);
|
//SubPixel:计算精度的设置
|
//'none' 不适用亚像素,最大误差为半个像素
|
//'interpolation' 差值得到亚像素精度
|
//'least_squares', 'least_squares_high', 'least_squares_very_high'
|
//'max_deformation 1', 'max_deformation 2', 'max_deformation 3', 'max_deformation 4'
|
Params.Inputs.Add("SubPixel", "none");
|
//NumLevels:搜索时金字塔的层级,0表示不使用金字塔
|
Params.Inputs.Add("NumLevels", 0);
|
//Greediness:贪婪度,搜索启发式,一般都设为0.8,越高速度越快,容易出现找不到的情况
|
Params.Inputs.Add("Greediness", 0.8);
|
Params.Inputs.Add("ResultType", "");
|
|
Params.Inputs.Add("MinCount", 0);
|
Params.Inputs.Add("MaxCount", 9999);
|
|
Params.Outputs.Add("CenterX", new List<double>());
|
Params.Outputs.Add("CenterY", new List<double>());
|
Params.Outputs.Add("Phi", new List<double>());
|
Params.Outputs.Add("Score", new List<double>());
|
Params.Outputs.Add("Count", 0);
|
}
|
|
private static readonly object lockObj = new object();
|
/// <summary>
|
/// 运行算子
|
/// </summary>
|
public override void TAlgorithmMain()
|
{
|
lock (lockObj)
|
{
|
#region 初始化变量
|
HTuple hv_CenterRow = new HTuple();
|
HTuple hv_CenterColumn = new HTuple();
|
HTuple hv_CenterPhi = new HTuple();
|
HTuple hv_Score = new HTuple();
|
#endregion
|
|
try
|
{
|
if (InputImage == null)
|
{
|
Msg = "输入图片为空";
|
Result = false;
|
return;
|
}
|
if (!(InputImage is HObject))
|
{
|
Msg = "输入图片格式不为HObject";
|
Result = false;
|
return;
|
}
|
|
object DomainImage = null;
|
|
#region 裁剪区域
|
if (!ReduceDomainImage(InputImage, ref DomainImage))
|
{
|
Msg = "裁剪区域失败";
|
Result = false;
|
return;
|
}
|
|
HObject hoDomainImage = DomainImage as HObject;
|
HTuple hv_Channels = new HTuple();
|
//判断是否为灰度图
|
using (HDevDisposeHelper dh = new HDevDisposeHelper())
|
{
|
try
|
{
|
HOperatorSet.CountChannels(hoDomainImage, out hv_Channels);
|
if (hv_Channels.TupleInt() != 1)
|
HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage);
|
|
//转换后再次检查是否为灰度图
|
HOperatorSet.CountChannels(hoDomainImage, out hv_Channels);
|
if (hv_Channels.TupleInt() != 1)
|
{
|
HOperatorSet.Rgb1ToGray(hoDomainImage, out hoDomainImage);
|
Msg = "输入图片不为灰度图";
|
Result = false;
|
return;
|
}
|
}
|
catch
|
{
|
Msg = "输入图片不为灰度图且转换失败";
|
Result = false;
|
return;
|
}
|
}
|
#endregion
|
|
//判断是否有模板
|
if (ModelID.hvModel == null || ModelID.hvModel.Length == 0)
|
{
|
Msg = "未创建模板";
|
Result = false;
|
return;
|
}
|
|
#region 算子逻辑
|
Record = new ObjectRecord();
|
HOperatorSet.GetImageSize(ModelID.hoImage, out HTuple ho_ModelWidth, out HTuple ho_ModelHeight);
|
ModelType type = ModelID.Type;
|
double AngleStart = Convert.ToDouble(Params.Inputs["AngleStart"]);
|
double AngleExtent = Convert.ToDouble(Params.Inputs["AngleExtent"]);
|
double MinScore = Convert.ToDouble(Params.Inputs["MinScore"]);
|
int NumMatches = ProcessParams.ConvertToInt32(Params.Inputs["NumMatches"]);
|
double MaxOverlap = Convert.ToDouble(Params.Inputs["MaxOverlap"]);
|
string SubPixel = ProcessParams.ConvertToString(Params.Inputs["SubPixel"]);
|
string NumLevels = ProcessParams.ConvertToString(Params.Inputs["NumLevels"]);
|
double Greediness = Convert.ToDouble(Params.Inputs["Greediness"]);
|
|
double ScaleRMin = Convert.ToDouble(Params.Inputs["ScaleRMin"]);
|
double ScaleRMax = Convert.ToDouble(Params.Inputs["ScaleRMax"]);
|
double ScaleCMin = Convert.ToDouble(Params.Inputs["ScaleCMin"]);
|
double ScaleCMax = Convert.ToDouble(Params.Inputs["ScaleCMax"]);
|
|
switch (type)
|
{
|
case ModelType.局部变形模板:
|
//局部变形模板匹配
|
MaxTimeOut = 8000;
|
#region 参数介绍
|
//* 参数1:输入图像
|
//* 参数2:模板句柄
|
//* 参数3:搜索时的起始角度
|
//* 参数4:搜索时的终止角度,必须与创建模板时的有交集
|
//* 参数5:被找到的模板最小分数--大于等于这个值才能被匹配
|
//* 默认值:0.5 建议值:0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0
|
//* 典型值范围:0≤MinScore ≤ 1
|
//* 最小增量:0.01 建议增量:0.05
|
//* 参数6:要找到的模板最大实例数
|
//* 0 不限制
|
//* 参数7:要找到的模型实例的最大重叠比例
|
//* 默认值:0.5 建议值:0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0
|
//* 典型值范围:0≤ MaxOverlap≤ 1 最小增量:0.01 建议增量:0.05
|
//* 0 表示不允许重叠
|
//* 参数8:计算精度的设置
|
//* 'none' 不适用亚像素,最大误差为半个像素
|
//* 'interpolation' 差值得到亚像素精度
|
//* 'least_squares', 'least_squares_high', 'least_squares_very_high'
|
//* 'max_deformation 1', 'max_deformation 2', 'max_deformation 3', 'max_deformation 4'
|
//* 'max_deformation 5', 'max_deformation 6'
|
//* 参数9:搜索时金字塔的层级
|
//* 参数10:贪婪度,搜索启发式,一般都设为0.8,越高速度快,容易出现找不到的情况
|
//* 0≤ Greediness ≤ 1
|
//* 最后4个:输出匹配位置的行和列坐标、角度、得分 【中心坐标】
|
#endregion
|
|
//0.5为最低分数阈值,后续通过MinScore过滤
|
HOperatorSet.FindLocalDeformableModel(hoDomainImage, out _, out _, out _, ModelID.hvModel
|
, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI
|
, ScaleRMin, ScaleRMax
|
, ScaleCMin, ScaleCMax
|
, 0.5, NumMatches, MaxOverlap
|
, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels)
|
, Greediness, new HTuple(), new HTuple(), new HTuple()
|
, out hv_Score, out hv_CenterRow, out hv_CenterColumn);
|
break;
|
case ModelType.各向异形模板:
|
//形状模板匹配
|
#region 参数介绍
|
//* 参数1:输入图像
|
//* 参数2:模板句柄
|
//* 参数3:搜索时的起始角度
|
//* 参数4:搜索时的终止角度,必须与创建模板时的有交集
|
//* 参数5:被找到的模板最小分数--大于等于这个值才能被匹配
|
//* 默认值:0.5 建议值:0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0
|
//* 典型值范围:0≤MinScore ≤ 1
|
//* 最小增量:0.01 建议增量:0.05
|
//* 参数6:要找到的模板最大实例数
|
//* 0 不限制
|
//* 参数7:要找到的模型实例的最大重叠比例
|
//* 默认值:0.5 建议值:0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0
|
//* 典型值范围:0≤ MaxOverlap≤ 1 最小增量:0.01 建议增量:0.05
|
//* 0 表示不允许重叠
|
//* 参数8:计算精度的设置
|
//* 'none' 不适用亚像素,最大误差为半个像素
|
//* 'interpolation' 差值得到亚像素精度
|
//* 'least_squares', 'least_squares_high', 'least_squares_very_high'
|
//* 'max_deformation 1', 'max_deformation 2', 'max_deformation 3', 'max_deformation 4'
|
//* 'max_deformation 5', 'max_deformation 6'
|
//* 参数9:搜索时金字塔的层级
|
//* 参数10:贪婪度,搜索启发式,一般都设为0.8,越高速度快,容易出现找不到的情况
|
//* 0≤ Greediness ≤ 1
|
//* 最后4个:输出匹配位置的行和列坐标、角度、得分 [中心坐标]
|
#endregion
|
|
//0.5为最低分数阈值,后续通过MinScore过滤
|
HOperatorSet.FindAnisoShapeModel(hoDomainImage, ModelID.hvModel
|
, AngleStart / 180.0 * Math.PI, AngleExtent / 180.0 * Math.PI
|
, ScaleRMin, ScaleRMax
|
, ScaleCMin, ScaleCMax
|
, 0.5, NumMatches, MaxOverlap, SubPixel
|
, NumLevels == "auto" ? NumLevels : Convert.ToInt32(NumLevels)
|
, Greediness
|
, out hv_CenterRow, out hv_CenterColumn
|
, out hv_CenterPhi
|
, out _, out _, out hv_Score);
|
break;
|
default:
|
Msg = "不支持的模板";
|
Result = false;
|
return;
|
}
|
#endregion
|
|
#region 结果处理
|
List<double> CenterX = new List<double>();
|
List<double> CenterY = new List<double>();
|
List<double> Phi = new List<double>();
|
List<double> Score = new List<double>();
|
for (int i = 0; i < hv_CenterRow.Length; i++)
|
{
|
if (hv_Score[i].D < MinScore)
|
continue;
|
|
CenterX.Add(Math.Round(hv_CenterColumn[i].D, 3));
|
CenterY.Add(Math.Round(hv_CenterRow[i].D, 3));
|
|
if (i >= hv_CenterPhi.Length)
|
Phi.Add(0);
|
else
|
Phi.Add(Math.Round(hv_CenterPhi[i].D, 3));
|
|
Score.Add(Math.Round(hv_Score[i].D, 3));
|
//HOperatorSet.GenRectangle2ContourXld(out HObject hRectangle, hv_CenterRow[i].D, hv_CenterColumn[i].D, hv_CenterPhi[i].D, ho_ModelWidth / 2, ho_ModelHeight / 2);
|
HOperatorSet.GenRectangle2(out HObject hRectangle, CenterY[i], CenterX[i], Phi[i], ho_ModelWidth / 2, ho_ModelHeight / 2);
|
((ObjectRecord)Record).AddRecord(hRectangle);
|
}
|
|
Params.Outputs["CenterX"] = CenterX;
|
Params.Outputs["CenterY"] = CenterY;
|
Params.Outputs["Phi"] = Phi;
|
Params.Outputs["Score"] = Score;
|
Params.Outputs["Count"] = Score.Count;
|
#endregion
|
|
#region 生成OutputImage给后续处理
|
try
|
{
|
OutputImage = hoDomainImage;
|
}
|
catch (Exception ex)
|
{
|
Msg = "生成OutputImage失败,原因是:" + ex.ToString();
|
Result = false;
|
return;
|
}
|
#endregion
|
|
if (Msg == "运行超时")
|
{
|
Result = false;
|
Record.ChangeAll2False();
|
return;
|
}
|
|
int MinCount = ProcessParams.ConvertToInt32(Params.Inputs["MinCount"]);
|
int MaxCount = ProcessParams.ConvertToInt32(Params.Inputs["MaxCount"]);
|
|
if (CenterX.Count < MinCount || CenterX.Count > MaxCount)
|
{
|
Msg = string.Format("结果个数超出范围({0},{1})", MinCount, MaxCount);
|
Record.ChangeAll2False();
|
Result = false;
|
return;
|
}
|
|
Msg = "运行成功";
|
Result = true;
|
return;
|
}
|
catch (Exception ex)
|
{
|
Msg = "运行失败,原因是:" + ex.ToString().TrimEnd();
|
OutputImage = null;
|
Result = false;
|
return;
|
}
|
finally
|
{
|
if (!Result)
|
{
|
Params.Outputs["CenterX"] = 0;
|
Params.Outputs["CenterY"] = 0;
|
Params.Outputs["Phi"] = 0;
|
Params.Outputs["Score"] = 0;
|
Params.Outputs["Count"] = 0;
|
}
|
bCompleted = true;
|
#region 内存释放
|
|
#endregion
|
}
|
}
|
}
|
|
public bool CreateModel(HObject Template, ModelType modelType = ModelType.各向异形模板, string NumLevels = "auto"
|
, double AngleStart = -5, double AngleExtent = 10, string AngleStep = "auto"
|
, double ScaleRMin = 0.9, double ScaleRMax = 1.1, string ScaleRStep = "auto"
|
, double ScaleCMin = 1.1, double ScaleCMax = 0.9, string ScaleCStep = "auto"
|
, string Optimization = "none", string Metric = "ignore_local_polarity"
|
, string Contrast = "auto", int MinContrast = 10)
|
{
|
try
|
{
|
#region 参数介绍
|
//Template: : //reduce_domain后的模板图像
|
//NumLevels ,//金字塔的层数,可设为“auto”或0—10的整数
|
//AngleStart ,//模板旋转的起始角度
|
//AngleExtent ,//模板旋转角度范围, >=0
|
//AngleStep ,//旋转角度的步长, >=0 and <=pi/16
|
//Optimization ,//设置模板优化和模板创建方法
|
//Metric , //匹配方法设置
|
//Contrast ,//设置对比度
|
//MinContrast // 设置最小对比度
|
#endregion
|
switch (modelType)
|
{
|
case ModelType.局部变形模板:
|
HOperatorSet.CreateLocalDeformableModel(Template, NumLevels == "auto" ? NumLevels : Convert.ToInt16(NumLevels)
|
, AngleStart, AngleExtent, AngleStep == "auto" ? AngleStep : Convert.ToDouble(AngleStep)
|
, ScaleRMin, ScaleRMax, ScaleRStep == "auto" ? ScaleRStep : Convert.ToDouble(ScaleRStep)
|
, ScaleCMin, ScaleCMax, ScaleCStep == "auto" ? ScaleCStep : Convert.ToDouble(ScaleCStep)
|
, Optimization, Metric
|
, Contrast, MinContrast
|
, new HTuple(), new HTuple()
|
, out ModelID.hvModel);
|
ModelID.hoImage = Template.CopyObj(1, -1);
|
ModelID.Type = ModelType.局部变形模板;
|
return true;
|
case ModelType.各向异形模板:
|
default:
|
HOperatorSet.CreateAnisoShapeModel(Template, NumLevels == "auto" ? NumLevels : Convert.ToInt16(NumLevels)
|
, AngleStart, AngleExtent, AngleStep == "auto" ? AngleStep : Convert.ToDouble(AngleStep)
|
, ScaleRMin, ScaleRMax, ScaleRStep == "auto" ? ScaleRStep : Convert.ToDouble(ScaleRStep)
|
, ScaleCMin, ScaleCMax, ScaleCStep == "auto" ? ScaleCStep : Convert.ToDouble(ScaleCStep)
|
, Optimization, Metric
|
, Contrast, MinContrast, out ModelID.hvModel);
|
ModelID.hoImage = Template.CopyObj(1, -1);
|
ModelID.Type = ModelType.各向异形模板;
|
return true;
|
}
|
}
|
catch { return false; }
|
}
|
|
/// <summary>
|
/// 加载算法
|
/// </summary>
|
/// <param name="fullPath">完整路径带.json</param>
|
/// <returns></returns>
|
public override bool Load(string fullPath)
|
{
|
try
|
{
|
if (string.IsNullOrEmpty(fullPath))
|
return false;
|
|
if (!fullPath.Contains(".json"))
|
{
|
Debug.WriteLine("文件路径不完整");
|
return false;
|
}
|
|
if (fullPath.StartsWith(".\\"))
|
{
|
// 判断原字符串长度是否大于等于2,避免越界
|
if (fullPath.Length >= 2)
|
{
|
// 替换开头两个字符
|
fullPath = Application.StartupPath + fullPath.Substring(2);
|
Debug.WriteLine($"修改后的字符串: {fullPath}");
|
}
|
}
|
|
// 获取不带文件名的目录路径
|
string directoryPath = Path.GetDirectoryName(fullPath);
|
strProcessName = Path.GetFileNameWithoutExtension(fullPath);
|
// 修正真实路径,模板匹配工具其路径为一个文件夹,而不是一个文件
|
fullPath = directoryPath + "\\" + strProcessName + "\\" + strProcessName + ".json";
|
|
if (!File.Exists(fullPath))
|
{
|
Debug.WriteLine("文件不存在创建空文件");
|
ModelID = new HModel(fullPath, ModelType.各向异形模板, strProcessName);
|
Save(directoryPath);
|
ModelID.Save(fullPath, ModelID.Type);
|
return true;
|
}
|
|
string strJson = string.Empty;
|
using (StreamReader streamReader = new StreamReader(fullPath, Encoding.UTF8))
|
{
|
strJson = streamReader.ReadToEnd();
|
streamReader.Close();
|
}
|
Params = JsonConvert.DeserializeObject<ProcessParams>(strJson);
|
if (Params == null)
|
return false;
|
|
// 反序列化后修复数据
|
Params.FixDeserializedData();
|
strProcessName = Path.GetFileNameWithoutExtension(fullPath);
|
|
if (!Enum.TryParse(Params.Inputs["ModelType"].ToString(), out ModelType modelType))
|
return false;
|
|
if (!ModelID.Load(fullPath, modelType))
|
return false;
|
|
return true;
|
}
|
catch { return false; }
|
}
|
|
/// <summary>
|
/// 保存算法
|
/// </summary>
|
/// <param name="filePath">不带.json</param>
|
/// <returns></returns>
|
public override bool Save(string filePath)
|
{
|
try
|
{
|
// 修正真实路径,模板匹配工具其路径为一个文件夹,而不是一个文件
|
filePath += ("\\" + strProcessName);
|
Params.Inputs.Add("ModelType", ModelID.Type.ToString());
|
if (!base.Save(filePath)
|
|| !ModelID.Save(filePath + "\\" + strProcessName + ".json", ModelID.Type))
|
return false;
|
|
return true;
|
}
|
catch { return false; }
|
}
|
}
|
|
public class HModel
|
{
|
public HModel(string modelName = "") { ModelName = modelName; }
|
|
public HModel(string modelFullPath, ModelType modelType, string modelName)
|
{
|
ModelFullPath = modelFullPath;
|
ModelName = modelName;
|
Type = modelType;
|
switch (modelType)
|
{
|
case ModelType.局部变形模板:
|
Load(ModelFullPath, modelType);
|
break;
|
case ModelType.各向异形模板:
|
default:
|
Load(ModelFullPath, modelType);
|
break;
|
}
|
}
|
|
/// <summary>
|
/// 模板路径
|
/// </summary>
|
public string ModelFullPath = "C:\\MyVisionModel\\ModelName.temp";
|
|
/// <summary>
|
/// 模板名称
|
/// </summary>
|
public string ModelName
|
{
|
get { return Path.GetFileNameWithoutExtension(ModelFullPath); }
|
set
|
{
|
// 获取文件的扩展名(包括点)
|
string fileExtension = Path.GetExtension(ModelFullPath);
|
|
// 获取文件所在的文件夹路径
|
string directoryPath = Path.GetDirectoryName(ModelFullPath);
|
|
ModelFullPath = directoryPath + "\\" + value + fileExtension;
|
}
|
}
|
|
/// <summary>
|
/// Halcon模板句柄
|
/// </summary>
|
public HTuple hvModel;
|
|
/// <summary>
|
/// 模板图片
|
/// </summary>
|
public HObject hoImage;
|
|
public HTuple Width
|
{
|
get
|
{
|
if (hoImage == null)
|
return (HTuple)0;
|
|
HOperatorSet.GetImageSize(hoImage, out HTuple ho_ModelWidth, out HTuple ho_ModelHeight);
|
return ho_ModelWidth;
|
}
|
}
|
|
public HTuple Height
|
{
|
get
|
{
|
if (hoImage == null)
|
return (HTuple)0;
|
|
HOperatorSet.GetImageSize(hoImage, out HTuple ho_ModelWidth, out HTuple ho_ModelHeight);
|
return ho_ModelHeight;
|
}
|
}
|
|
/// <summary>
|
/// Halcon模板类型
|
/// </summary>
|
public ModelType Type = ModelType.各向异形模板;
|
|
/// <summary>
|
/// 加载模板(带.json)
|
/// </summary>
|
/// <param name="fullPath">完整路径带.json</param>
|
/// <returns></returns>
|
public bool Load(string fullPath, ModelType modelType)
|
{
|
try
|
{
|
if (string.IsNullOrEmpty(fullPath))
|
return false;
|
|
string filePath = Path.GetDirectoryName(fullPath);
|
ModelName = Path.GetFileNameWithoutExtension(fullPath);
|
ModelFullPath = filePath + "\\" + ModelName;
|
ModelFullPath += ".model";
|
Type = modelType;
|
switch (modelType)
|
{
|
case ModelType.局部变形模板:
|
ModelFullPath += ".dfm";
|
if (File.Exists(ModelFullPath))
|
HOperatorSet.ReadDeformableModel(ModelFullPath, out hvModel);
|
break;
|
case ModelType.各向异形模板:
|
default:
|
if (File.Exists(ModelFullPath))
|
HOperatorSet.ReadShapeModel(ModelFullPath, out hvModel);
|
break;
|
}
|
|
string ImageFileName = Path.GetFileNameWithoutExtension(fullPath);
|
string ImageFullPath = filePath + "\\" + ImageFileName + ".bmp";
|
if (File.Exists(ImageFullPath))
|
HOperatorSet.ReadImage(out hoImage, ImageFullPath);
|
return true;
|
}
|
catch { Type = ModelType.各向异形模板; return false; }
|
}
|
|
/// <summary>
|
/// 保存模板(路径带.model)
|
/// </summary>
|
/// <param name="fullPath">带.model</param>
|
/// <returns></returns>
|
public bool Save(string fullPath)
|
{
|
try
|
{
|
if (string.IsNullOrEmpty(fullPath))
|
return false;
|
|
string filePath = Path.GetDirectoryName(fullPath);
|
//判断文件夹是否存在
|
if (!Directory.Exists(filePath))
|
{
|
try
|
{
|
Directory.CreateDirectory(filePath);
|
}
|
catch (Exception)
|
{ }
|
}
|
|
ModelName = Path.GetFileNameWithoutExtension(fullPath);
|
// 使用 Path.GetExtension 提取扩展名
|
switch (Type)
|
{
|
case ModelType.局部变形模板:
|
HOperatorSet.WriteDeformableModel(hvModel, fullPath);
|
break;
|
case ModelType.各向异形模板:
|
default:
|
HOperatorSet.WriteShapeModel(hvModel, fullPath);
|
break;
|
}
|
|
string ImageFileName = Path.GetFileNameWithoutExtension(fullPath);
|
string ImageFullPath = filePath + "\\" + ImageFileName + ".bmp";
|
HOperatorSet.WriteImage(hoImage, "bmp", 0, ImageFullPath);
|
return true;
|
}
|
catch { return false; }
|
}
|
|
/// <summary>
|
/// 保存模板(路径带.json)
|
/// </summary>
|
/// <param name="fullPath">带.json</param>
|
/// <returns></returns>
|
public bool Save(string fullPath, ModelType modelType)
|
{
|
try
|
{
|
if (string.IsNullOrEmpty(fullPath))
|
return false;
|
|
string filePath = Path.GetDirectoryName(fullPath);
|
//判断文件夹是否存在
|
if (!Directory.Exists(filePath))
|
{
|
try
|
{
|
Directory.CreateDirectory(filePath);
|
}
|
catch (Exception)
|
{ }
|
}
|
|
ModelName = Path.GetFileNameWithoutExtension(fullPath);
|
ModelFullPath = filePath + "\\" + ModelName + ".model";
|
Type = modelType;
|
switch (modelType)
|
{
|
case ModelType.局部变形模板:
|
HOperatorSet.WriteDeformableModel(hvModel, ModelFullPath);
|
break;
|
case ModelType.各向异形模板:
|
default:
|
HOperatorSet.WriteShapeModel(hvModel, ModelFullPath);
|
break;
|
}
|
|
string ImageFileName = Path.GetFileNameWithoutExtension(fullPath);
|
string ImageFullPath = filePath + "\\" + ImageFileName + ".bmp";
|
HOperatorSet.WriteImage(hoImage, "bmp", 0, ImageFullPath);
|
return true;
|
}
|
catch { return false; }
|
}
|
}
|
}
|