Halcon hWindowControl 鼠标缩放平移区域模板匹配绘制

如题所示标题,想同时表达两个意思:1:缩放平移绘制区域,2:创建模板匹配区域并保存。被一个技术问题卡住折腾了近大半天时间+熬夜2个小时,经过不懈努力,反复验证各参数意义,找到了问题的原因,终于攻克难题。分享给需要的朋友。效果如下:

思路如下:

首先鼠标滚轮缩放,按压鼠标左键平移的鼠标事件组合:MouseDown,MouseUp,MouseMove,MouseWheelEvent,

具体为:

void AddEvent()
        {
            hWindowControl2.HMouseWheel += HWindowControl1_HMouseWheel;
            hWindowControl2.HMouseMove += HWindowControl1_HMouseMove;
            hWindowControl2.HMouseDown += HWindowControl1_HMouseDown;
            hWindowControl2.HMouseUp += HWindowControl1_HMouseUp;
            hWindowControl2.MouseLeave += HWindowControl1_MouseLeave;
        }


MouseDown记录鼠标点击的起始位置:

 bool mousePressed = false;
        Point startPoint = Point.Empty;
 
        private void HWindowControl1_HMouseDown(object sender, HMouseEventArgs e)
        {
            mousePressed = true;
            startPoint = new Point((int)e.X, (int)e.Y);
            this.hWindowControl1.Cursor = Cursors.SizeAll;
        }
MouseMove 平移:注意关键之处,每次移动后的步进位置,需要重新给startPoint赋值,此处调试一下代码就知道如何写了。

另外一点是每次平移后把最新的平移旋转矩阵 out 参数出来,供下次作为新参数传递进去重新计算;

 private void HWindowControl1_HMouseMove(object sender, HMouseEventArgs e)
        {
 
            if (hMatrix == null || !mousePressed) return;
 
            HTuple hv_Matrix = null;
            double x = e.X - startPoint.X;
            double y = e.Y - startPoint.Y;
            ImageHandle.MoveImage(h_Image, out h_ScaledImage, hWindow, hMatrix, out hv_Matrix, y, x);
            startPoint = new Point((int)e.X, (int)e.Y);
            hMatrix = hv_Matrix;
        }

鼠标离开控件区域:防止bug发生; 

private void HWindowControl1_MouseLeave(object sender, EventArgs e)
        {
            mousePressed = false;
            startPoint = Point.Empty;
            this.hWindowControl1.Cursor = Cursors.Default;
        }


MoseUp结束移动:

 private void HWindowControl1_HMouseUp(object sender, HMouseEventArgs e)
        {
            mousePressed = false;
            startPoint = Point.Empty;
            this.hWindowControl1.Cursor = Cursors.Default;
        }

鼠标滚轮事件: 

double _scaleValue = 1;
        HTuple hMatrix;
        //HTuple hScaleMatrix;
        private void HWindowControl1_HMouseWheel(object sender, HMouseEventArgs e)
        {
            if (e.Delta == 0) return;
            //获取鼠标在缩放之前的目标上的位置
            //Point targetZoomFocus1 = e.GetPosition(this.hWindowControl1);
 
            double d = e.Delta / Math.Abs(e.Delta);
            if (_scaleValue < 0.5 && d < 0) return;
            if (_scaleValue > 5 && d > 0) return;
 
            double targetScaleValue = 0;
            _scaleValue += d * 0.2;
            HTuple hv_Matrix = null;
            if (d > 0)
            {
                targetScaleValue = 1 + 0.2;
            }
            else
            {
                targetScaleValue = 1 - 0.2;
            }
            ImageHandle.ScaleImage(h_Image, out h_ScaledImage, hWindow, hMatrix, out hv_Matrix, targetScaleValue, e.X, e.Y);
            hMatrix = hv_Matrix;
        }

 技术卡壳的地方在于:模板区域的选定后保存绘制结果

 绘制区域:这个没有什么可说的,用Halcon导出的C#代码就可以实现:

 public static void DrawRegion(HObject ho_Image, HWindow hWindow, out HTuple row1, out HTuple col1, out HTuple row2, out HTuple col2)
        {
            HObject ho_ROI_0;
            HOperatorSet.GenEmptyObj(out ho_ROI_0);
            HOperatorSet.SetColor(hWindow, "green");
            HOperatorSet.DrawRectangle1(hWindow, out row1, out col1, out row2, out col2);
            HOperatorSet.GenRectangle1(out ho_ROI_0, row1, col1, row2, col2);
            HOperatorSet.DispObj(ho_ROI_0, hWindow);
            ho_ROI_0.Dispose();
        }

关键问题来了:在平移缩放后的图像上绘制的区域Region所得出的row1,column1,row2,column2 是基于Halcon的标准坐标系,而缩放使用的仿射变换,坐标系不同了。

使用hom_mat2d_translate_local未果:换个思路,把基于Haclon的坐标Region 逆向变换,缩放平移回去就可以了。这个思路也是碰壁后得到的,思路对了,看实现。说来容易,可实际碰壁不少,首先就是使用错误导致怀疑Halcon当前版本是否有bug.(最后看来是对算子理解不充分)

