using HalconDotNet;
|
using MvCameraControl;
|
using LB_VisionControls;
|
using Newtonsoft.Json;
|
using Newtonsoft.Json.Serialization;
|
using OpenCvSharp;
|
using SharpCompress.Common;
|
using System;
|
using System.Collections.Generic;
|
using System.Diagnostics;
|
using System.Drawing.Imaging;
|
using System.Linq;
|
using System.Text;
|
using System.Threading.Tasks;
|
using System.Xml.Linq;
|
|
namespace LB_VisionProcesses.Alogrithms.Halcon
|
{
|
public class HCaltabTool : TAlgorithm
|
{
|
public HCaltabTool()
|
{
|
strProcessClass = "LB_VisionProcesses.Alogrithms.Halcon.HCaltabTool";
|
strProcessName = "Halcon2D_畸变矫正工具";
|
|
Params.Inputs.Add("XNum", 7);
|
Params.Inputs.Add("YNum", 7);
|
Params.Inputs.Add("MarkDist", 12.5);
|
Params.Inputs.Add("DiameterRatio", 0.5);
|
Params.Inputs.Add("Focus", 12);
|
Params.Inputs.Add("Kappa", 0);
|
Params.Inputs.Add("Sx", 2.4);
|
Params.Inputs.Add("Sy", 2.4);
|
Params.Inputs.Add("Width", 5472);
|
Params.Inputs.Add("Height", 3648);
|
}
|
|
public HCaltabTool(HCaltabTool HCaltab)
|
{
|
Record.AddXld(HCaltab.Record.RecordObject_OK.Clone());
|
Record.AddXld(HCaltab.Record.RecordObject_NG.Clone());
|
|
strProcessClass = "LB_VisionProcesses.Alogrithms.Halcon.HCaltabTool";
|
strProcessName = HCaltab.strProcessName + "(Copy)";
|
|
Params.Inputs.Add("XNum", HCaltab.HCaltabParam.XNum);
|
Params.Inputs.Add("YNum", HCaltab.HCaltabParam.YNum);
|
Params.Inputs.Add("MarkDist", HCaltab.HCaltabParam.MarkDist);
|
Params.Inputs.Add("DiameterRatio", HCaltab.HCaltabParam.DiameterRatio);
|
Params.Inputs.Add("Focus", HCaltab.HCaltabParam.Focus);
|
Params.Inputs.Add("Kappa", HCaltab.HCaltabParam.Kappa);
|
Params.Inputs.Add("Sx", HCaltab.HCaltabParam.Sx);
|
Params.Inputs.Add("Sy", HCaltab.HCaltabParam.Sy);
|
Params.Inputs.Add("Width", HCaltab.HCaltabParam.Width);
|
Params.Inputs.Add("Height", HCaltab.HCaltabParam.Height);
|
}
|
|
public override void Dispose()
|
{
|
try
|
{
|
ClearCaltbImages();
|
|
if (HCaltabMap != null)
|
HCaltabMap.Dispose();
|
|
if (Record != null)
|
Record.Dispose();
|
}
|
catch { }
|
}
|
|
/// <summary>
|
/// 结果
|
/// </summary>
|
public bool IsCaltab
|
{
|
get
|
{
|
return HCaltabMap.IsCaltab;
|
}
|
}
|
|
string _filePath = $"C:\\Name\\";
|
|
/// <summary>
|
/// 文件路径
|
/// </summary>
|
public string FilePath
|
{
|
get { return _filePath; }
|
set
|
{
|
_filePath = value;
|
HCaltabParam.FilePath = value;
|
}
|
}
|
|
/// <summary>
|
/// 标定参数文件
|
/// </summary>
|
public HCaltabParam HCaltabParam = new HCaltabParam();
|
|
HCaltabMap HCaltabMap = new HCaltabMap();
|
|
public HObject Image
|
{
|
get
|
{
|
if (HCaltabMap.GetCaltbImages().Count > 0)
|
return HCaltabMap.GetCaltbImages()[0];
|
else
|
return null;
|
}
|
}
|
|
#region 矫正结果
|
public bool GetCaltbImage(HObject OriImage, out HObject CaltbImage)
|
{
|
CaltbImage = OriImage;
|
|
try
|
{
|
return HCaltabMap.GetCaltbImage(OriImage, out CaltbImage);
|
}
|
catch { return false; }
|
}
|
|
public bool GetCaltbPoint(HPoint OriPoint, out HPoint CaltbPoint)
|
{
|
CaltbPoint = new HPoint(OriPoint);
|
|
try
|
{
|
return HCaltabMap.GetCaltbPoint(OriPoint, out CaltbPoint);
|
}
|
catch { return false; }
|
}
|
#endregion
|
|
public override bool Run()
|
{
|
#region 初始化变量
|
DateTime StartTime = DateTime.Now;
|
|
InitRunParams();
|
HOperatorSet.GenEmptyObj(out HObject EmptyObj);
|
OutputImage = EmptyObj;
|
#endregion
|
|
try
|
{
|
if (InputImage == null)
|
{
|
Msg = "输入图片为空";
|
Result = false;
|
return Result;
|
}
|
|
//if (InputImage is Bitmap)
|
//{
|
// try
|
// {
|
// using (HImage hImage = new HImage())
|
// {
|
// Rectangle rect = new Rectangle(0, 0, ((Bitmap)InputImage).Width, ((Bitmap)InputImage).Height);
|
// BitmapData srcBmpData = ((Bitmap)InputImage).LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppRgb);
|
// hImage.GenImageInterleaved(srcBmpData.Scan0, "rgbx", ((Bitmap)InputImage).Width, ((Bitmap)InputImage).Height, 0, "byte", ((Bitmap)InputImage).Width, ((Bitmap)InputImage).Height, 0, 0, -1, 0);
|
// ((Bitmap)InputImage).UnlockBits(srcBmpData);
|
// //((Bitmap)InputImage).Dispose();
|
// InputImage = null;
|
// InputImage = hImage.Clone();
|
// }
|
// }
|
// catch (Exception ex)
|
// {
|
// }
|
//}
|
if (!(InputImage is HObject))
|
{
|
Msg = "输入图片格式不为HObject";
|
Result = false;
|
return Result;
|
}
|
|
#region 裁剪区域
|
object DomainImage = null;
|
if (!ReduceDomainImage(InputImage, ref DomainImage))
|
{
|
Msg = "裁剪区域失败";
|
Result = false;
|
return Result;
|
}
|
#endregion
|
|
#region 算子逻辑
|
Record = new ObjectRecord();
|
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 Result;
|
}
|
}
|
catch
|
{
|
Msg = "输入图片不为灰度图且转换失败";
|
Result = false;
|
return Result;
|
}
|
}
|
|
if (HCaltabMap == null || !HCaltabMap.IsCaltab)
|
{
|
Msg = "未进行标定,无法矫正畸变";
|
Result = false;
|
return Result;
|
}
|
|
if (!GetCaltbImage(hoDomainImage, out hoDomainImage))
|
{
|
Msg = "矫正畸变失败";
|
Result = false;
|
return Result;
|
}
|
|
#endregion
|
|
#region 生成OutputImage给后续处理
|
try
|
{
|
OutputImage = hoDomainImage;
|
}
|
catch (Exception ex)
|
{
|
Msg = "生成OutputImage失败,原因是:" + ex.ToString();
|
Result = false;
|
return Result;
|
}
|
#endregion
|
|
Msg = "运行成功";
|
Result = true;
|
return Result;
|
}
|
catch (Exception ex)
|
{
|
Msg = "运行失败,原因是:" + ex.ToString().TrimEnd();
|
OutputImage = null;
|
Result = false;
|
return Result;
|
}
|
finally
|
{
|
RunTime = (DateTime.Now - StartTime).TotalMilliseconds;
|
}
|
}
|
|
public bool AddCaltbImage(HObject image)
|
{
|
try
|
{
|
if (image == null || !image.IsInitialized())
|
return false;
|
|
HCaltabMap.AddCaltbImage(image.CopyObj(1, -1));
|
|
return true;
|
}
|
catch { return false; }
|
}
|
|
public bool LoadCaltbImages()
|
{
|
try
|
{
|
ClearCaltbImages();
|
|
return HCaltabMap.LoadCaltbImages(FilePath);
|
}
|
catch { return false; }
|
}
|
|
public bool SaveCaltbImages()
|
{
|
//判断文件夹是否存在,防呆输入为文件名称
|
if (!Directory.Exists(FilePath))
|
{
|
try
|
{
|
Directory.CreateDirectory(FilePath);
|
}
|
catch { }
|
}
|
|
return true;
|
}
|
|
public void ClearCaltbImages()
|
{
|
HCaltabMap.ClearCaltbImages();
|
}
|
|
public bool CheckCaltbImage(List<HObject> lst_Images = null, int Width = 0, int Height = 0)
|
{
|
if (lst_Images == null)
|
lst_Images = HCaltabMap.GetCaltbImages();
|
|
if (Width == 0 || Height == 0)
|
{
|
Width = HCaltabParam.Width;
|
Height = HCaltabParam.Height;
|
}
|
|
foreach (var imge in lst_Images)
|
{
|
if (imge == null || !imge.IsInitialized())
|
return false;
|
|
HOperatorSet.GetImageSize(imge, out HTuple hv_Width, out HTuple hv_Height);
|
if (hv_Width.Length == 0 || hv_Height.Length == 0)
|
{
|
Msg = "标定图片长度为空";
|
return false;
|
}
|
|
if (hv_Width.I != Width || hv_Height.I != Height)
|
{
|
Msg = $"标定图片长度{hv_Width.I}*{hv_Height.I}与相机参数{Width}*{Height}不符";
|
return false;
|
}
|
}
|
return true;
|
}
|
|
public bool CreateCaltbFile(int XNum, int YNum, double MarkDist, double DiameterRatio, out string FilePath)
|
{
|
FilePath = this.FilePath;
|
try
|
{
|
BaseCalib.CreateCaltab(out _, FilePath, XNum, YNum, MarkDist, DiameterRatio);
|
return true;
|
}
|
catch { MessageBox.Show("文件名称含非法字符,创建标定文件失败"); return false; }
|
}
|
|
public bool Caltb(int XNum, int YNum, double MarkDist, double DiameterRatio, int Focus, int Kappa
|
, double Sx, double Sy, int Width, int Height)
|
{
|
try
|
{
|
List<HObject> CaltbImages_Copy = new List<HObject>();
|
foreach (var image in HCaltabMap.GetCaltbImages())
|
{
|
if (image != null && image.IsInitialized())
|
CaltbImages_Copy.Add(image.CopyObj(1, -1));
|
}
|
|
return Caltb(CaltbImages_Copy, HCaltabParam.XNum, HCaltabParam.YNum, HCaltabParam.MarkDist, HCaltabParam.DiameterRatio
|
, HCaltabParam.Focus, HCaltabParam.Kappa, HCaltabParam.Sx, HCaltabParam.Sy, HCaltabParam.Width, HCaltabParam.Height);
|
}
|
catch { return false; }
|
}
|
|
public bool Caltb(List<HObject> lst_Images)
|
{
|
try
|
{
|
return Caltb(lst_Images, HCaltabParam.XNum, HCaltabParam.YNum, HCaltabParam.MarkDist, HCaltabParam.DiameterRatio
|
, HCaltabParam.Focus, HCaltabParam.Kappa, HCaltabParam.Sx, HCaltabParam.Sy, HCaltabParam.Width, HCaltabParam.Height);
|
}
|
catch { return false; }
|
}
|
|
public bool Caltb(List<HObject> lst_Images, int XNum, int YNum, double MarkDist, double DiameterRatio
|
, double Focus, double Kappa, double Sx, double Sy, int Width, int Height)
|
{
|
try
|
{
|
if (!CheckCaltbImage(lst_Images, Width, Height))
|
return false;
|
|
BaseCalib.CreateCaltab(out string CalPlateDescr, FilePath, XNum, YNum, MarkDist, DiameterRatio);
|
|
BaseCalib.gen_cam_par_area_scan_division(Focus / 1000.0, Kappa
|
, Sx / 1000000.0, Sy / 1000000.0
|
, Width / 2.0, Height / 2.0, Width, Height, out HTuple CameraParam);
|
|
BaseCalib.CaltabCalib(CameraParam, lst_Images
|
, out HTuple hv_CameraInner, out HTuple hv_CameraPose, out HTuple hv_CameraInner_Adaptive
|
, out HObject ho_Map, out HObject Xld, out Msg, CalPlateDescr);
|
Record.Dispose();
|
|
if (hv_CameraInner == null || hv_CameraPose == null || hv_CameraInner_Adaptive == null
|
|| ho_Map == null || !ho_Map.IsInitialized())
|
return false;
|
|
Record = new ObjectRecord();
|
Record.AddXld(Xld);
|
|
HCaltabMap.Dispose();
|
HCaltabMap = new HCaltabMap(hv_CameraInner, hv_CameraInner_Adaptive, hv_CameraPose);
|
HCaltabMap.AddCaltbImages(lst_Images);
|
|
HCaltabParam = new HCaltabParam(FilePath, XNum, YNum, MarkDist, DiameterRatio, Focus, Kappa, Sx, Sy, Width, Height);
|
return HCaltabMap.Save(FilePath);
|
}
|
catch { return false; }
|
}
|
|
public override bool Load(string fullPath)
|
{
|
try
|
{
|
// 获取不带文件名的目录路径
|
string directoryPath = Path.GetDirectoryName(fullPath);
|
strProcessName = Path.GetFileNameWithoutExtension(fullPath);
|
// 修正真实路径,工具其路径为一个文件夹,而不是一个文件
|
FilePath = directoryPath + "\\" + strProcessName;
|
fullPath = FilePath + "\\" + strProcessName + ".json";
|
|
if (!File.Exists(fullPath))
|
{
|
Debug.WriteLine("文件不存在创建空文件");
|
Save(directoryPath);
|
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();
|
int XNum = ProcessParams.ConvertToInt32(Params.Inputs["XNum"]);
|
int YNum = ProcessParams.ConvertToInt32(Params.Inputs["YNum"]);
|
double MarkDist = ProcessParams.ConvertToDouble(Params.Inputs["MarkDist"]);
|
double DiameterRatio = ProcessParams.ConvertToDouble(Params.Inputs["DiameterRatio"]);
|
double Focus = ProcessParams.ConvertToDouble(Params.Inputs["Focus"]);
|
double Kappa = ProcessParams.ConvertToDouble(Params.Inputs["Kappa"]);
|
double Sx = ProcessParams.ConvertToDouble(Params.Inputs["Sx"]);
|
double Sy = ProcessParams.ConvertToDouble(Params.Inputs["Sy"]);
|
int Width = ProcessParams.ConvertToInt32(Params.Inputs["Width"]);
|
int Height = ProcessParams.ConvertToInt32(Params.Inputs["Height"]);
|
|
HCaltabParam = new HCaltabParam(FilePath, XNum, YNum, MarkDist, DiameterRatio, Focus, Kappa, Sx, Sy, Width, Height);
|
bool result = HCaltabMap.Load(FilePath);
|
if (result)
|
{
|
if (!dicHCaltabMaps.ContainsKey(strProcessName))
|
dicHCaltabMaps.TryAdd(strProcessName, HCaltabMap);
|
else if (dicHCaltabMaps.ContainsKey(strProcessName))
|
dicHCaltabMaps[strProcessName] = HCaltabMap;
|
}
|
|
return result;
|
}
|
catch { return false; }
|
}
|
|
public override bool Save(string filePath)
|
{
|
try
|
{
|
if (string.IsNullOrEmpty(filePath) || filePath.Trim() == "")
|
{
|
Debug.WriteLine("文件路径不完整");
|
return false;
|
}
|
|
// 修正真实路径,工具其路径为一个文件夹,而不是一个文件
|
filePath += ("\\" + strProcessName);
|
|
string strJson = string.Empty;
|
var settings = new JsonSerializerSettings
|
{
|
Formatting = Newtonsoft.Json.Formatting.Indented,
|
// 自定义缩进(4空格)
|
ContractResolver = new DefaultContractResolver
|
{
|
NamingStrategy = new CamelCaseNamingStrategy()
|
}
|
};
|
strJson = JsonConvert.SerializeObject(Params, settings);
|
|
//判断文件夹是否存在,防呆输入为文件名称
|
if (!Directory.Exists(filePath))
|
{
|
try
|
{
|
Directory.CreateDirectory(filePath);
|
}
|
catch (Exception)
|
{ }
|
}
|
// filePath 已经含了Name
|
File.WriteAllText(filePath + $"\\{strProcessName}.json", strJson, Encoding.UTF8);
|
|
// filePath 已经含了Name
|
FilePath = filePath;
|
|
bool result = HCaltabMap.Save(FilePath);
|
if (result)
|
{
|
if (!dicHCaltabMaps.ContainsKey(strProcessName))
|
dicHCaltabMaps.TryAdd(strProcessName, HCaltabMap);
|
else if (dicHCaltabMaps.ContainsKey(strProcessName))
|
dicHCaltabMaps[strProcessName] = HCaltabMap;
|
}
|
|
return result;
|
}
|
catch { return false; }
|
}
|
}
|
|
public class HCaltabMap : IDisposable
|
{
|
#region 标定图片
|
List<HObject> CaltbImages = new List<HObject>();
|
|
public List<HObject> GetCaltbImages()
|
{
|
List<HObject> CaltbImages_Copy = new List<HObject>();
|
foreach (var image in CaltbImages)
|
{
|
if (image != null && image.IsInitialized())
|
CaltbImages_Copy.Add(image.CopyObj(1, -1));
|
}
|
return CaltbImages_Copy;
|
}
|
|
public bool AddCaltbImages(List<HObject> images)
|
{
|
try
|
{
|
foreach (var image in images)
|
{
|
if (image != null && image.IsInitialized())
|
{
|
HTuple hv_Channels = new HTuple();
|
//判断是否为灰度图
|
using (HDevDisposeHelper dh = new HDevDisposeHelper())
|
{
|
try
|
{
|
HOperatorSet.CountChannels(image, out hv_Channels);
|
HObject GrayImage = image.CopyObj(1, -1);
|
if (hv_Channels.TupleInt() != 1)
|
HOperatorSet.Rgb1ToGray(GrayImage, out GrayImage);
|
|
//转换后再次检查是否为灰度图
|
HOperatorSet.CountChannels(GrayImage, out hv_Channels);
|
if (hv_Channels.TupleInt() == 1)
|
CaltbImages.Add(GrayImage);
|
}
|
catch { }
|
}
|
}
|
}
|
|
return true;
|
}
|
catch { return false; }
|
}
|
|
public bool AddCaltbImage(HObject image)
|
{
|
try
|
{
|
if (image != null && image.IsInitialized())
|
{
|
HTuple hv_Channels = new HTuple();
|
//判断是否为灰度图
|
using (HDevDisposeHelper dh = new HDevDisposeHelper())
|
{
|
try
|
{
|
HOperatorSet.CountChannels(image, out hv_Channels);
|
HObject GrayImage = image.CopyObj(1, -1);
|
if (hv_Channels.TupleInt() != 1)
|
HOperatorSet.Rgb1ToGray(GrayImage, out GrayImage);
|
|
//转换后再次检查是否为灰度图
|
HOperatorSet.CountChannels(GrayImage, out hv_Channels);
|
if (hv_Channels.TupleInt() == 1)
|
{
|
CaltbImages.Add(GrayImage);
|
return true;
|
}
|
}
|
catch { }
|
}
|
}
|
return false;
|
}
|
catch { return false; }
|
}
|
|
public bool LoadCaltbImages(string FilePath)
|
{
|
try
|
{
|
ClearCaltbImages();
|
|
for (int i = 0; i < 99; i++)
|
{
|
string ImagePath = FilePath + $"\\CaltbImages_{i}.bmp";
|
if (!File.Exists(ImagePath))
|
break;
|
|
HOperatorSet.ReadImage(out HObject ho_Image, ImagePath);
|
}
|
|
return true;
|
}
|
catch { return false; }
|
}
|
|
public bool SaveCaltbImages(string FilePath)
|
{
|
//判断文件夹是否存在,防呆输入为文件名称
|
if (!Directory.Exists(FilePath))
|
{
|
try
|
{
|
Directory.CreateDirectory(FilePath);
|
}
|
catch { }
|
}
|
|
try
|
{
|
for (int i = 0; i < CaltbImages.Count; i++)
|
{
|
string ImagePath = FilePath + $"\\CaltbImages_{i}.bmp";
|
var Image = CaltbImages[i];
|
if (Image != null && Image.IsInitialized())
|
{
|
HOperatorSet.CountChannels(Image, out HTuple hv_Channels);
|
|
if (hv_Channels.TupleInt() != 1)
|
HOperatorSet.Rgb1ToGray(Image, out Image);
|
|
//Halcon存图需要用斜杠
|
ImagePath.Replace("\\", "/");
|
HOperatorSet.WriteImage(Image, "bmp", 0, ImagePath);
|
}
|
}
|
}
|
catch { return false; }
|
|
return true;
|
}
|
|
public void ClearCaltbImages()
|
{
|
try
|
{
|
foreach (var image in CaltbImages)
|
{
|
if (image != null && image.IsInitialized())
|
image.Dispose();
|
}
|
CaltbImages.Clear();
|
CaltbImages = new List<HObject>();
|
}
|
catch { Debug.WriteLine($"ClearCaltbImages失败"); }
|
}
|
#endregion
|
|
public void Dispose()
|
{
|
try
|
{
|
ClearCaltbImages();
|
|
if (Map != null && Map.IsInitialized())
|
Map.Dispose();
|
}
|
catch { }
|
}
|
|
/// <summary>
|
/// 结果
|
/// </summary>
|
public bool IsCaltab
|
{
|
get
|
{
|
if (CameraInner_Adaptive == null || CameraInner_Adaptive.Length == 0
|
|| CameraInner == null || CameraInner.Length == 0
|
|| CameraPose == null || CameraPose.Length == 0)
|
return false;
|
|
if (Map == null || !Map.IsInitialized())
|
return false;
|
|
return true;
|
}
|
}
|
|
public HCaltabMap() { }
|
|
public HCaltabMap(HTuple CameraInner, HTuple CameraInner_Adaptive, HTuple CameraPose)
|
{
|
this.CameraInner = CameraInner.Clone();
|
this.CameraInner_Adaptive = CameraInner_Adaptive.Clone();
|
this.CameraPose = CameraPose.Clone();
|
HOperatorSet.GenRadialDistortionMap(out _mAp, CameraInner, CameraInner_Adaptive, "bilinear");
|
}
|
|
/// <summary>
|
/// 相机内参
|
/// </summary>
|
HTuple CameraInner = new HTuple();
|
|
/// <summary>
|
/// 相机外参
|
/// </summary>
|
HTuple CameraPose = new HTuple();
|
|
/// <summary>
|
/// 无畸变的相机内参
|
/// </summary>
|
HTuple CameraInner_Adaptive = new HTuple();
|
|
/// <summary>
|
/// 畸变变换图
|
/// </summary>
|
HObject Map
|
{
|
get
|
{
|
try
|
{
|
if (_mAp == null || !_mAp.IsInitialized())
|
HOperatorSet.GenRadialDistortionMap(out _mAp, CameraInner, CameraInner_Adaptive, "bilinear");
|
|
return _mAp;
|
}
|
catch { return null; }
|
}
|
set
|
{
|
if (_mAp != null && _mAp.IsInitialized())
|
_mAp.Dispose();
|
_mAp = value;
|
}
|
}
|
|
HObject _mAp = new HObject();
|
|
public bool GetCaltbImage(HObject OriImage, out HObject CaltbImage)
|
{
|
CaltbImage = OriImage;
|
|
try
|
{
|
if (OriImage == null || !OriImage.IsInitialized()
|
|| Map == null || !Map.IsInitialized())
|
return false;
|
|
HOperatorSet.MapImage(OriImage, Map, out CaltbImage);
|
return true;
|
}
|
catch { return false; }
|
}
|
|
public bool GetCaltbPoint(HPoint OriPoint, out HPoint CaltbPoint)
|
{
|
CaltbPoint = new HPoint(OriPoint);
|
|
try
|
{
|
if (CameraInner_Adaptive == null || CameraInner_Adaptive.Length == 0
|
|| CameraInner == null || CameraInner.Length == 0
|
|| CameraPose == null || CameraPose.Length == 0)
|
return false;
|
|
HOperatorSet.ImagePointsToWorldPlane(CameraInner_Adaptive, CameraPose
|
, OriPoint.Row, OriPoint.Column, "mm", out HTuple row, out HTuple col);
|
|
if (row.Length == 0 || col.Length == 0)
|
return false;
|
|
CaltbPoint.Row = row.D;
|
CaltbPoint.Column = col.D;
|
return true;
|
}
|
catch { return false; }
|
}
|
|
public bool Save(string FilePath)
|
{
|
try
|
{
|
string CameraInnerAdaptivePath = FilePath + "\\CameraInner_Adaptive.tup";
|
string CameraInnerPath = FilePath + "\\CameraInner.tup";
|
string CameraPosePath = FilePath + "\\CameraPose.tup";
|
//相机内参
|
HOperatorSet.WriteTuple(CameraInner_Adaptive, CameraInnerAdaptivePath);
|
HOperatorSet.WriteTuple(CameraInner, CameraInnerPath);
|
//相机外参
|
HOperatorSet.WriteTuple(CameraPose, CameraPosePath);
|
|
return SaveCaltbImages(FilePath);
|
}
|
catch { return false; }
|
}
|
|
public bool Load(string FilePath)
|
{
|
try
|
{
|
Dispose();
|
|
string CameraInnerAdaptivePath = FilePath + "\\CameraInner_Adaptive.tup";
|
string CameraInnerPath = FilePath + "\\CameraInner.tup";
|
string CameraPosePath = FilePath + "\\CameraPose.tup";
|
|
//相机内参
|
HOperatorSet.ReadTuple(CameraInnerAdaptivePath, out CameraInner_Adaptive);
|
//相机内参
|
HOperatorSet.ReadTuple(CameraInnerPath, out CameraInner);
|
//相机外参
|
HOperatorSet.ReadTuple(CameraPosePath, out CameraPose);
|
|
HOperatorSet.GenRadialDistortionMap(out _mAp, CameraInner, CameraInner_Adaptive, "bilinear");
|
|
return true;
|
}
|
catch { return false; }
|
}
|
}
|
|
/// <summary>
|
/// 畸变标定参数类
|
/// </summary>
|
[Serializable]
|
public class HCaltabParam
|
{
|
public HCaltabParam() { }
|
|
public HCaltabParam(string FilePath, int XNum = 7, int YNum = 7, double MarkDist = 12.5, double DiameterRatio = 0.5
|
, double Focus = 8.0, double Kappa = 0, double Sx = 2.6, double Sy = 2.6, int Width = 5472, int Height = 3648)
|
{
|
this.FilePath = FilePath;
|
this.XNum = XNum;
|
this.YNum = YNum;
|
this.MarkDist = MarkDist;
|
this.DiameterRatio = DiameterRatio;
|
this.Focus = Focus;
|
this.Kappa = Kappa;
|
this.Sx = Sx;
|
this.Sy = Sy;
|
this.Width = Width;
|
this.Height = Height;
|
}
|
|
/// <summary>
|
/// 文件路径
|
/// </summary>
|
public string FilePath = @"C:\\";
|
|
/// <summary>
|
/// 圆点行数
|
/// </summary>
|
public int XNum { get; set; } = 7;
|
|
/// <summary>
|
/// 圆点行数
|
/// </summary>
|
public int YNum { get; set; } = 7;
|
|
/// <summary>
|
/// 两个圆之间的距离, 单位mm
|
/// </summary>
|
public double MarkDist { get; set; } = 12.5;
|
|
/// <summary>
|
/// 比例值, Mark直径比上Mark中心距离
|
/// </summary>
|
public double DiameterRatio { get; set; } = 0.5;
|
|
/// <summary>
|
/// 用于标定的描述文件(命名规范不要修改)
|
/// </summary>
|
public string CalPlateDescr { get { return FilePath + $"\\Caltab_{XNum}_{YNum}_{MarkDist}.descr"; } }
|
|
/// <summary>
|
/// 制作标定板的PS文件(命名规范不要修改)
|
/// </summary>
|
public string CalPlatePSFile { get { return FilePath + $"\\Caltab_{XNum}_{YNum}_{MarkDist}.ps"; } }
|
|
/// <summary>
|
/// 厚度
|
/// </summary>
|
public int Thickness { get; set; } = 1;
|
|
/// <summary>
|
/// 相机类型(面扫描(除法))
|
/// </summary>
|
public string CamType { get; set; } = "area_scan_division";
|
|
/// <summary>
|
/// 镜头的焦距
|
/// </summary>
|
public double Focus { get; set; } = 12;
|
|
public double Kappa { get; set; } = 0;
|
|
/// <summary>
|
/// 单个相机像元的宽
|
/// </summary>
|
public double Sx { get; set; } = 2.4;
|
|
/// <summary>
|
/// 单个相机像元的高
|
/// </summary>
|
public double Sy { get; set; } = 2.4;
|
|
/// <summary>
|
/// 图像宽
|
/// </summary>
|
public int Width { get; set; } = 5472;
|
|
/// <summary>
|
/// 图像高
|
/// </summary>
|
public int Height { get; set; } = 3648;
|
|
/// <summary>
|
/// 标定效果, 越接近0越越好
|
/// </summary>
|
public double RMS { get; set; } = 999.9;
|
}
|
}
|