*此程序显示了如何以亚像素精度检测钻石的边缘以及如何确定钻石顶点的位置。
*首先,我们使用阈值图像对钻石进行分割,并提取钻石边缘周围的较薄区域 通过使用形态学运算。
*然后,以亚像素精度提取边缘并将其拟合为直线。 随后,通过拟合直线相交来确定钻石底尖的位置。
dev_update_off ()
dev_close_window ()
read_image (Image, 'diamond/diamond_01')
get_image_size (Image, Width, Height)
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)
set_display_font (WindowHandle, 16, 'mono', 'true', 'false')
dev_set_line_width (2)
*
NumImages := 5
for Index := 1 to NumImages by 1
read_image (Image, 'diamond/diamond_' + Index$'.2')
*
* Segment diamond region//分割钻石区域
threshold (Image, Region, 128, 255) //灰度128~255
clip_region_rel (Region, RegionClipped, 0, 290, 0, 0) //将输入Region的最小外接矩形区域进行剪切,按照上下左右剪裁,此处向下剪裁290
shape_trans (RegionClipped, RegionTrans, 'convex') //变换区域的形状,'convex'为凸包,围绕点或形状的紧密拟合的凸边界
dilation_rectangle1 (RegionTrans, RegionDilation, 5, 1) //使用矩形结构元素对区域进行膨胀,width=5,heigh=1
erosion_rectangle1 (RegionTrans, RegionErosion, 5, 1) //使用矩形结构元素对区域进行腐蚀
difference (RegionDilation, RegionErosion, RegionDifference) //膨胀区域-腐蚀区域,注意:大区域减去小区域
reduce_domain (Image, RegionDifference, ImageReduced) //Image中RegionDifference的那部分图像
*
* Subpixel accurate fitting of the edges //亚像素边缘的精确拟合
edges_sub_pix (ImageReduced, Edges, 'canny', 3, 5, 5) //亚像素边缘提取
union_collinear_contours_xld (Edges, UnionContours, 100, 10, 4, rad(10), 'attr_keep') //将近似共线轮廓合并
select_contours_xld (UnionContours, SelectedContours, 'contour_length', 50, 2000, 0, 0) //选择轮廓长度为50~2000的边界
fit_line_contour_xld (SelectedContours, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist) //对一些线段的XLD做近似计算直线计算,最小二乘法
*
* Sort the edge contours and determine their intersection
tuple_sort_index (RowBegin, Indices) //将一组数组进行升序排列,然后将其在原数组的index按升序放入indexs中
RowBegin := subset(RowBegin,Indices) //选取数组RowBegin中的第Indices个元素
RowEnd := subset(RowEnd,Indices)
ColBegin := subset(ColBegin,Indices)
ColEnd := subset(ColEnd,Indices)
Nr := subset(Nr,Indices) //法向量的行坐标
Nc := subset(Nc,Indices) //法向量的列坐标
Dist := subset(Dist,Indices) //原点到该线的距离
gen_contour_polygon_xld (LineEdge1, [Dist[0] / Nr[0],0], [0,Dist[0] / Nc[0]]) //不带圆角的多边形轮廓,产生直线
gen_contour_polygon_xld (LineEdge2, [Dist[1] / Nr[1],Width - 1], [0,(Dist[1] - (Width - 1) * Nr[1]) / Nc[1]]) //产生直线
intersection_lines (RowBegin[0], ColBegin[0], RowEnd[0], ColEnd[0], RowBegin[1], ColBegin[1], RowEnd[1], ColEnd[1], RowTip, ColTip, IsOverlapping) //计算两线的交点
gen_cross_contour_xld (Cross, RowTip, ColTip, 20, rad(45)) //生成XLD轮廓,在两线交点画一个十字叉
*
* Display the results //显示结果
dev_display (Image)
dev_set_color ('yellow')
dev_display (LineEdge1)
dev_display (LineEdge2)
dev_set_color ('blue')
dev_display (Cross)
if (Index != NumImages)
disp_continue_message (WindowHandle, 'black', 'true')
stop ()
endif
endfor
fit_line_contour_xld( Contours : : Algorithm, MaxNumPoints, ClippingEndPoints, Iterations, ClippingFactor : RowBegin, ColBegin, RowEnd, ColEnd, Nr, Nc, Dist ) //对一些线段的XLD做近似计算直线计算
regression:回归,标准的最小二乘法拟合
huber:加权的最小二乘法拟合,异常值的影响被减小基于Huber方法
tukey:加权的最小二乘法拟合,异常值的影响被减小基于Tukey方法
drop:加权的最小二乘法拟合,异常值的影响被消除
gauss:加权的最小二乘法拟合,异常值的影响被减小基于最逼近线上的所有其轮廓点的平均值和距离标准方差
Contours(in):输入轮廓
Algorithm(in):形成线的算法
MaxNumPoints(in):用于计算的最大轮廓点个数
ClippingEndPoints(in):在逼近过程中被忽略的开始及末尾点个数
Iterations(in):迭代的最大次数
ClippingFactor(in):消除异常值的裁剪因子
RowBegin(out):线段开始点的行坐标
ColBegin(out):线段开始的列坐标
RowEnd(out):线段结尾的行坐标
ColEnd(out):线段结尾的列坐标
Nr(out):线参数:法向量的行坐标
Nc(out):法向量的列坐标
Dist(out):原点到该线的距离
gen_contour_polygon_xld (Line, [RowBegin,RowEnd], [ColBegin,ColEnd]) //不带圆角的多边形轮廓
源代码的操作,我很迷呀!
gen_contour_polygon_xld (LineEdge1, [Dist[0] / Nr[0],0], [0,Dist[0] / Nc[0]]) //不带圆角的多边形轮廓,产生直线
gen_contour_polygon_xld (LineEdge2, [Dist[1] / Nr[1],Width - 1], [0,(Dist[1] - (Width - 1) * Nr[1]) / Nc[1]]) //产生直线
//画线
//也可以这样画出直线段 ,但是显示的不太明显,例程中做了一定的调整
//gen_contour_polygon_xld (LineEdge1, [RowBegin[0],RowEnd[0]], [ColBegin[0],ColEnd[0]])
//gen_contour_polygon_xld (LineEdge2, [RowBegin[1],RowEnd[1]], [ColBegin[1],ColEnd[1]])
参考博问说的:https://blog.csdn.net/xd940940/article/details/104711747
1.提取轮廓:腐蚀区域 减去 膨胀区域 = 边缘区域
2.求物体的尖端:尖端两侧 两个线段 交点