123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637 |
- /*
- * ==============================================================================
- *
- * Filename: PMAlign
- * Description:
- *
- * Version: 1.0
- * Created: 2021/3/30 14:07:10
- *
- * Author: liu.wenjie
- *
- * ==============================================================================
- */
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using CommonMethods;
- using HalconDotNet;
- using ToolBase;
- using static DataStruct.DataStructClass;
- using System.Windows.Forms;
- using Logger;
- using System.Diagnostics;
- using System.IO;
- using ViewROI;
- using DataStruct;
- namespace PMAlignTool
- {
- [Serializable]
- public class PMAlign : IToolBase
- {
- /// <summary>
- /// 绑定job名称
- /// </summary>
- public string bingdingJobName { get; set; }
- /// <summary>
- /// 工具名称
- /// </summary>
- public string toolName { get; set; } = string.Empty;
- /// <summary>
- /// 输入姿态
- /// </summary>
- public PosXYU inputPose = new PosXYU();
- /// <summary>
- /// 制作模板时的输入位姿
- /// </summary>
- public PosXYU templatePose = new PosXYU();
- /// <summary>
- /// 是否显示匹配到的模板
- /// </summary>
- internal bool showTemplate { get; set; } = true;
- /// <summary>
- /// 是否显示中心十字架
- /// </summary>
- internal bool showCross { get; set; } = true;
- /// <summary>
- /// 是否显示特征
- /// </summary>
- internal bool showFeature { get; set; } = true;
- /// <summary>
- /// 显示结果序号
- /// </summary>
- internal bool showIndex { get; set; } = true;
- /// <summary>
- /// 是否显示搜索区域
- /// </summary>
- internal bool showSearchRegion { get; set; } = true;
- /// <summary>
- /// 模板句柄
- /// </summary>
- internal HTuple modelID = -1;
- /// <summary>
- /// 行列间隔像素数
- /// </summary>
- internal int spanPixelNum { get; set; } = 100;
- /// <summary>
- /// 排序模式
- /// </summary>
- // internal SortMode sortMode = SortMode.从上至下且从左至右;
- /// <summary>
- /// 模板区域
- /// </summary>
- internal HObject templateRegion;
- /// <summary>
- /// 在进行模板创建及匹配时进行的图像预处理
- /// </summary>
- public ImagePreProcess imageProcess { get; set; } = new ImagePreProcess();
- /// <summary>
- /// 搜索区域图像
- /// </summary>
- internal HObject reducedImage;
- /// <summary>
- /// 最小匹配分数
- /// </summary>
- internal double minScore { get; set; } = 0.5;
- /// <summary>
- /// 匹配个数
- /// </summary>
- internal int matchNum { get; set; } = 1;
- /// <summary>
- /// 起始角度
- /// </summary>
- internal int startAngle { get; set; } = -30;
- /// <summary>
- /// 角度范围
- /// </summary>
- internal int angleRange { get; set; } = 360;
- /// <summary>
- /// 角度步长
- /// </summary>
- internal int angleStep { get; set; } = 1;
- /// <summary>
- /// 对比度
- /// </summary>
- internal int contrast { get; set; } = 30;
- /// <summary>
- /// 超时处理
- /// </summary>
- internal int timeOut { get; set; } = 500;
- /// <summary>
- /// 训练时所使用的模板图像,不点击获取图像时,不进行更新
- /// </summary>
- [NonSerialized]
- public HObject oldTrainImage;
- public bool isCreateModel { get; set; }
- internal string pmaModelName { get; set; } = Guid.NewGuid().ToString();
- /// <summary>
- /// 剪出的模板图像
- /// </summary>
- [NonSerialized]
- public HObject modelPartImage = new HObject();
- /// <summary>
- /// 模板位置和实际位置的姿态差异
- /// </summary>
- internal HTuple posHomMat2D = new HTuple();
- public override void DispMainWindow(HWindowTool_Smart dispHWindow)
- {
- if (showFeature)
- {
- ShowTemplate(dispHWindow, false);
- }
- }
- /// <summary>
- /// 极性
- /// </summary>
- internal string polarity { get; set; } = "use_polarity";
- /// <summary>
- /// 工具锁
- /// </summary>
- private object obj { get; set; } = new object();
- /// <summary>
- /// 模板匹配结果
- /// </summary>
- public List<MatchResult> L_resultList { get; set; } = new List<MatchResult>() { };
- /// <summary>
- /// 匹配模式
- /// </summary>
- public MatchMode matchMode { get; set; } = MatchMode.BasedShape;
- /// <summary>
- /// 缩放最小值
- /// </summary>
- public HTuple minScale { get; internal set; } = 0.9;
- /// <summary>
- /// 缩放最大值
- /// </summary>
- public HTuple maxScale { get; internal set; } = 1.1;
- public bool isAutoConstants { get; set; }
- public string modelFilePath { get; set; }
- public RegionType searchRegionType { get; set; }
- /// <summary>
- /// 文件存储路径
- /// </summary>
- public string trainImgPath, trainShmPath, trainModelPath, dataDirectory;
- [NonSerialized]
- public HObject SearchRegion;
- public void InitTool()
- {
- trainImgPath = ConfigData.ConfigPath + $"\\{bingdingJobName}\\{toolName}_{pmaModelName}_TrainImage.bmp";
- trainShmPath = ConfigData.ConfigPath + $"\\{bingdingJobName}\\{toolName}_{pmaModelName}.Shm";
- trainModelPath = ConfigData.ConfigPath + $"\\{bingdingJobName}\\{toolName}_{pmaModelName}_ModelImage.bmp";
- dataDirectory = ConfigData.ConfigPath + $"\\{bingdingJobName}\\";
- }
- public override void Run(SoftwareRunState softwareState)
- {
- Stopwatch sw = new Stopwatch();
- sw.Restart();
- softwareRunState = softwareState;
- if (inputImage == null)
- {
- toolRunStatu = ToolRunStatu.Lack_Of_Input_Image;
- runMessage = "工具输入图像为空";
- FormPMAlignTool.Instance.SetToolStatus(runMessage, toolRunStatu);
- return;
- }
- try
- {
- if (softwareRunState == SoftwareRunState.Debug)
- {
- DispImage();
- }
- if (inputPose != null)
- {
- HTuple Row = inputPose.X - templatePose.X;
- HTuple Col = inputPose.Y - templatePose.Y;
- HTuple angle = inputPose.U - templatePose.U;
- HTuple _homMat2D;
- HOperatorSet.HomMat2dIdentity(out _homMat2D);
- HOperatorSet.HomMat2dRotate(_homMat2D, (HTuple)(angle), (HTuple)templatePose.X, (HTuple)templatePose.Y, out _homMat2D);
- HOperatorSet.HomMat2dTranslate(_homMat2D, (HTuple)(Row), (HTuple)(Col), out _homMat2D);
- //对预期线的找模板区域做放射变换
- }
- HObject findModelImg = ProcessImage(inputImage);
- int ret = FindModelTemplate(findModelImg);
- UpdateResultDataGridview();
- ToolRunStatu myState = ret == 0 ? ToolRunStatu.Succeed : ToolRunStatu.Model_UnFound;
- toolRunStatu = myState;
- string retMsg = ret == 0 ? $"{toolName}工具运行成功,已找到匹配项!" : $"{toolName}未找到匹配项";
- runMessage = retMsg;
- sw.Stop();
- runTime = $"运行时间: {sw.ElapsedMilliseconds} ms";
- FormPMAlignTool.Instance.SetToolStatus(retMsg, myState);
- }
- catch (Exception ex)
- {
- FormPMAlignTool.Instance.SetToolStatus($"{toolName}工具运行异常,异常原因: {ex}", ToolRunStatu.Tool_Run_Error);
- }
- finally
- {
-
- }
- }
- public void UpdateResultDataGridview()
- {
- FormPMAlignTool.Instance.dgv_matchResult.Rows.Clear();
- //FormPMAlignTool.Instance.dgv_matchResult.Columns.Clear();
- //FormPMAlignTool.Instance.dgv_matchResult.Columns.Add("num", "序号");
- //FormPMAlignTool.Instance.dgv_matchResult.Columns.Add("Socre", "分值");
- //FormPMAlignTool.Instance.dgv_matchResult.Columns.Add("Row", "行");
- //FormPMAlignTool.Instance.dgv_matchResult.Columns.Add("Col", "列");
- //FormPMAlignTool.Instance.dgv_matchResult.Columns.Add("Angle", "角度");
- int count = 0;
- foreach (var item in L_resultList)
- {
- FormPMAlignTool.Instance.dgv_matchResult.Rows.Add(++count, item.Socre, item.Row, item.Col, item.Angle);
- }
- }
- public void UpdateParamsFromUI()
- {
- minScore = FormPMAlignTool.Instance.nud_minScore.Value;
- startAngle = Convert.ToInt16(FormPMAlignTool.Instance.nud_angleStart.Value);
- angleRange = Convert.ToInt16(FormPMAlignTool.Instance.nud_angleRange.Value);
- angleStep = Convert.ToInt16(FormPMAlignTool.Instance.nud_angleStep.Value);
- polarity = FormPMAlignTool.Instance.cbx_polarity.TextStr;
- isAutoConstants = FormPMAlignTool.Instance.ckb_autoContrast.Checked;
- minScale = FormPMAlignTool.Instance.nud_ScaleStart.Value;
- maxScale = FormPMAlignTool.Instance.nud_ScaleRange.Value;
- timeOut = Convert.ToInt16(FormPMAlignTool.Instance.nud_Timeout.Value);
- contrast = Convert.ToInt16(FormPMAlignTool.Instance.tkb_contrast.Value);
- }
- public override void DispImage()
- {
- FormPMAlignTool.Instance.myHwindow.DispHWindow.ClearWindow();
- if (inputImage != null)
- {
- FormPMAlignTool.Instance.myHwindow.DispHWindow.DispObj(inputImage);
- }
- }
- private void CreateModelRegion()
- {
- HOperatorSet.GenEmptyObj(out templateRegion);
- foreach (var item in FormPMAlignTool.Instance.templateModelListAdd)
- {
- HObject selectObj = item.GetDrawingObjectIconic();
- HOperatorSet.Union2(selectObj, templateRegion, out templateRegion);
- }
- foreach (var item in FormPMAlignTool.Instance.templateModelListSub)
- {
- HObject selectObj = item.GetDrawingObjectIconic();
- HOperatorSet.Difference(templateRegion, selectObj, out templateRegion);
- }
- }
- public void SetParamsFromUI()
- {
- minScore = FormPMAlignTool.Instance.nud_minScore.Value;
- startAngle = Convert.ToInt16(FormPMAlignTool.Instance.nud_angleStart.Value);
- angleRange = Convert.ToInt16(FormPMAlignTool.Instance.nud_angleRange.Value);
- angleStep = Convert.ToInt16(FormPMAlignTool.Instance.nud_angleStep.Value);
- polarity = FormPMAlignTool.Instance.cbx_polarity.TextStr;
- isAutoConstants = FormPMAlignTool.Instance.ckb_autoContrast.Checked;
- minScale = FormPMAlignTool.Instance.nud_ScaleStart.Value;
- maxScale = FormPMAlignTool.Instance.nud_ScaleRange.Value;
- }
- public int CreateModelTemplate(bool setInputModelRegion, HObject inputModelRegion)
- {
- HObject template;
- oldTrainImage = inputImage;
- // 判断是否从外部输入模板
- if(setInputModelRegion)
- {
- templateRegion = inputModelRegion;
- }
- else
- {
- if (FormPMAlignTool.Instance.templateModelListAdd.Count == 0)
- {
- LoggerClass.WriteLog($"{toolName}未划定模板建立区域", MsgLevel.Exception);
- isCreateModel = false;
- return -1;
- }
- CreateModelRegion();
- }
- HObject createModelImg;
- HOperatorSet.GenEmptyObj(out createModelImg);
- createModelImg = ProcessImage(inputImage);
- HOperatorSet.ReduceDomain(createModelImg, templateRegion, out template);
- HOperatorSet.CropDomain(template, out modelPartImage);
- //SetParamsFromUI();
- try
- {
- HTuple rows, cols, angles, scores, scale;
- if (matchMode == MatchMode.BasedShape)
- {
- HOperatorSet.CreateShapeModel(template,
- "auto",
- 0,
- 360,
- "auto",
- "auto",
- polarity,
- isAutoConstants ? (HTuple)"auto" : (HTuple)contrast,
- "auto",
- out modelID);
- HOperatorSet.FindShapeModel(createModelImg,
- (HTuple)modelID,
- ((HTuple)startAngle).TupleRad(),
- ((HTuple)angleRange - startAngle).TupleRad(),
- (HTuple)minScore,
- (HTuple)matchNum,
- (HTuple)0.5,
- (HTuple)"least_squares",
- (HTuple)0,
- (HTuple)0.9,
- out rows,
- out cols,
- out angles,
- out scores);
- }
- else
- {
- HOperatorSet.CreateNccModel(template,
- "auto",
- ((HTuple)startAngle).TupleRad(),
- ((HTuple)angleRange).TupleRad(),
- "auto",
- "use_polarity",
- out modelID);
- HOperatorSet.FindNccModel(createModelImg,
- (HTuple)modelID,
- ((HTuple)startAngle).TupleRad(),
- ((HTuple)angleRange - startAngle).TupleRad(),
- (HTuple)minScore,
- (HTuple)matchNum,
- (HTuple)0.5,
- (HTuple)"true",
- (HTuple)0,
- out rows,
- out cols,
- out angles,
- out scores);
- }
- isCreateModel = true;
- // 模板句柄信息
- Directory.CreateDirectory(dataDirectory);
- HOperatorSet.WriteShapeModel(modelID, trainShmPath);
- HOperatorSet.WriteImage(inputImage, "bmp", 0, trainImgPath);
- HOperatorSet.WriteImage(modelPartImage, "bmp", 0, trainModelPath);
- if (scores != null && scores.Type != HTupleType.EMPTY)
- {
- templatePose = new PosXYU { X = rows[0].D, Y = cols[0].D , U = angles[0].D };
- }
- }
- catch (Exception ex)
- {
- Logger.LoggerClass.WriteLog($"{toolName}创建模板时出现异常", ex);
- isCreateModel = false;
- return -1;
- }
- finally
- {
- // FormPMAlignTool.Instance.templateModelListAdd.Clear();
- // FormPMAlignTool.Instance.templateModelListSub.Clear();
- }
- return 0;
- }
- public int FindModelTemplate(HObject findModelImage)
- {
- if (!File.Exists(trainShmPath))
- {
- LoggerClass.WriteLog($"{toolName}未创建或加载模板", MsgLevel.Exception);
- return -1;
- }
- HOperatorSet.ReadShapeModel(trainShmPath, out modelID);
- HObject image;
- if (searchRegionType == RegionType.AllImage)
- {
- image = findModelImage;
- }
- else
- {
- HOperatorSet.ReduceDomain(inputImage, SearchRegion, out reducedImage);
- image = reducedImage;
- }
- HTuple rows, cols, angles, scores;
- L_resultList.Clear();
- try
- {
- image = ProcessImage(image);
- if (matchMode == MatchMode.BasedShape)
- {
- HTuple temp;
- HOperatorSet.FindShapeModel(image,
- (HTuple)modelID,
- ((HTuple)startAngle).TupleRad(),
- ((HTuple)angleRange - startAngle).TupleRad(),
- (HTuple)minScore,
- (HTuple)matchNum,
- (HTuple)0.5,
- (HTuple)"least_squares",
- (HTuple)0,
- (HTuple)0.7,
- out rows,
- out cols,
- out angles,
- out scores);
- /*
- HOperatorSet.FindScaledShapeModel(image,
- (HTuple)modelID,
- ((HTuple)startAngle).TupleRad(),
- ((HTuple)angleRange - startAngle).TupleRad(),
- minScale,
- maxScale,
- (HTuple)minScore,
- (HTuple)matchNum,
- (HTuple)0.5,
- (HTuple)"least_squares",
- (HTuple)0,
- (HTuple)0.9,
- out rows,
- out cols,
- out angles,
- out temp,
- out scores);
- */
- }
- else
- {
- HOperatorSet.FindNccModel(image,
- (HTuple)modelID,
- ((HTuple)startAngle).TupleRad(),
- ((HTuple)angleRange - startAngle).TupleRad(),
- (HTuple)minScore,
- (HTuple)matchNum,
- (HTuple)0.5,
- (HTuple)"true",
- (HTuple)0,
- out rows,
- out cols,
- out angles,
- out scores);
- }
-
- if (rows.TupleLength() > 0)
- {
- for (int i = 0; i < rows.TupleLength(); i++)
- {
- MatchResult matchResult = new MatchResult();
- matchResult.Row = Math.Round((double)rows[i], 3);
- matchResult.Col = Math.Round((double)cols[i], 3);
- matchResult.Angle = Math.Round((double)angles[i], 3);
- matchResult.Socre = Math.Round((double)scores[i], 3);
- L_resultList.Add(matchResult);
- }
- MatchResult temp;
- // 将匹配结果按分值由大到小排序
- for (int i = 0; i < L_resultList.Count - 1; i++)
- {
- for (int j = i + 1; j < L_resultList.Count; j++)
- {
- if (L_resultList[i].Socre < L_resultList[j].Socre)
- {
- temp = L_resultList[i];
- L_resultList[i] = L_resultList[j];
- L_resultList[j] = temp;
- }
- }
- }
- HOperatorSet.VectorAngleToRigid(templatePose.X, templatePose.Y, templatePose.U, L_resultList[0].Row, L_resultList[0].Col, L_resultList[0].Angle, out posHomMat2D);
- }
- if (softwareRunState == SoftwareRunState.Debug)
- {
- FormPMAlignTool.Instance.myHwindow.DispHWindow.ClearWindow();
- FormPMAlignTool.Instance.myHwindow.DispImage(inputImage);
- }
- if (L_resultList.Count > 0)
- {
- toolRunStatu = ToolRunStatu.Succeed;
- if (softwareRunState == SoftwareRunState.Debug)
- {
- ShowTemplate(FormPMAlignTool.Instance.myHwindow);
- }
- return 0;
- }
- }
- catch (Exception ex)
- {
- LoggerClass.WriteLog($"{toolName}寻找模板时出现异常!", ex);
- toolRunStatu = ToolRunStatu.Not_Succeed;
- }
- return -1;
- }
- public HObject contour;
- /// <summary>
- /// 显示模板
- /// </summary>
- internal void ShowTemplate(HWindowTool_Smart dispHWindow, bool clearImg = false)
- {
- try
- {
- if (modelID == null)
- {
- return;
- }
- if(clearImg)
- {
- dispHWindow.DispHWindow.ClearWindow();
- dispHWindow.DispImage(inputImage);
- }
- if(L_resultList.Count > 0)
- {
- foreach (var item in L_resultList)
- {
- HTuple homMat2D;
- HOperatorSet.GetShapeModelContours(out contour, modelID, new HTuple(1));
- HOperatorSet.VectorAngleToRigid(0, 0, 0, item.Row, item.Col, item.Angle,out homMat2D);
- HOperatorSet.AffineTransContourXld(contour, out contour, homMat2D);
- dispHWindow.DispHWindow.SetColor("green");
- dispHWindow.DispHWindow.DispObj(contour);
- }
- }
-
- }
- catch (Exception ex)
- {
- Logger.LoggerClass.WriteLog($"{toolName}显示模板时出现错误", ex);
- }
- }
- private HObject ProcessImage(HObject inputImg)
- {
- if (inputImage == null) return inputImage;
- if (imageProcess.erosionValue1.isEnable)
- {
- HOperatorSet.GrayErosionShape(inputImg, out inputImg, imageProcess.erosionValue1.algValue, imageProcess.erosionValue1.algValue, imageProcess.erosionValue1.algName);
- }
- if (imageProcess.dilationValue.isEnable)
- {
- HOperatorSet.GrayDilationShape(inputImg, out inputImg, imageProcess.erosionValue1.algValue, imageProcess.erosionValue1.algValue, imageProcess.dilationValue.algName);
- }
- if (imageProcess.erosionValue2.isEnable)
- {
- HOperatorSet.GrayErosionShape(inputImg, out inputImg, imageProcess.erosionValue1.algValue, imageProcess.erosionValue1.algValue, imageProcess.erosionValue2.algName);
- }
- return inputImg;
- }
-
- }
- [Serializable]
- public class ImagePreProcess
- {
- public ProcessAlg erosionValue1 { get; set; } = new ProcessAlg();
- public ProcessAlg dilationValue { get; set; } = new ProcessAlg();
- public ProcessAlg erosionValue2 { get; set; } = new ProcessAlg();
- }
- [Serializable]
- public class ProcessAlg
- {
- public double algValue { get; set; } = 0;
- public bool isEnable { get; set; } = false;
- public string algName { get; set; } = "rectangle";
- }
- [Serializable]
- public enum MatchMode
- {
- BasedShape,
- BasedGray,
- }
- [Serializable]
- public enum RegionType
- {
- AllImage,
- Rectangle1,
- Rectangle2,
- Circle,
- Ellipse,
- MultPoint,
- Ring,
- Any,
- }
- /// <summary>
- /// 模板匹配结果
- /// </summary>
- [Serializable]
- public struct MatchResult
- {
- internal double Row;
- internal double Col;
- internal double Angle;
- internal double Socre;
- }
- }
|