Halcon是MVTec公司开发的一款强大的机器视觉软件,它提供了多种模板匹配的方法来解决在图像中定位和识别已知图案的问题。以下是Halcon中几种主要的模板匹配方法:
-
基于灰度值的模板匹配:
- 灰度值相关的模板匹配通常包括Sum of Absolute Differences (SAD)和Sum of Squared Differences (SSD)等方法,通过计算模板图像与目标图像相应位置像素间的灰度差绝对值之和或平方和来评估相似度。
-
基于形状的模板匹配:
- 形状匹配(如shape_model算子)允许模板即使在大小、旋转或轻微形变的情况下也能被识别出来。这种方法对物体的几何结构进行描述,并且能够在一定程度上容忍变形和变化。
-
基于组件的模板匹配:
- 组件匹配侧重于图像中的特定特征或者组件来进行匹配,比如图像中有多个独立的部分需要同时出现在目标图像中才能确定匹配成功。
-
基于描述符的模板匹配:
- 虽然Halcon的核心功能可能不直接提供现代计算机视觉中常见的基于特征描述符(如SIFT, SURF, ORB等)的模板匹配,但其可以通过自定义算子实现类似的匹配方式,比如基于关键点和局部描述符的匹配。
-
Deformable模板匹配:
- 可变形模板匹配允许模板在一定范围内发生非刚性变形,适用于那些在实际应用中可能出现较大形变的目标对象。
使用Halcon进行模板匹配的基本步骤包括:
- 读取模板图像并定义感兴趣区域(ROI)。
- 加载待匹配的图像。
- 根据需求选择合适的匹配算子进行匹配操作。
- 设置匹配参数,例如搜索范围、匹配精度等。
- 执行匹配算法并获取匹配结果,如最佳匹配位置、相似度得分等信息。
以上就是关于Halcon模板匹配技术的概述及其一些基本类型,具体应用时还需要根据实际情况调整参数和选择最合适的匹配策略。
本文主要使用基于形状的模板匹配(create_shape_model)
算子介绍:
- create_shape_model
在Halcon中,create_shape_model
函数用于创建一个基于形状模型(Shape Model)的对象。这个函数利用给定的ObjectModel对象和一系列参数来生成一个能够在不同尺度、旋转角度下进行鲁棒匹配的模型。
函数原型:
create_shape_model(
ObjectModel : Image, NumLevels : int, AngleStart : int,
AngleExtent : int, AngleStep : string, ScaleMin : double,
ScaleMax : double, ScaleStep : double, Optimization : string,
Metric : string, Contrast : double, MinContrast : double,
ModelID : int) : Status
参数解释:
-
ObjectModel
:输入的对象模型,通常是一个包含了目标物体轮廓或关键点信息的区域序列。 -
Image
:用于创建形状模型的基础图像,可以用来计算背景统计特性等信息。 -
NumLevels
:金字塔层数,决定了模型创建时的空间分辨率层次。 -
AngleStart
,AngleExtent
,AngleStep
:定义了模型在角度上的搜索范围和步长,单位是度数。 -
ScaleMin
,ScaleMax
,ScaleStep
:确定了模型在尺度上的搜索范围以及每级尺度之间的变化步长。 -
Optimization
:优化策略,如’auto’,让Halcon自动选择合适的优化算法。 -
Metric
:匹配时使用的距离度量标准。 -
Contrast
:对比度阈值,用于控制模型生成过程中的边缘强度要求。 -
MinContrast
:最小对比度阈值,低于此阈值的边缘将被忽略。 -
ModelID
:输出参数,返回创建后的形状模型的句柄,后续可以使用此句柄进行匹配操作。
该函数执行后会返回一个状态值(Status),指示函数调用是否成功。通过创建的形状模型,可以在其他图像中寻找与模板相似的目标,即使这些目标存在尺度变化、旋转或轻微形变的情况。
- find_scaled_shape_model
在Halcon机器视觉软件中,find_scaled_shape_model
函数用于在图像中查找已创建的形状模型(Shape Model),并且允许目标物体在尺度上有一定的变化。这是一个强大的工具,尤其适用于检测那些由于距离、角度或物理尺寸变化导致大小有所不同的目标对象。
使用find_scaled_shape_model
的基本步骤如下:
find_scaled_shape_model(
Image : Template : ShapeModelID : StartRow, StartColumn :
Rows, Columns : AngleStart, AngleEnd : ScaleMin, ScaleMax :
AdaptivThreshold, NumMatches : Row, Column, Phi, Scale :
Score : Model : ) : Status
-
Image
:输入的灰度或二值图像,在此图像中搜索与形状模型匹配的对象。 -
Template
:在创建形状模型时使用的模板图像,这里可以省略,因为已经通过ShapeModelID
引用了模型。 -
ShapeModelID
:之前通过create_shape_model
函数创建并保存的形状模型句柄。 -
StartRow
,StartColumn
:搜索区域的起始行和列坐标。 -
Rows
,Columns
:搜索区域的行数和列数,定义了搜索范围。 -
AngleStart
,AngleEnd
:搜索的角度范围,单位通常是弧度。 -
ScaleMin
,ScaleMax
:允许的目标最小和最大缩放比例。 -
AdaptivThreshold
:适应性阈值参数,用于控制匹配过程中的阈值选择。 -
NumMatches
:期望找到的最大匹配数量,返回多个可能的匹配结果。 -
Row
,Column
,Phi
,Scale
:输出参数,分别表示匹配到的目标的位置(行、列)、旋转角度以及缩放比例。 -
Score
:每个匹配项的评分,反映匹配的质量。 -
Model
:可选输出参数,用于存储匹配过程中生成的临时模型数据。 -
Status
:返回状态信息,指示操作是否成功完成以及其他相关信息。
通过调用find_scaled_shape_model
函数,你可以找到图像中所有符合指定形状模型,并且在给定尺度范围内变化的目标实例,并获取它们的位置、旋转角度、缩放比例以及匹配得分等信息。
halcon源文件代码
********halcon源文件代码
read_image (Image, 'fabrik')
*获取图片尺寸
get_image_size (Image, Width, Height)
dev_close_window ()
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
*显示图片
dev_display (Image)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_set_line_width (2)
*圈出ROI
create_drawing_object_rectangle2 (50,50, 0, 60, 50, DrawID)
attach_drawing_object_to_window (WindowHandle, DrawID)
stop ()
get_drawing_object_params (DrawID, 'phi', Angle)
get_drawing_object_params (DrawID, 'row', row)
get_drawing_object_params (DrawID, 'column', column)
get_drawing_object_params (DrawID, 'length1', length1)
get_drawing_object_params (DrawID, 'length2', length2)
*释放模型
clear_drawing_object (DrawID)
gen_rectangle2 (Rectangle, row, column, Angle, length1, length2)
stop ()
*显示图片
dev_display (Image)
create_drawing_object_circle (100, 100, 80, DrawID1)
attach_drawing_object_to_window (WindowHandle, DrawID)
stop ()
get_drawing_object_params (DrawID1, 'row', row)
get_drawing_object_params (DrawID1, 'column', column)
get_drawing_object_params (DrawID1, 'radius', radius)
*释放模型
clear_drawing_object (DrawID1)
gen_circle (Circle, row, column, radius)
stop ()
*显示图片
dev_display (Image)
create_drawing_object_ellipse (200, 200, 0, 100, 60, DrawID2)
attach_drawing_object_to_window (WindowHandle, DrawID2)
stop ()
get_drawing_object_params (DrawID2, 'row', row)
get_drawing_object_params (DrawID2, 'column', column)
get_drawing_object_params (DrawID2, 'phi', phi)
get_drawing_object_params (DrawID2, 'radius1', radius1)
get_drawing_object_params (DrawID2, 'radius2', radius2)
*释放模型
clear_drawing_object (DrawID2)
gen_ellipse (Ellipse, row, column, phi, radius1, radius2)
reduce_domain (Image, Rectangle, ImageReduced)
threshold (ImageReduced, Region, 128, 255)
connection (Region, ConnectedRegions)
fill_up (ConnectedRegions, RegionFillUp)
*显示图片
dev_display (Image)
*创建模板
create_shape_model (ImageReduced, 'auto', -0.39, 0.79, 'auto', 'auto', 'use_polarity', 'auto', 'auto', ModelID)
*获取模板ROI区域中心
area_center (Rectangle, Area, Row, Column)
get_shape_model_contours (ModelContours, ModelID, 1)
write_shape_model (ModelID, './matchModel.shm')
**读取需要匹配的图像
read_image (Image2, 'fabrik')
*读取模板
read_shape_model ('./matchModel.shm', ModelID)
find_scaled_shape_model (Image2, ModelID, 0, rad(180), 0.9, 1.1, 0.5, 1, 0.5, 'least_squares', 0, 0.9, RowScaled, ColumnScaled, Angle, Scale, Score)
vector_angle_to_rigid (0, 0, 0, row, column, 0, HomMat2D1)
affine_trans_contour_xld (ModelContours, ContoursAffineTrans1, HomMat2D1)
*下面是为了显示出查找到的模型,做仿射变换把轮廓变换到相应图像上的位置,应为轮廓始终是在原点上的,但查找到的参数只有其中心点坐标,角度,缩放因子等参数
*通过仿射变换把原轮廓变换到相对应的位置上
for I := 0 to |Score| - 1 by 1
hom_mat2d_identity (HomMat2DIdentity)
hom_mat2d_translate (HomMat2DIdentity, RowScaled[I], ColumnScaled[I], HomMat2DTranslate)
hom_mat2d_rotate (HomMat2DTranslate, Angle[I], RowScaled[I], ColumnScaled[I], HomMat2DRotate)
hom_mat2d_scale (HomMat2DRotate, Scale[I], Scale[I], RowScaled[I], ColumnScaled[I], HomMat2DScale)
affine_trans_contour_xld (ModelContours, ContoursAffineTrans1, HomMat2DScale)
dev_display (ContoursAffineTrans1)
endfor
MainWindow.xaml
<Window
x:Class="myHalcon1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:HalconDotNet="clr-namespace:HalconDotNet;assembly=halcondotnet"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:myHalcon1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="800"
Height="450"
mc:Ignorable="d">
<Window.Resources>
<Style TargetType="Button">
<Setter Property="Margin" Value="10,10,10,0" />
<Setter Property="Padding" Value="10" />
</Style>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<HalconDotNet:HSmartWindowControlWPF Name="Hsmart" />
<Border
Name="bdROI"
Width="160"
Height="60"
Margin="0,5,5,0"
Padding="3"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Background="LightPink"
CornerRadius="10"
Opacity="0.8">
<StackPanel VerticalAlignment="Center" Orientation="Vertical">
<StackPanel Margin="5" Orientation="Horizontal">
<TextBlock
FontSize="14"
Foreground="White"
Text="完成绘制:" />
<TextBlock
Name="tbROIName"
FontSize="14"
FontWeight="Bold" />
</StackPanel>
<StackPanel
Margin="0"
HorizontalAlignment="Center"
Orientation="Horizontal">
<Button
x:Name="bdRoIDone"
Width="60"
Height="25"
Margin="5"
Padding="0"
Click="bdRoIDone_Click"
Content="确定"
FontSize="10" />
<Button
x:Name="bdROICancle"
Width="60"
Height="25"
Margin="5"
Padding="0"
Click="bdROICancle_Click"
Content="取消"
FontSize="10" />
</StackPanel>
</StackPanel>
</Border>
<StackPanel Grid.Column="1">
<GroupBox Margin="10" Header="绘图形">
<StackPanel>
<Button
Name="rectangle"
Click="btn_rectangle_Click"
Content="画矩形" />
<Button
Name="circle"
Click="btn_circle_Click"
Content="画圆形" />
<Button
Name="ellipse"
Click="btn_ellipse_Click"
Content="画椭圆形" />
<Button
Name="clear"
Click="btn_clear_Click"
Content="清除画板" />
</StackPanel>
</GroupBox>
<GroupBox Margin="10" Header="模板匹配">
<StackPanel>
<Button
Name="btn_loadImg"
Click="btn_loadImg_Click"
Content="加载图片" />
<Button
Name="createMb"
Click="btn_createMb_Click"
Content="创建模板" />
<Button
Name="matchMb"
Click="btn_matchMb_Click"
Content="匹配模板" />
</StackPanel>
</GroupBox>
</StackPanel>
</Grid>
</Window>
MainWindow.xaml.cs
using HalconDotNet;
using Microsoft.Win32;
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
namespace myHalcon1
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
bool BtnDrawDone;
bool IsDrawROI;
public MainWindow()
{
InitializeComponent();
bdROI.Visibility = Visibility.Collapsed;
}
#region halcon方法
public void set_display_font(HTuple hv_WindowHandle, HTuple hv_Size, HTuple hv_Font,
HTuple hv_Bold, HTuple hv_Slant)
{
// Local iconic variables
// Local control variables
HTuple hv_OS = null, hv_Fonts = new HTuple();
HTuple hv_Style = null, hv_Exception = new HTuple(), hv_AvailableFonts = null;
HTuple hv_Fdx = null, hv_Indices = new HTuple();
HTuple hv_Font_COPY_INP_TMP = hv_Font.Clone();
HTuple hv_Size_COPY_INP_TMP = hv_Size.Clone();
// Initialize local and output iconic variables
//This procedure sets the text font of the current window with
//the specified attributes.
//
//Input parameters:
//WindowHandle: The graphics window for which the font will be set
//Size: The font size. If Size=-1, the default of 16 is used.
//Bold: If set to 'true', a bold font is used
//Slant: If set to 'true', a slanted font is used
//
HOperatorSet.GetSystem("operating_system", out hv_OS);
// dev_get_preferences(...); only in hdevelop
// dev_set_preferences(...); only in hdevelop
if ((int)((new HTuple(hv_Size_COPY_INP_TMP.TupleEqual(new HTuple()))).TupleOr(
new HTuple(hv_Size_COPY_INP_TMP.TupleEqual(-1)))) != 0)
{
hv_Size_COPY_INP_TMP = 16;
}
if ((int)(new HTuple(((hv_OS.TupleSubstr(0, 2))).TupleEqual("Win"))) != 0)
{
//Restore previous behaviour
hv_Size_COPY_INP_TMP = ((1.13677 * hv_Size_COPY_INP_TMP)).TupleInt();
}
else
{
hv_Size_COPY_INP_TMP = hv_Size_COPY_INP_TMP.TupleInt();
}
if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("Courier"))) != 0)
{
hv_Fonts = new HTuple();
hv_Fonts[0] = "Courier";
hv_Fonts[1] = "Courier 10 Pitch";
hv_Fonts[2] = "Courier New";
hv_Fonts[3] = "CourierNew";
hv_Fonts[4] = "Liberation Mono";
}
else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("mono"))) != 0)
{
hv_Fonts = new HTuple();
hv_Fonts[0] = "Consolas";
hv_Fonts[1] = "Menlo";
hv_Fonts[2] = "Courier";
hv_Fonts[3] = "Courier 10 Pitch";
hv_Fonts[4] = "FreeMono";
hv_Fonts[5] = "Liberation Mono";
}
else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("sans"))) != 0)
{
hv_Fonts = new HTuple();
hv_Fonts[0] = "Luxi Sans";
hv_Fonts[1] = "DejaVu Sans";
hv_Fonts[2] = "FreeSans";
hv_Fonts[3] = "Arial";
hv_Fonts[4] = "Liberation Sans";
}
else if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual("serif"))) != 0)
{
hv_Fonts = new HTuple();
hv_Fonts[0] = "Times New Roman";
hv_Fonts[1] = "Luxi Serif";
hv_Fonts[2] = "DejaVu Serif";
hv_Fonts[3] = "FreeSerif";
hv_Fonts[4] = "Utopia";
hv_Fonts[5] = "Liberation Serif";
}
else
{
hv_Fonts = hv_Font_COPY_INP_TMP.Clone();
}
hv_Style = "";
if ((int)(new HTuple(hv_Bold.TupleEqual("true"))) != 0)
{
hv_Style = hv_Style + "Bold";
}
else if ((int)(new HTuple(hv_Bold.TupleNotEqual("false"))) != 0)
{
hv_Exception = "Wrong value of control parameter Bold";
throw new HalconException(hv_Exception);
}
if ((int)(new HTuple(hv_Slant.TupleEqual("true"))) != 0)
{
hv_Style = hv_Style + "Italic";
}
else if ((int)(new HTuple(hv_Slant.TupleNotEqual("false"))) != 0)
{
hv_Exception = "Wrong value of control parameter Slant";
throw new HalconException(hv_Exception);
}
if ((int)(new HTuple(hv_Style.TupleEqual(""))) != 0)
{
hv_Style = "Normal";
}
HOperatorSet.QueryFont(hv_WindowHandle, out hv_AvailableFonts);
hv_Font_COPY_INP_TMP = "";
for (hv_Fdx = 0; (int)hv_Fdx <= (int)((new HTuple(hv_Fonts.TupleLength())) - 1); hv_Fdx = (int)hv_Fdx + 1)
{
hv_Indices = hv_AvailableFonts.TupleFind(hv_Fonts.TupleSelect(hv_Fdx));
if ((int)(new HTuple((new HTuple(hv_Indices.TupleLength())).TupleGreater(0))) != 0)
{
if ((int)(new HTuple(((hv_Indices.TupleSelect(0))).TupleGreaterEqual(0))) != 0)
{
hv_Font_COPY_INP_TMP = hv_Fonts.TupleSelect(hv_Fdx);
break;
}
}
}
if ((int)(new HTuple(hv_Font_COPY_INP_TMP.TupleEqual(""))) != 0)
{
throw new HalconException("Wrong value of control parameter Font");
}
hv_Font_COPY_INP_TMP = (((hv_Font_COPY_INP_TMP + "-") + hv_Style) + "-") + hv_Size_COPY_INP_TMP;
HOperatorSet.SetFont(hv_WindowHandle, hv_Font_COPY_INP_TMP);
// dev_set_preferences(...); only in hdevelop
return;
}
#endregion
HImage image;
private void btn_loadImg_Click(object sender, RoutedEventArgs e)
{
//1.创建打开图片的对话框
var imageFileDialog = new OpenFileDialog();
//2.设置对话框能够打开图片的类型
imageFileDialog.Filter = "图片|*.jpg;*.png;*.bmp";
//3.设置默认打开图片扩展名称
imageFileDialog.DefaultExt = ".png";
//4.打开判断对话框是否打开
if (imageFileDialog.ShowDialog() == true)
{
//5.获取选择的图片名称
var fileName = imageFileDialog.FileName;
//6.创建halcon图片
image = new HImage();
//7.把打开图片文件读取到HImage对象中
image.ReadImage(fileName);
//8.打开前图片清空
Hsmart.HalconWindow.ClearWindow();
//9.使用Honcal控件显示图片
Hsmart.HalconWindow.DispObj(image);
}
}
HTuple hv_DrawID;
HTuple hv_Angle;
HTuple hv_row;
HTuple hv_column;
HTuple hv_length1;
HTuple hv_length2;
HTuple hv_Row3;
HTuple hv_Col1;
HObject ho_Rectangle;
HObject ho_Cross1;
string startRow;
string startCol;
string endRow;
string endCol;
private void btn_rectangle_Click(object sender, RoutedEventArgs e)
{
bdROI.Visibility = Visibility.Visible;
HOperatorSet.GenEmptyObj(out ho_Rectangle);
HOperatorSet.GenEmptyObj(out ho_Cross1);
//圈出ROI
HOperatorSet.CreateDrawingObjectRectangle2(50, 50, 0, 60, 50, out hv_DrawID);
HOperatorSet.AttachDrawingObjectToWindow(Hsmart.HalconWindow, hv_DrawID);
Task.Run(() =>
{
BtnDrawDone = false;
while (true)
{
Thread.Sleep(50);
if (BtnDrawDone)
{
//GetRetanglePara(out ho_Rectangle);
//获取roi区域信息
HOperatorSet.GetDrawingObjectParams(hv_DrawID, "phi", out hv_Angle);
HOperatorSet.GetDrawingObjectParams(hv_DrawID, "row", out hv_row);
HOperatorSet.GetDrawingObjectParams(hv_DrawID, "column", out hv_column);
HOperatorSet.GetDrawingObjectParams(hv_DrawID, "length1", out hv_length1);
HOperatorSet.GetDrawingObjectParams(hv_DrawID, "length2", out hv_length2);
HOperatorSet.GenRectangle2(out ho_Rectangle, hv_row, hv_column, hv_Angle, hv_length1, hv_length2);
//以下代码用于显示区域四个顶点的坐标
ho_Rectangle.Dispose();
HOperatorSet.GenRectangle2ContourXld(out ho_Rectangle, hv_row, hv_column, hv_Angle,
hv_length1, hv_length2);
HOperatorSet.GetContourXld(ho_Rectangle, out hv_Row3, out hv_Col1);
ho_Cross1.Dispose();
HOperatorSet.GenCrossContourXld(out ho_Cross1, hv_Row3, hv_Col1, 60, 0);
string startRow = hv_Row3.TupleSelect(1).D.ToString("0.00");
string startCol = hv_Col1.TupleSelect(1).D.ToString("0.00");
string endRow = hv_Row3.TupleSelect(3).D.ToString("0.00");
string endCol = hv_Col1.TupleSelect(3).D.ToString("0.00");
//显示四个顶点的十字星
//HS.HalconWindow.DispObj(ho_Cross1);
//生成模板矩形
ho_Rectangle.Dispose();
HOperatorSet.GenRectangle2(out ho_Rectangle, hv_row, hv_column, hv_Angle, hv_length1, hv_length2);
//同步四个坐标
HOperatorSet.DetachDrawingObjectFromWindow(Hsmart.HalconWindow, hv_DrawID);
IsDrawROI = true;
Console.WriteLine("startRow:" + startRow + ",startCol:" + startCol + ",endRow:" + endRow + ",endCol:" + endCol);
break;
}
}
});
}
HTuple hv_radius;
HObject ho_Circle;
private void btn_circle_Click(object sender, RoutedEventArgs e)
{
HOperatorSet.GenEmptyObj(out ho_Circle);
HOperatorSet.CreateDrawingObjectCircle(100, 100, 80, out hv_DrawID);
HOperatorSet.AttachDrawingObjectToWindow(Hsmart.HalconWindow, hv_DrawID);
// stop(...); only in hdevelop
HOperatorSet.GetDrawingObjectParams(hv_DrawID, "row", out hv_row);
HOperatorSet.GetDrawingObjectParams(hv_DrawID, "column", out hv_column);
HOperatorSet.GetDrawingObjectParams(hv_DrawID, "radius", out hv_radius);
//释放模型
//HOperatorSet.ClearDrawingObject(hv_DrawID1);
//ho_Circle.Dispose();
//HOperatorSet.GenCircle(out ho_Circle, hv_row, hv_column, hv_radius);
stop(...); only in hdevelop
显示图片
//if (HDevWindowStack.IsOpen())
//{
// HOperatorSet.DispObj(ho_Image, HDevWindowStack.GetActive());
//}
}
HTuple hv_phi;
HTuple hv_radius1;
HTuple hv_radius2;
HObject ho_Ellipse;
private void btn_ellipse_Click(object sender, RoutedEventArgs e)
{
HOperatorSet.GenEmptyObj(out ho_Ellipse);
HOperatorSet.CreateDrawingObjectEllipse(200, 200, 0, 100, 60, out hv_DrawID);
HOperatorSet.AttachDrawingObjectToWindow(Hsmart.HalconWindow, hv_DrawID);
// stop(...); only in hdevelop
HOperatorSet.GetDrawingObjectParams(hv_DrawID, "row", out hv_row);
HOperatorSet.GetDrawingObjectParams(hv_DrawID, "column", out hv_column);
HOperatorSet.GetDrawingObjectParams(hv_DrawID, "phi", out hv_phi);
HOperatorSet.GetDrawingObjectParams(hv_DrawID, "radius1", out hv_radius1);
HOperatorSet.GetDrawingObjectParams(hv_DrawID, "radius2", out hv_radius2);
释放模型
//HOperatorSet.ClearDrawingObject(hv_DrawID2);
//ho_Ellipse.Dispose();
//HOperatorSet.GenEllipse(out ho_Ellipse, hv_row, hv_column, hv_phi, hv_radius1,
// hv_radius2);
}
private void btn_clear_Click(object sender, RoutedEventArgs e)
{
HOperatorSet.DetachDrawingObjectFromWindow(Hsmart.HalconWindow, hv_DrawID);
}
private void bdRoIDone_Click(object sender, RoutedEventArgs e)
{
BtnDrawDone = true;
bdROI.Visibility = Visibility.Hidden;
}
private void bdROICancle_Click(object sender, RoutedEventArgs e)
{
if (hv_DrawID != null)
{
HOperatorSet.DetachDrawingObjectFromWindow(Hsmart.HalconWindow, hv_DrawID);
}
bdROI.Visibility = Visibility.Hidden;
}
HTuple hv_ModelID;
HTuple hv_Row1;
HTuple hv_Column1;
HTuple hv_Score;
HTuple hv_HomMat2D;
HObject ho_ModelContours;
HObject ho_ContoursAffineTrans;
HObject ho_RegionAffineTrans;
HObject imgreduced;
bool IsCreateMb;
private void btn_createMb_Click(object sender, RoutedEventArgs e)
{
try
{
HOperatorSet.ReduceDomain(image, ho_Rectangle, out imgreduced);
//创建模板
HOperatorSet.CreateShapeModel(imgreduced, "auto", -0.39, 0.79, "auto",
"auto", "use_polarity", "auto", "auto", out hv_ModelID);
//查看模板
HOperatorSet.GetShapeModelContours(out ho_ModelContours, hv_ModelID, 1);
HOperatorSet.WriteShapeModel(hv_ModelID, "./matchModel.shm");
IsCreateMb = true;
}
catch( Exception ex)
{
MessageBox.Show(ex.Message);
}
}
HTuple hv_RowScaled;
HTuple hv_ColumnScaled;
HTuple hv_Scale;
HTuple hv_HomMat2D1;
HObject ho_ContoursAffineTrans1;
private void btn_matchMb_Click(object sender, RoutedEventArgs e)
{
HOperatorSet.GenEmptyObj(out ho_ContoursAffineTrans);
HOperatorSet.GenEmptyObj(out ho_RegionAffineTrans);
HOperatorSet.GenEmptyObj(out ho_ContoursAffineTrans1);
HOperatorSet.SetColor(Hsmart.HalconWindow, "green");
HOperatorSet.SetLineWidth(Hsmart.HalconWindow, 3);
if (IsCreateMb == false)
{
MessageBox.Show("请创建模板");
return;
}
try
{
//读取模板
HOperatorSet.ReadShapeModel("./matchModel.shm", out hv_ModelID);
HOperatorSet.FindScaledShapeModel(image, hv_ModelID, 0, (new HTuple(180)).TupleRad()
, 0.9, 1.1, 0.5, 1, 0.5, "least_squares", 0, 0.9, out hv_RowScaled, out hv_ColumnScaled,
out hv_Angle, out hv_Scale, out hv_Score);
HOperatorSet.VectorAngleToRigid(0, 0, 0, hv_row, hv_column, 0, out hv_HomMat2D1);
ho_ContoursAffineTrans1.Dispose();
HOperatorSet.AffineTransContourXld(ho_ModelContours, out ho_ContoursAffineTrans1,
hv_HomMat2D1);
//下面是为了显示出查找到的模型,做仿射变换把轮廓变换到相应图像上的位置,应为轮廓始终是在原点上的,但查找到的参数只有其中心点坐标,角度,缩放因子等参数
//通过仿射变换把原轮廓变换到相对应的位置上
for (int hv_I = 0; (int)hv_I <= (int)((new HTuple(hv_Score.TupleLength())) - 1); hv_I = (int)hv_I + 1)
{
HOperatorSet.HomMat2dIdentity(out HTuple hv_HomMat2DIdentity);
HOperatorSet.HomMat2dTranslate(hv_HomMat2DIdentity, hv_RowScaled.TupleSelect(
hv_I), hv_ColumnScaled.TupleSelect(hv_I), out HTuple hv_HomMat2DTranslate);
HOperatorSet.HomMat2dRotate(hv_HomMat2DTranslate, hv_Angle.TupleSelect(hv_I),
hv_RowScaled.TupleSelect(hv_I), hv_ColumnScaled.TupleSelect(hv_I), out HTuple hv_HomMat2DRotate);
HOperatorSet.HomMat2dScale(hv_HomMat2DRotate, hv_Scale.TupleSelect(hv_I),
hv_Scale.TupleSelect(hv_I), hv_RowScaled.TupleSelect(hv_I), hv_ColumnScaled.TupleSelect(
hv_I), out HTuple hv_HomMat2DScale);
ho_ContoursAffineTrans1.Dispose();
HOperatorSet.AffineTransContourXld(ho_ModelContours, out ho_ContoursAffineTrans1,
hv_HomMat2DScale);
}
HOperatorSet.DispObj(ho_ContoursAffineTrans1, Hsmart.HalconWindow);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
创建模板
匹配模板,角度1
匹配模板,角度2
匹配模板,角度3