例如开始的代码是这样写的:

 //把图片变回去 hom_mat2d_to_affine_par(HomMat2DTranslate, Sx, Sy, Phi, Theta, Tx, Ty)
            //HTuple hv_Sx = null, hv_Sy = null;
            //HTuple hv_Phi = null, hv_Theta = null, hv_Tx = null, hv_Ty = null;
            //HOperatorSet.HomMat2dToAffinePar(hMatrix, out hv_Sx, out hv_Sy,out hv_Phi, out hv_Theta, out hv_Tx, out hv_Ty);
            //HOperatorSet.VectorAngleToRigid(1/ hv_Sx, 1/ hv_Sy, hv_Phi, hv_Ty, hv_Tx, hv_Phi, out hv_HomMat2D);
            //HOperatorSet.AffineTransImage(ho_TemplateImage, out ho_ImageAffineTrans, hv_HomMat2D, "bicubic", "false");

另外犯了一个错,就是把二维矩阵变换的:平移和缩放的叠加写错:

 HOperatorSet.VectorAngleToRigid()等错误运用;

  HOperatorSet.HomMat2dRotate() 试图先得到一个平移矩形在利用这个算子添加一个缩放矩阵,结果出错。

而是应该先得到平移矩阵:

  HOperatorSet.VectorAngleToRigid(0, 0, 0, -hv_Tx, -hv_Ty, 0, out hv_HomMat2D);

再得到旋转矩阵:

HOperatorSet.HomMat2dScale(hv_HomMat2DIdentity, 1 / hv_Sx, 1 / hv_Sy, 0, 0, out hv_HomMat2D_Region);

最后把2者合并:

   HOperatorSet.HomMat2dCompose(hv_HomMat2D_Region, hv_HomMat2D, out hv_targetMatrix); //多谢这个算子

另外一个关键算子:

HOperatorSet.HomMat2dToAffinePar(hMatrix, out hv_Sx, out hv_Sy, out hv_Phi, out hv_Theta, out hv_Tx, out hv_Ty);

它可以把Matix分解得到M11,M12,缩放和平移的矢量值;

保存绘制区域模板的完整代码:

  public static void SaveModel(HObject ho_Image, HWindow hWindow, HTuple hMatrix, HTuple row1, HTuple col1, HTuple row2, HTuple col2, HTuple modelPath)
        {
 
            // Local iconic variables 
 
            HObject ho_ROI_0, ho_TemplateImage, ho_ROI_1;
            HTuple hv_ModelID = null;
            HTuple hv_HomMat2D = null;
            HOperatorSet.GenEmptyObj(out ho_ROI_0);
            HOperatorSet.GenEmptyObj(out ho_ROI_1);
            HOperatorSet.GenEmptyObj(out ho_TemplateImage);
            HTuple hv_targetMatrix = null;
            HTuple hv_HomMat2D_Region = null;
            ho_TemplateImage.Dispose();
            ho_ROI_0.Dispose();
 
            HOperatorSet.GenRectangle1(out ho_ROI_0, row1, col1, row2, col2);
 
            HTuple hv_Sx = null, hv_Sy = null;
            HTuple hv_Phi = null, hv_Theta = null, hv_Tx = null, hv_Ty = null;
            HOperatorSet.HomMat2dToAffinePar(hMatrix, out hv_Sx, out hv_Sy, out hv_Phi, out hv_Theta, out hv_Tx, out hv_Ty);
            HTuple hv_HomMat2DIdentity = null;
            HOperatorSet.HomMat2dIdentity(out hv_HomMat2DIdentity);
            HOperatorSet.VectorAngleToRigid(0, 0, 0, -hv_Tx, -hv_Ty, 0, out hv_HomMat2D);
            //把图片变回去
            HOperatorSet.HomMat2dScale(hv_HomMat2DIdentity, 1 / hv_Sx, 1 / hv_Sy, 0, 0, out hv_HomMat2D_Region);
            HOperatorSet.HomMat2dCompose(hv_HomMat2D_Region, hv_HomMat2D, out hv_targetMatrix);
            HOperatorSet.AffineTransRegion(ho_ROI_0, out ho_ROI_1, hv_targetMatrix, "nearest_neighbor");
            HOperatorSet.ReduceDomain(ho_Image, ho_ROI_1, out ho_TemplateImage);
            HOperatorSet.ClearWindow(hWindow);
            HOperatorSet.DispObj(ho_TemplateImage, hWindow);
         
            HOperatorSet.CreateShapeModel(ho_TemplateImage, 5, (new HTuple(0)).TupleRad()
                , (new HTuple(360)).TupleRad(), (new HTuple(0.1406)).TupleRad(), (new HTuple("point_reduction_high")).TupleConcat(
                "no_pregeneration"), "use_polarity", ((new HTuple(48)).TupleConcat(60)).TupleConcat(
                9), 3, out hv_ModelID);
 
            HOperatorSet.WriteShapeModel(hv_ModelID, modelPath);
            ho_Image.Dispose();
 
            //ho_ROI_0.Dispose();
            //ho_TemplateImage.Dispose();
 
        }

本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:
  • 评论列表:
  •  xiao卢
     发布于 2022-01-08 10:30:13  回复该评论
  • 大佬们,ImageHandle.MoveImage,这个是什么

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年4月    »
1234567
891011121314
15161718192021
22232425262728
2930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864