流程如下:
①、创建MFC工程(基于vs2017):
②、测试运行MFC工程:
引发一个异常,加断点运行查看问题所在
根据网上教程修改,打开方式为:“工具”->“选项”->“调试”->“符号”,选中"Microsoft符号服务器"即可。
运行加载很长一段时间,仍然没加载完。于是我想是不是因为我的项目名称是中文导致的。于是我重新创建了一个项目:
改成英文项目名称后运行成功(后面我又测试了一个中文创建的项目,报以上相同的错误,所以在此提醒一下,尽量使用英文创建项目)。
③、配置Halcon环境(在HALCON学习之旅(六))中已给出配置方法,在此,再加一种不同配置方式:
④、MFC与Halcon编程
⑤、效果展示
代码实现:
void CMFCDemo1Dlg::CreateMyWindow()
{
Hlong Farther_windowHandle;
Hlong m_Window_Origin_X = 0, m_Window_Origin_Y = 0;
//设置窗口的背景颜色
SetWindowAttr("background_color", "black");
//获取显示控件句柄
HWND m_PREVIEW_STATIC;
GetDlgItem(IDC_PREVIEW_STATIC, &m_PREVIEW_STATIC);
Farther_windowHandle = (Hlong)m_PREVIEW_STATIC;
//获取显示控件的客户区
CRect rect;
CWnd *pWnd = GetDlgItem(IDC_PREVIEW_STATIC);
pWnd->GetClientRect(&rect);
//打开一个新窗口,这个窗口用来进行图像数据,区域、图形以及文本输出
OpenWindow(m_Window_Origin_X, m_Window_Origin_Y, rect.Width(), rect.Height(), Farther_windowHandle, "visible", "", &WindowHandle);
}
void CMFCDemo1Dlg::LoadImage()
{
HObject ho_Image;
HTuple hv_Width, hv_Height;
//读取一张图像
ReadImage(&ho_Image, "luntan.png");
//获取图像大小
GetImageSize(ho_Image, &hv_Width, &hv_Height);
//设置对象显示的颜色
SetColor(WindowHandle, "yellow");
//通过改变图像的缩放来适应图像在窗口的正常显示
SetPart(WindowHandle, 0, 0, hv_Height, hv_Width);
//在窗口上显示图像
DispObj(ho_Image, WindowHandle);
//设置文本光标位置
SetTposition(WindowHandle, hv_Width / 2, hv_Height / 2);
//在文本光标位置显示HelloWorld
WriteString(WindowHandle, "HelloWorld");
}
流程如下:
①、创建C#工程(基于vs2017):
②、测试运行C#工程:
③、配置Halcon环境(此配置方式与C++/MFC配置方式不同)。首先:将… /Halcon/bin/dotnet35/ 目录下的 halcondotnet.dll 拷贝到工程Debug目录下:
其次,在工程目录下的引用选择右键,打开添加引用对话框,引用 halcondotnet.dll:
④、C#与Halcon编程
⑤、效果展示
代码实现:
public void OpenWindow()
{
long m_lWindowRow = 0, m_lWindowColumn = 0;
//获取PictureBox控件句柄
HTuple Farther_windowHandle = this.pictureBox1.Handle;
//设置显示界面属性
HOperatorSet.SetWindowAttr("background_color", "blue");
//打开窗体
HOperatorSet.OpenWindow(m_lWindowRow, m_lWindowColumn, (HTuple)this.pictureBox1.Width, (HTuple)this.pictureBox1.Height, Farther_windowHandle, "visible", "", out MainUI_Camera_WindowID);
}
public void LoadImage()
{
//读取图像
HOperatorSet.ReadImage(out RawImage, "luntan.png");
//初始化图像宽高
HTuple width = null, height = null;
//获取图像大小
HOperatorSet.GetImageSize(RawImage, out width, out height);
//设置图形窗口颜色
HOperatorSet.SetColor(MainUI_Camera_WindowID, "yellow");
//设置显示区域
HOperatorSet.SetPart(MainUI_Camera_WindowID, 0, 0, height, width);
//显示图像
HOperatorSet.DispObj(RawImage, MainUI_Camera_WindowID);
//定义光标位置
HOperatorSet.SetTposition(MainUI_Camera_WindowID, width / 2, height / 2);
//在光标位置打印文本信息
HOperatorSet.WriteString(MainUI_Camera_WindowID, "HelloWorld");
}
使用流程:
①、打开测量助手
②、输入
②、边缘
③、模糊(初步了解)
模糊测量:基于模糊逻辑。
模糊逻辑:模仿人脑的不确定性概念判断、推理思维方式,对于模型未知或不能确定的描述系统,以及强非线性、大滞后的控制对象,应用模糊集合和模糊规则进行推理,表达过渡性界限或定性知识经验,模拟人脑方式,实行模糊综合判断,推理解决常规方法难于对付的规则型模糊信息问题。
模糊阈值:选择最小模糊分数的0.1和1之间的值,最终的模糊得分是所有个体得分的几何平均值。
④、结果
⑤、插入代码
附加:若打开了两个或多个测量助手,关闭助手流程:打开要关闭的助手(Measure)->点击文件 ->退出助手
代码实现:
* Measure 02: Code generated by Measure 02
* Measure 02: Prepare measurement
*幅度阈值(T)
AmplitudeThreshold := 40
*ROI宽(R)
RoiWidthLen2 := 5
*获取 HALCON 系统参数的当前值
*'int_zooming' 确定图像处理某些步骤的精度。通过将'int_zooming'设置为'true'整数运算或使用快速浮点运算。通过将其设置为'false'将使用高精度浮点运算。
set_system ('int_zooming', 'true')
* Measure 02: Coordinates for line Measure 02 [0]
*线段测量的起始行
LineRowStart_Measure_02_0 := 167.088
*线段测量的起始列
LineColumnStart_Measure_02_0 := 61.4355
*线段测量的截止行
LineRowEnd_Measure_02_0 := 898.139
*线段测量的截止列
LineColumnEnd_Measure_02_0 := 1117.6
* Measure 02: Convert coordinates to rectangle2 type
*将坐标转换为rectangle2类型
TmpCtrl_Row := 0.5*(LineRowStart_Measure_02_0+LineRowEnd_Measure_02_0)
TmpCtrl_Column := 0.5*(LineColumnStart_Measure_02_0+LineColumnEnd_Measure_02_0)
TmpCtrl_Dr := LineRowStart_Measure_02_0-LineRowEnd_Measure_02_0
TmpCtrl_Dc := LineColumnEnd_Measure_02_0-LineColumnStart_Measure_02_0
TmpCtrl_Phi := atan2(TmpCtrl_Dr, TmpCtrl_Dc)
TmpCtrl_Len1 := 0.5*sqrt(TmpCtrl_Dr*TmpCtrl_Dr + TmpCtrl_Dc*TmpCtrl_Dc)
TmpCtrl_Len2 := RoiWidthLen2
* Measure 02: Create measure for line Measure 02 [0]
* Measure 02: Attention: This assumes all images have the same size!
*准备提取垂直与矩形的直边
*参数1 矩形中心的行坐标
*参数2 矩形中心的列坐标
*参数3 矩形的纵轴与水平线的角度(弧度)
*参数4 矩形的一半宽度
*参数5 矩形的一半高度
*参数6 后续要处理的图像宽度
*参数7 后续要处理的图像高度
*参数8 要使用的差值类型 Interpolation = 'nearest_neighbor',测量中的灰度值是由最近像素的灰度值得到的,即通过常数插值。对于Interpolation = 'bilinear',使用双线性插值;对于Interpolation = 'bicubic',使用双三次插值。
*参数9 测量对象句柄
gen_measure_rectangle2 (TmpCtrl_Row, TmpCtrl_Column, TmpCtrl_Phi, TmpCtrl_Len1, TmpCtrl_Len2, 1280, 1024, 'nearest_neighbor', MsrHandle_Measure_02_0)
* Measure 02: ***************************************************************
* Measure 02: * The code which follows is to be executed once / measurement *
* Measure 02: ***************************************************************
* Measure 02: Load image
*读取图像变量
read_image (Image, 'F:/halcon_Learning/screw_thread.png')
* Measure 02: Execute measurements
*执行测量
*提取垂直于矩形或环形弧的直边对
*参数1 输入图像
*参数2 测量对象句柄
*参数3 高斯平滑sigma
*参数4 最小边缘幅度
*参数5 确定如何将边分组为边对的灰度值转换类型
*参数6 边对的选择
*参数7 输出第一条边的中心行坐标
*参数8 输出第一条边的中心列坐标
*参数9 输出第一条边的边沿幅度(带符号)
*参数10 输出第二条边的中心行坐标
*参数11 输出第二条边的中心列坐标
*参数12 输出第二条边的边沿幅度(带符号)
*参数13 边对的边之间的距离
*参数14 连续边对之间的距离
measure_pairs (Image, MsrHandle_Measure_02_0, 1, AmplitudeThreshold, 'all', 'all', Row1_Measure_02_0, Column1_Measure_02_0, Amplitude1_Measure_02_0, Row2_Measure_02_0, Column2_Measure_02_0, Amplitude2_Measure_02_0, Width_Measure_02_0, Distance_Measure_02_0)
* Measure 02: Do something with the results
*销毁测量对象句柄
close_measure (MsrHandle_Measure_02_0)
效果展示:
*读取图像变量
read_image(Image, 'progres')
*获取图像大小
get_image_size(Image, Width, Height)
*关闭图行窗口
dev_close_window()
*创建一个新的图像窗口
dev_open_window(0, 0, Width, Height, 'black', WindowHandle)
*显示图像
dev_display(Image)
*设置输出对象显示的颜色
dev_set_color('red')
*设置区域填充方式
dev_set_draw('margin')
*获取矩形
gen_rectangle1(Rectangle, 260, 90, 360, 350)
*减少图像区域
*参数1 输入图像
*参数2 新定义区域
*参数3 缩减到新定义区域的图像
reduce_domain(Image, Rectangle, ImageReduced)
*全阈值分割
threshold(ImageReduced, Region, 0, 150)
*获取连通区域
connection(Region, ConnectedRegions)
*特征筛选
select_shape(ConnectedRegions, SelectedRegions, 'area', 'and', 0, 100)
*计算等效椭圆参数
*算子elliptic_axis计算与Regions中的输入区域具有相同方向和长宽比的椭圆的半径Ra、Rb和方向Phi。
*几个输入区域可以作为元组传递。
*Ra代表椭圆的主半径,Rb代表椭圆的次级半径。
*主轴相对于x轴的方向是以弧度表示的。
*椭圆的主轴等价于输入区域惯性矩的主轴。
*参数1 输入区域
*参数2 输出主半轴(归一化到面积)
*参数3 输出次半轴(归一化到面积)
*参数4 输出主半轴和x轴之间的角度(弧度)
elliptic_axis(SelectedRegions, Ra, Rb, Phi)
*获取区域的面积和中心坐标
area_center(SelectedRegions, Area, Row, Column)
*显示图像变量
dev_display(Image)
*设置输出对象颜色
dev_set_color('green')
*计算区域的平均值
meanRedius := sum(Ra) / |Ra|
*计算半径的方差,方差描述随机变量对数学期望的偏离程度
VarianceRadius := sum((Ra - meanRedius) * (Ra - meanRedius)) / |Ra|
附加:elliptic_axis算子的计算流程:
需先了解moments_region_2nd 算子中的个别参数。
moments_region_2nd计算regions中输入区域的几何矩 M 11 M_{11} M11、 M 20 M_{20} M20、 M 02 M_{02} M02。进一步计算输入区域的长轴和短轴,并在Ia和Ib中返回。
其中 M 20 M_{20} M20返回行相关矩, M 02 M_{02} M02返回列相关矩。矩 M 11 M_{11} M11表示区域点的行坐标和列坐标之间的协方差。
计算公式:
M i j = Σ ( r , c ) ϵ R ( r 0 − r ) i ( c 0 − c ) i M_{ij} = \Sigma_{(r,c) \epsilon R} (r_0-r)^i(c_0-c)^i Mij=Σ(r,c)ϵR(r0−r)i(c0−c)i
r 0 r_0 r0和 c 0 c_0 c0是区域R的重心坐标, r r r和 c c c遍历区域的所有像素。
对于如何计算多边形的重心,可参考该博客:https://www.jianshu.com/p/39ef232ad531
将得到的 M 20 M_{20} M20, M 02 M_{02} M02和 M 11 M_{11} M11归一化到面积,计算主半径Ra和次半径Rb以及方向phi。
计算公式:
R a = 8 ( M 20 + M 02 + ( M 20 − M 02 ) 2 + 4 M 11 2 ) 2 Ra = \frac{\sqrt{8(M_{20} + M_{02}+\sqrt{(M_{20}-M_{02})^2 + 4M_{11}^2})}}{2} Ra=28(M20+M02+(M20−M02)2+4M112)
R b = 8 ( M 20 + M 02 − ( M 20 − M 02 ) 2 + 4 M 11 2 ) 2 Rb = \frac{\sqrt{8(M_{20} + M_{02}-\sqrt{(M_{20}-M_{02})^2 + 4M_{11}^2})}}{2} Rb=28(M20+M02−(M20−M02)2+4M112)
P h i = − 0.5 ∗ a t a n 2 ( 2 M 11 , M 02 − M 20 ) Phi = -0.5 * atan2(2M_{11}, M_{02} - M_{20}) Phi=−0.5∗atan2(2M11,M02−M20)
效果展示:
*打开图像变量
read_image(Image, 'clip')
*获取图像大小
get_image_size(Image, Width, Height)
*关闭已经打开的窗口
dev_close_window()
*创建一个新的图形窗口
dev_open_window(0, 0, Width, Height, 'black', WindowHandle)
*显示图像变量
dev_display(Image)
*设置独立于操作系统的字体
*参数1 图形窗口ID
*参数2 设置字体大小 默认值为:16
*参数3 设置字体类型
*参数4 是否使用粗体 'true'是使用粗体,'false'是不使用粗体
*参数5 是否使用倾斜 'true'是使用倾斜,'false'是不使用倾斜
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
*这个过程在屏幕右下角显示“点击运行继续”
*参数1 图形窗口ID
*参数2 定义文本颜色 建议值: 'black', 'blue', 'yellow', 'red', 'green', 'cyan', 'magenta', 'forest green', 'lime green', 'coral', 'slate blue'
*参数3 如果设置为“true”,文本将被写入一个白框中;若设置为'false'则没有任何效果
disp_continue_message(WindowHandle, 'black', 'true')
*停止程序执行
*stop操作符停止HDevelop程序的连续执行。
*如果发生这种情况,PC保持在停止语句(而不是放在下一个可执行程序行),以便直接显示程序中断的原因,即使有许多注释或其他不可执行的程序行。
*该操作符相当于菜单栏中的Stop动作(F9)。可以通过Run操作(F5)轻松地继续该程序。
*可以通过在首选项对话框中设置时间参数来重新定义行为。执行不会停止,而是继续
stop()
*二值化阈值
binary_threshold(Image, Region, 'max_separability', 'dark', UsedThreshold)
*获取连通区域
connection(Region, ConnectedRegions)
*特征筛选
select_shape(ConnectedRegions, SelectedRegions, 'area', 'and', 5000, 10000)
*设置区域的填充方式
dev_set_draw('margin')
*设置输出显示对象的颜色
dev_set_colored(12)
*显示过滤后的区域
dev_display(SelectedRegions)
*获取过滤后区域的方向
*该操作符基于elliptic_axis
*参数1 带检测的区域
*参数2 返回区域的方向
orientation_region(SelectedRegions, Phi)
*获取区域的面积和中心点
area_center(SelectedRegions, Area, Row, Column)
*设置输出显示对象的线宽
dev_set_line_width(3)
*设置输出显示对象的颜色
dev_set_color('blue')
length := 80
*在窗口中显示箭头
*参数1 图形窗口ID
*参数2 开始行索引
*参数3 开始列索引
*参数4 结束行索引
*参数5 结束列索引
*参数6 箭头大小
disp_arrow(WindowHandle, Row, Column, Row - length * sin(Phi), Column + length * cos(Phi), 4)
*在窗口上显示信息
*deg(Phi)->弧度转化为角度
disp_message(WindowHandle, deg(Phi)$'3.1f' + ' °', 'image', Row, Column - 100, 'black', 'false')
效果展示:
*读取图像变量
read_image(Image, 'die_pads')
*关闭图形窗口
dev_close_window()
*获取图像大小
get_image_size (Image, Width, Height)
*创建一个新的图形变量
dev_open_window (0, 0, Width * 2, Height * 2, 'black', WindowHandle)
*显示图像变量
dev_display(Image)
*设置显示图像大小
dev_set_part(0, 0, Height - 1, Width - 1)
*使用全局阈值对图像进行快速阈值处理
*Fast_threshold从输入图像中选取灰度值g满足以下条件的像素:
*MinGray <= g <= MaxGray
*为了减少处理时间,选择分两步完成:首先,处理所有位于所选水平线上的点,这些点的距离是MinSize。
*在下一步中,所有之前选择的点的邻域(大小(2*MinSize+1) x (2*MinSize+1))被处理。
*在支持SSE2指令集的多核计算机上,threshold很可能比fast_threshold快。
*Fast_threshold可能只在那些特性不可用的情况下被优先使用,例如在嵌入式平台上
*参数1 输入图像
*参数2 分割后的区域
*参数3 (MinGray)灰度最小值
*参数4 (MaxGray)灰度最大值
*参数5 MinSize(要提取的对象最小尺寸)
fast_threshold(Image, Region, 180, 255, 20)
*获取连通区域
connection(Region, ConnectedRegions)
*特征筛选
select_shape (ConnectedRegions, SelectedRegions, ['area','anisometry'], 'and', [200,1], [1200,2])
*无条件填充过滤间隙
fill_up(SelectedRegions, RegionFillUp)
*将填充区域形状转化为凸型
*参数1 需要转化的区域
*参数2 转化后的区域
*参数3 转化类型 默认值:'convex'凸包
*建议值:'ellipse'椭圆
*'outer_circle'最小外接圆
*'inner_circle'最大内接圆
*'rectangle1'平行于坐标轴的最小的外接矩形
*'rectangle2' 最小的封闭矩形
*'inner_rectangle1'与区域内最大的平行轴矩形
*'inner_center' 输入区域骨架上到输入区域重心距离最小的点
shape_trans(RegionFillUp, RegionTrans, 'convex')
*把一个区域缩小到它的边界。
*参数1 要计算边界的区域
*参数2 产生的边界
*参数3 边界类型 默认值'inner'轮廓线在原区域内
*建议值:'inner_filled' 轮廓线位于原始区域内,输入区域内部的孔洞被抑制。由于算法优化,这个轮廓可能与用“内”得到的相应轮廓略有不同
*'outer' 轮廓是原始区域外的一个像素
boundary (RegionTrans, RegionBorder, 'inner')
*形态学膨胀
dilation_circle (RegionBorder, RegionDilation, 2.5)
*将膨胀后的区域合并为一个区域
union1 (RegionDilation, RegionUnion)
*减少图像区域
reduce_domain(Image, RegionUnion, ImageReduced)
*对图像进行边缘提取
edges_sub_pix (ImageReduced, Edges, 'sobel_fast', 0.5, 20, 40)
*对xld区域进行特征筛选(与select_shape参数类似)
select_shape_xld (Edges, SelectedContours, 'contlength', 'and', 10, 200)
*将相邻的轮廓合并为一个轮廓
*统一合并XLD 轮廓数组的所有端点靠近在一起的轮廓。
*统一轮廓由输入轮廓的轮廓点的串联组成。
*如有必要,这些输入轮廓点的顺序将被翻转,以便必须连接的轮廓的端点在结果点列表中是直接相邻的。
*重复此操作,直到不再有未连接的相邻轮廓
*参数1 输入XLD轮廓
*参数2 输出连接后的XLD轮廓
*参数3 等高线端点的最大距离
*参数4 等高线端点相对较长的等高线长度的最大距离
*参数5 描述轮廓属性处理的模式 默认值:'attr_keep' 所有属性都被复制到输出中,并且——如果一个轮廓必须被翻转以连接到另一个轮廓——它们将适应新的方向
*建议值:对于大量的输入轮廓,如果进一步计算不需要这些属性,则选择'attr_forget'值
union_adjacent_contours_xld (SelectedContours, UnionContours, 2, 1, 'attr_keep')
*将UnionContours轮廓拟合成为一个仿射矩形轮廓
*fit_rectangle2_contour_xld将矩形与contours给出的矩形XLD轮廓进行匹配,并在Row、Column(center)、Phi (orientation)以及Length1和Length2 (一半长度)中返回矩形的参数。角度Phi以弧度返回,并指定水平轴与半长为Length1的边在数学上正方向(逆时针方向)之间的角度。
*此外,在PointOrder中返回轮廓的点顺序。PointOrder = 'positive'表示等高线沿数学上的正方向(逆时针方向)穿过。
*矩形拟合所用的算法可通过算法选择:
*'regression' 标准最小二乘直线拟合
*'huber' 加权最小二乘直线拟合,在Huber方法的基础上减少了离群值的影响
*'tukey' 加权最小二乘直线拟合,其中基于Tukey方法忽略离群值
*参数1 输入轮廓
*参数2 矩形拟合算法
*参数3 用于计算的最大等高线点数(所有点数为-1) 默认值:-1
*参数4 被认为是闭合的轮廓端点之间的最大距离 默认值:0.0
*参数5 为了进行拟合,在轮廓的开始和结束处需要忽略的点的数目 默认值:0
*参数6 最大迭代次数 默认值:3
*参数7 用于消除异常值的检测因子 默认值:2.0
*参数8 返回矩形中心的行坐标
*参数9 返回矩形中心的列坐标
*参数10 返回矩形的主轴方向的角度(弧度)
*参数11 矩形的第一个半径(半长)
*参数12 矩形的第二个半径(半宽)
*参数13 返回高等线的点阶
fit_rectangle2_contour_xld (UnionContours, 'tukey', -1, 0, 0, 3, 2, Row, Column, Phi, Length1, Length2, PointOrder)
*获取一个矩形的XLD轮廓
*gen_rectangle2_contour_xld在任意方向的矩形中创建一个或多个XLD轮廓
*矩形有中心(行、列),方向为Phi,半边长度为Length1和Length2。角度Phi必须以弧度为单位给出,并指定横轴与半长为Length1的边在数学上正方向(逆时针方向)的夹角。通过传递一个由矩形参数组成的元组,可以创建多个XLD轮廓
*参数1 输出外接矩
*参数2 输入矩形中心的行坐标
*参数3 输入矩形中心的列坐标
*参数4 输入矩形的主轴方向角度(弧度)
*参数5 输入矩形的第一个半径长
*参数6 输入矩形的第二个半径长
gen_rectangle2_contour_xld (Rectangle, Row, Column, Phi, Length1, Length2)
*显示图像
dev_display (Image)
*设置输出显示的颜色数目
dev_set_colored (12)
*显示PADs区域
dev_display (Rectangle)
附加:
①、union_adjacent_contours_xld算子的计算流程:
在此详细说明一下参数3(MaxDistAbs)和参数4(MaxDistRel)的计算方式:
参数3->等高线端点的最大距离
定义两个轮廓之间可接受的最大绝对距离。距离沿参考等高线的回归线测量。因此,它是两条等值线之间的间隙投影到参考等值线回归线上的长度
参数4->等高线端点相对较长的等高线长度的最大距离
定义了两个轮廓之间可接受的最大相对距离。相对距离的计算方法是将距离a(见参数MaxDistAbs的描述)除以参考轮廓线的长度b
②、fit_rectangle2_contour_xld算子的计算流程:
对应代码里面的注释详解
对于参数2 Algorithm =“huber”和“tukey”,一个稳健的误差统计用来估计轮廓点距离矩形的近似边的标准差,而忽略异常值。对矩形的每条边分别计算标准差,以便处理两边不完全垂直的矩形。参数7 ClippingFactor(相对于标准偏差的缩放因子)控制离群值的数量:选择ClippingFactor的值越小,检测到的离群值就越多。对异常值进行迭代检测。参数6 Iterations指定迭代的次数。对于Algorithm = ‘regression’,后两个参数的值将被忽略。注意,在tukey方法中,离群值在执行近似之前被移除,所有其他点都被加权,而在huber方法中,离群值仍然有很小的影响。特别地,对于离群点,优化受到线性影响,而对于距离较小的点,优化受到二次影响。对于代数方法,所有点的距离对优化有二次影响,因此对异常值不具有鲁棒性。在实践中,推荐采用tukey方法
为了减少计算负荷,可以将矩形的拟合限制在轮廓点的一个子集内:如果给参数3 MaxNumPoints赋值不是-1,则只使用均匀分布在轮廓上的MaxNumPoints
根据用于创建轮廓的处理,轮廓的起始点和结束点可能包含位置误差。因此,可以从矩形拟合中排除轮廓开始和结束处的参数5 ClippingEndPoints点
当等值线的起始点和结束点之间的距离<= 参数4 MaxClosureDist时,我们认为等值线是闭合的。对于闭合轮廓,不使用轮廓的端点进行矩形拟合,因为它将获得拟合中剩余点的两倍权重
矩形与轮廓的拟合是基于寻找轮廓点与矩形四条边之间的对应关系。为了使拟合成功,必须至少有一个点位于代表各自矩形边的线段内部,也就是说,这个点不能位于线段的端点。因此,至少需要8个等高线点才能符合矩形。一个点被内部分配到与它有最小距离的矩形边。为此,在内部使用当前最优的矩形参数,即当前迭代步骤使用的参数。如果在矩形的至少一侧没有找到对应的点,则不能唯一地确定矩形参数。在本例中,返回错误3266。因此,fit_rectangle2_contour_xld的调用者必须确保输入的轮廓与矩形足够相似。特别是,如果等高线被四条线近似,等高线的内角不能小于45度,也不能大于135度。由于轮廓点被分配到矩形的最近边,这将意味着矩形的至少一侧将没有相应的点。此外,ClippingFactor不能选得太小,以免孤立点抑制产生没有相应轮廓点的矩形边。这只会发生在Algorithm = ‘tukey’。如果满足上述条件,fit_rectangle2_contour_xld将返回高度精确的矩形参数。如果使用Tukey的离群点抑制方法,则可以使用fit_rectangle2_contour_xld对矩形进行稳健拟合,如圆角矩形轮廓。
效果展示: