检测垫圈局部变形
*这个例子演示了如何利用局部变形匹配(local deformable matching)来寻找出垫圈是否变形
dev_update_off()
Smoothness:=25
read_image(ModelImage,..
read_image( Image,......
下面是ModelImage和Image(两个基本相近,肉眼难辨)
显示信息不予赘述。。。
一:创建variation model (差异模型)
sobel_amp(ModelImage, EdgeAmplitude, 'thin_max_abs', 5)
*/ 'thin_sum_abs' (thin(|a|) + thin(|b|)) / 4来求得幅值大小, 其中a,b是sobel卷积之后所求单一像素的输出值(横向,纵向)/*
1 , create_variation_model( 425,410,'byte', 'direct', VariationModelId)
create_variation_model( : : Width, Height, Type, Mode : ModelID)
创建一个差异比较的模型
描述:这个函数创建一个用于图像比较的handle, variation model是典型的从不合格产品中分辨出合格产品的应用模型(根据灰度图比较)。
差异模型(VariationModel)包含两部分,第一部分是理想的标准图(用于之后的比较,compare_variation_model或者compare_ext_variation_model),第二部分是一张图片,它包含了训练图中各张之间或者平均的差异信息。
/*差异模型(VM)使用多张标准图来进行训练,它的本质需要这些训练用的图片能够在同一个位置合同一个角度,当无法保证同位置同角度的时候,可以使用find_shape_model匹配来使图片转换到正确位置(利用affine_trans_image)*/
这里的type指的是对比的图像类型,Mode参数决定了如何训练标准图以及如何进行侧视图和标准图之间的差异匹配,Mode:
' standard' :标准图由训练图的平均值来得到(经过矫正位置之后的训练图),差异值的计算是标准图与测试图的标准差 (这种方法的优势是可以通过迭代来训练标准图,直接使用train_variation_model进行训练,缺点是必须花费很大代价来确认训练图的正确性,保证准确率)
' robust' : 标准图由多张训练图的中值来计算,差异值的计算是由训练图经过正确缩放后与测试图进行比较得到的一组数值得中值(这种模式对误差的容忍度搞,不过不可以迭代训练,必须通过concat_obj 和train_variation_model来训练)
2, prepare_direct_variation_model(ModelImage, EdgeAmplitude, VariationModelID, 30, 1.5)
prepare_direct_variation_model(RefImage, VarImage : : ModelID, AbsThreshold, VarThreshold : )
对进行的比较做准备,使用这个函数,前面的创建差异模型时候的mode必须是’direct'。direct在这里相对于prepare_variation_model的差别是,标准图和相应的差异图并不是使用train_variation_model计算出来的,而是直接在RefImage和VarImage中指出来,作为函数输入。此函数非常适合标准图只有一张,即没有多张训练图的情况。这种情况下,差异图variation image应该由边缘函数'sobel_amp, edges_image, gray_range_rect' 等生成。(variation image指的是an image that represents the amount of gray value variation at every point of the object)
二:创建本地可变性模型
1, create_local_deformable_model(ModelImage, 'auto', rad(-10), rad(20),'auto',0.9,1.1, 'auto', 'none', 'use_polarity', 'auto', 'auto', [],[],ModelID)
create_local_deformable_model(Template : : NumLevels, AngleStart, AngleExtent, AngleStep, ScaleRMin, ScaleRMax, ScaleRStep, ScaleCMin,ScaleCMax, ScaleCStep, Optimization, Metric, Contrast, MinContrast, ParamName, ParamValue : ModelID)
描述:
这个操作把模板Template做准备工作用来后续的局部变形检测,变形模型的ROI作为此模板的roi
变形检测用来检测一个对象是否局部变形,这个检测模型在保持严格的基础上允许一些细小的变形,
和find_shape_model(在图中找到相应图形的最佳匹配)不同,create_local_deformable_model更加智能化,它可以预估变形程度并且修正图像中物体的位置
(物体相对于图像的相对位置),它可以处理更大的变形。
模型中,参照点(reference point)是由标准图中对象的重力中心点位置决定的,并且使用物体模板的axis-aligned cnclosing rectangle(个人理解就是一个矩形的长短轴相关)来决定搜索区域(使用find_local_deformable_model)
参数介绍:
Template:输入多通道图像,用来创建model
NumLevels:输入integer,用来控制最多有多少层金字塔层数:'auto', 0,1,2,3,。。。
AngleStart:输入角度,控制初始的最小角度(调整匹配时候开始的最小角度,默认-0.39)
AngleExtent:输入角度,控制旋转的范围,默认0.79
AngleStep:输入角度,控制旋转的最小角度,即分辨率,默认’auto'
ScaleRMin:行方向的最小缩放比例,默认1.0,通常大于0小于1
ScaleRMax:行方向的最大缩放比例,默认1.0,通常大于1小于1.5
ScaleRStep:行方向的缩放步长,可影响行方向的分辨率,默认'auto', 0.01,0.02,0.05,。。
ScaleCMin:
ScaleCMax: 列方向,同上
ScaleCStep:
Optimization:生成模型时的优化方式,默认'none',可选,'auto','point_reduction_XXX'
Metric: 比较时候的标准:默认'use_polarity'使用极坐标系进行比较
Contrast:在模板图片的滤波或者磁滞滤波中,控制结果的对比度,默认'auto', 10, 20....
MinContrast:在搜寻对象过程中的最小对比度,默认'auto', 1, 2, 3, 5....
ParamName: 普通参数名字(不太清楚用途,后续研究)默认[], 'min_size','part_size'
ParamValue:参数值, 默认[], 可选'small', 'medium', big'
ModelID: 输出的模型handle
3, get_deformable_model_contours( ModelContours, ModelID,1)
get_deformable_model_contours( : ModelContours : ModelID, Level : )
获取可变模型的边缘, Level决定了返回第几层金字塔图像的边缘
area_center( ModelImage, Area, Row, Column)
hom_mat2d_identity(HomMat2DIdentity)
创建一个单位矩阵,即对角线为1,其他为0,注意:产生的矩阵以tuple形式存在,且最后一行不显示
* / 1 0 0 \
* HomMat2DIdentity = | 0 1 0 |
* \ 0 0 1 /
齐次坐标(Homogenous Coordinate)
以点p(x,y)为例,如果想把它平移(a,b),至p’(x+a,y+b),是丌可能用矩阵计算完成的,
现在换成齐次坐标(x,y,1),通过矩阵相乘(左侧公式) ,很方便得到平移后的坐标(x+a,y+b)。
为了保持一致把矩阵改成 右侧矩阵,这就是齐次变换矩阵。
hom_mat2d_translate(HomMat2DIdentity, Row, Colum, HomMat2DTranslate)
hom_mat2d_translate( : : HomMat2D, Tx, Ty : HomMat2DTranslate)
对上面创建的单位矩阵进行转换,公式为:
/ 1 0 Tx \
HomMat2DTranslate = | 0 1 Ty | * HomMat2D
\ 0 0 1 /
注意,这个转换矩阵使用的右手规则,也就是说x轴对应的是行,y轴对应的是列
转换的意义是:
定位中心点,在后面的转换中,对结果矩阵进行行和列的定位。
这里生成的矩阵主要用于后面对对象图像的旋转,位移等等转换
(ModelContours样子)
affine_trans_contour_xld(ModelContours, ContoursAffinTrans, HomMat2DTranslate)
affine_trans_contour_xld(Contours : ContoursAffinTrans : HomMat2D : )
对模型的边缘进行一次任意仿射矩阵转换(旋转,位移,轻微扭转等等,这里使用的是identity,所以没有变化)
********************************************************
下面对图像进行迭代的处理
********************************************************
下面对图像进行迭代的处理
NumImages: = 7
for Index :=1 to NumImages by 1
read_image(Image, 'gasket/gasket_'+Index$'02')
dev....显示。。。
*接下来,在测试图中找到测试的model。 找到修改图,各自的向量区域和需求的边界
*query the rectified image, the respective vector field and the found contours
count_seconds(S1)
重点:
find_local_deformable_model(Image, ImageRectified, VectorField, DeformedContours, ModelID, rad(-10), rad(20), 1,1,1,1,0.93, 1, 0.7,0 ,0.4,['image_rectified', 'vector_field', 'deformed_contours'], ['deformation_smoothness','expand_border','subpixel'],[Smoothness, 0, 1], Score, Row, Column)
find_local_deformable_model(Image : ImageRectified, VectorField, DeformedContours : ModelID, AngleStart, AngleExtent, ScaleRMin, ScaleRMax, ScaleCMin, ScaleCMax, MinScore, NumMatches, MaxOverlap, NumLevels, Greediness, ResultType, ParamName, ParamValue : Score, Row, Column)
(find_local_deformable_model的结果)
这个函数的功能是在一张图片中找到local deformable model(ModelID) 的最佳匹配结果(可以是多个,由NumMatches输入),
模型必须在之前的步骤中使用(create_local_deformable_model或者read_deformable_model)生成。这个函数会返回找到的结果的行,列坐标作为输出。
另外,图片被修改的部分(ImageRectified),他们分别得向量区域(VectorField)和找到的模型的边界(DeformedContours)都可以被返回作为结果。
默认情况下,这些不被返回。为了应对需要上述一个或者全部对象的情况,参数ResultType应该被设置为'image_rectified','vector_field', 'deformed_contours'.
其中,ImageRectified和VectorField的大小根据创建local_deformable模型时候的最小图片来决定(模型大小),但是他们的大小也可以通过设置
ParamName(设定为expand_border)和ParamValue (改变number of pixels)来改变。
(ImageRectified)
(VectorField)
(DeformedContours)
同时,用户可以选择性的对一个特定方向指定为结果区域的方向(使用expand_border_top,或者,bottom,left, right),
注意VectorField是绝对坐标,可以用来做convert_map_type。
ParamName也可以设定为'deformation_smoothness'来控制对象的平滑程度。
Score是一个0到1之间的值,来表示一个模型存在一张图片中的程度。例子 三个符合[0.947296, 0.939897, 0.92051]
Greediness表示搜索的贪婪性(0-1),0表示完全准确,但是速度慢,当贪婪为1时候,速度增快但是可能会错过一些对象
ResultType可以选择[], 'image_retified', 'vector_field', 'deformed_contours'
count_seconds(S2)
Time :=S2-S1
if( |Score|>0) *找到的结果数
gen_warped_mesh_region( VectorField, MeshRegion, Smothness)
gen_warped_mesh_region(VectorField : WarpedMesh : Step : )
*********************************gen_warped_mesh***********************************************************
* Generate a grid of the deformation from the VectorField
* The step width is given by the parameter Step.
*
gen_empty_obj (WarpedMesh)
count_obj (VectorField, Number)
for Index := 1 to Number by 1
select_obj (VectorField, ObjectSelected, Index)
vector_field_to_real (ObjectSelected, DRow, DColumn)
(DRow)
(DColumn)
get_image_size (VectorField, Width, Height)
* Horizontal lines
for ContR := 0.5 to Height[0]-1 by Step
tuple_gen_sequence (0.5, Width[0]-1, 1, Column)
Height=170时Column数据 [0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5, 10.5, 11.5, 12.5, 13.5, 14.5, 15.5, 16.5, 17.5, 18.5, 19.5, 20.5, 21.5, 22.5, 23.5, 24.5, 25.5, 26.5, 27.5, 28.5, 29.5, 30.5, 31.5, 32.5, 33.5, 34.5, 35.5, 36.5, 37.5, 38.5, 39.5, 40.5, 41.5, 42.5, 43.5, 44.5, 45.5, 46.5, 47.5, 48.5, 49.5, 50.5, 51.5, 52.5, 53.5, 54.5, 55.5, 56.5, 57.5, 58.5, 59.5, 60.5, 61.5, 62.5, 63.5, 64.5, 65.5, 66.5, 67.5, 68.5, 69.5, 70.5, 71.5, 72.5, 73.5, 74.5, 75.5, 76.5, 77.5, 78.5, 79.5, 80.5, 81.5, 82.5, 83.5, 84.5, 85.5, 86.5, 87.5, 88.5, 89.5, 90.5, 91.5, 92.5, 93.5, 94.5, 95.5, 96.5, 97.5, 98.5, 99.5, 100.5, 101.5, 102.5, 103.5, 104.5, 105.5, 106.5, 107.5, 108.5, 109.5, 110.5, 111.5, 112.5, 113.5, 114.5, 115.5, 116.5, 117.5, 118.5, 119.5, 120.5, 121.5, 122.5, 123.5, 124.5, 125.5, 126.5, 127.5, 128.5, 129.5, 130.5, 131.5, 132.5, 133.5, 134.5, 135.5, 136.5, 137.5, 138.5, 139.5, 140.5]
tuple_gen_const (Width[0]-1, ContR, Row)
get_grayval_interpolated (DRow, Row, Column, 'bilinear', GrayRow)
GrayRow数据
[164.767, 164.728, 164.688, 164.648, 164.608, 164.57, 164.537, 164.507, 164.483, 164.468, 164.456, 164.444, 164.432, 164.42, 164.426, 164.448, 164.47, 164.492, 164.52, 164.553, 164.587, 164.622, 164.657, 164.692, 164.731, 164.773, 164.811, 164.846, 164.878, 164.911, 164.95, 164.996, 165.046, 165.078, 165.094, 165.111, 165.128, 165.14, 165.147, 165.153, 165.159, 165.165, 165.171, 165.17, 165.163, 165.157, 165.146, 165.131, 165.111, 165.084, 165.051, 165.015, 164.978, 164.941, 164.904, 164.865, 164.826, 164.787, 164.749, 164.71, 164.671, 164.629, 164.577, 164.514, 164.435, 164.347, 164.259, 164.17, 164.082, 163.994, 163.906, 163.817, 163.729, 163.641, 163.553, 163.464, 163.376, 163.288, 163.2, 163.111, 163.026, 162.951, 162.888, 162.839, 162.801, 162.762, 162.723, 162.684, 162.646, 162.607, 162.568, 162.53, 162.494, 162.457, 162.421, 162.386, 162.355, 162.329, 162.305, 162.281, 162.26, 162.242, 162.226, 162.212, 162.201, 162.192, 162.184, 162.181, 162.183, 162.188, 162.196, 162.204, 162.213, 162.224, 162.236, 162.247, 162.257, 162.271, 162.287, 162.301, 162.313, 162.322, 162.331, 162.336, 162.34, 162.342, 162.34, 162.333, 162.322, 162.308, 162.293, 162.276, 162.256, 162.234, 162.211, 162.182, 162.149, 162.112, 162.075, 162.037, 161.999]
*Return gray values of an image at the positions given by tuples of rows and columns.
get_grayval_interpolated (DColumn, Row, Column, 'bilinear', GrayColumn)
gen_contour_polygon_xld (Contour, GrayRow, GrayColumn)
concat_obj (WarpedMesh, Contour, WarpedMesh)
endfor
此时结果
* Vertical lines
for ContC := 0.5 to Width[0]-1 by Step
tuple_gen_sequence (0.5, Height[0]-1, 1, Row)
tuple_gen_const (Height[0]-1, ContC, Column)
get_grayval_interpolated (DRow, Row, Column, 'bilinear', GrayRow)
get_grayval_interpolated (DColumn, Row, Column, 'bilinear', GrayColumn)
gen_contour_polygon_xld (Contour, GrayRow, GrayColumn)
concat_obj (WarpedMesh, Contour, WarpedMesh)
endfor
endfor
return ()
显示变换结果
* This procedure displays the results of Shape-Based Matching.
*
NumMatches := |Row|
if (NumMatches>0)
if (|ScaleR|=1)
tuple_gen_const (NumMatches, ScaleR, ScaleR)
endif
if (|ScaleC|=1)
tuple_gen_const (NumMatches, ScaleC, ScaleC)
endif
if (|Model|=0)
tuple_gen_const (NumMatches, 0, Model)
elseif (|Model|=1)
tuple_gen_const (NumMatches, Model, Model)
endif
for Index := 0 to |ModelID|-1 by 1
get_shape_model_contours (ModelContours, ModelID[Index], 1)
dev_set_color (Color[Index%|Color|])
for Match := 0 to NumMatches-1 by 1
if (Index=Model[Match])
hom_mat2d_identity (HomMat2DIdentity)
hom_mat2d_scale (HomMat2DIdentity, ScaleR[Match], ScaleC[Match], 0, 0, HomMat2DScale)
hom_mat2d_rotate (HomMat2DScale, Angle[Match], 0, 0, HomMat2DRotate)
hom_mat2d_translate (HomMat2DRotate, Row[Match], Column[Match], HomMat2DTranslate)
affine_trans_contour_xld (ModelContours, ContoursAffinTrans, HomMat2DTranslate)
dev_display (ContoursAffinTrans)
endif
endfor
endfor
endif
return ()
********************************************************************************************
MeshRegion
gen_region_contour_xld(DeformedContours, EdgeRegion, 'margin')
dilation_circle( EdgeRegion, RegionDilation, 2*Smoothness)
intersection(RegionDilation, MeshRegion, RegionIntersection)
intersection(Region1, Region2 : RegionIntersection : : )
两个region的交集
下面依次是DeformedContours, EdgeRegion, RegionDilation, RegionIntersection
dev 显示。。。。。
compare_variation_model(ImageRectified, Region, VariationModelID)
compare_variation_model(Image : Region : ModelID : )
拿一张图片和variation model做比较
描述:在比较值钱,variation model 的两张内部阈值图片必须被提前创建(使用prepare_variation_model 或者prepare_direct_variation_model)。
这里用c(x,y)来代表输入图像Image, t{u,l}来表示两张内部阈值图片。
输出region包括了所有的有本质差异的点的集合
c(x,y) > t{u}(x,y) 或者 c(x,y) < t{l}(x,y)
如果只需要寻找过亮或者过暗的部分,可以用compare_ext_variation_model
程序中出来的Region为:
connection(Region, ConnectedRegions)
select_shape(ConnectedRegions, SelectedRegions, 'area','and' , 30, 99999)
count_obj(SelectedRegions, Number)
if(Number>0)
area_center(SelectedRegions, Area, Row1, Column1)
elliptic_axis(SelectedRegions, Ra, Rb, Phi)
tuple_gen_const(Number, 1,Ones)
PointOder :=[]
for Idx := 0 to Number-1 by 1
PointOrder :=[PointOrder, 'possitive']
endfor
????????????????疑问:这里的Idx怎么用?
gen_ellipse_contour_xld(ContEllipse, Row, Column1, Phi, Ra+10, Rb+10, 0*Ones, 6.28318*Ones, PointOrder, 1.5)
后面是显示工作,
endif和endfor
清除:clear_deformable_model(ModelID)
clear_variation_model(VariationModelID)
总结部分,会列出处理的主要过程和每个过程的主要输入,输出,用在什么地方:
待续