2D匹配
说明:
(1)[Out]为算子的输出,其余为输入;
(2)ModelID 表示模型的索引;
(3)create函数中,AngleStart、AngleExtent、AngleStep分别表示模板的最小旋转角度、旋转跨度、角度的步长(分辨率),以rad为单位;【注意:旋转范围相对于参考图像定义,即起始角度 0 对应对象在参考图像中的方向。因此,例如允许旋转角度为+/-5°,应将起始角度AngleStart设置为 -rad(5),将角度跨度AngleExtent设置为 rad(10)。】
Q1:角度的旋转方向好像没有说明,只说明了相对参考图像来定义旋转范围。–>观察first_example_shape_matching例程的结果,就能得到旋转方向,例程中逆时针方向角度从0开始增大,0°的位置由模板图像决定;下面两幅图说明了这个情况:
(4)find函数中,NumMatches表示每次查找目标的数量,一次查找多个,该值为0;
(5)find函数中,Row、Column、Angle、Score分别为查找到的目标的中心位置 (实际是模板ROI的中心)、角度、与模板的相似度;
下图,全图匹配,找到所有可能的匹配目标,输出的匹配点很接近模板ROI的中心:(以下几张图片匹配点坐标由find_shape_model输出)
下图,蓝色框内部只有一个对象,模板ROI是绿色框,注意观察表内的匹配框中心和匹配点的坐标: 1个问题:蓝色框中心是匹配框中心吗?
下图,蓝色框内有两个目标,绿色框是模板ROI,匹配这两个目标,注意观察表内的匹配框中心和匹配点,可以发现蓝色框的中心不是匹配框中心,再次确定 匹配点是模板ROI的中心(像素误差1~2,个人认为可以忽略);
(6)Contrast:Contrast = [lowerThre,upperThre,minSize]表示滞后阈值,val(upperThre)==val(lowerThre)表示不使用滞后阈值,minSize的值可以是具体的数值,也可以是“auto_min_size”;注意:自动确定的参数值可能不是最适合的。【hysteresis_threshold:主要看low、high和maxlength这三个参数,某个灰度值为g。
(1)g≥high的点,都接受,称为“安全点”;
(2)介于low、high之间的点称为“潜在点”,pg1表示;“潜在点”到“安全点”的路径有最大长度,如果pg1通过该条路径可以到达“安全点”,那么pg1被归为“安全点”;】
(1)以像素灰度值的关系描述模型
主要介绍NCC匹配的相关内容。
特点:使用像素及其邻域灰度值作为模板;
方法:包括灰度值匹配和NCC匹配,但是这里只记录NCC匹配,下图是NCC匹配的方法;
适用场景:适用于(1)以固定纹理为特征的图像;(2)图像严重失焦,比如物体到相机的距离变化引起的失焦,模板需是良好聚焦的图像;(3)线性光照变化大时也能用,比如曝光时间从极短到极长,模板需是良好照明下的图像;(4)但不适用于背景太复杂的图像。
- 创建:create_ncc_model
- create_ncc_model (Template, NumLevels, AngleStart, AngleExtent, AngleStep, Metric, ModelID)
[Out]:ModelID
- create_ncc_model (Template, NumLevels, AngleStart, AngleExtent, AngleStep, Metric, ModelID)
- 查找:find_ncc_model
- find_ncc_model (Image, ModelID, AngleStart, AngleExtent, MinScore, NumMatches, MaxOverlap, SubPixel, NumLevels, Row, Column, Angle, Score)
[Out]:Row, Column, Angle, Score
- find_ncc_model (Image, ModelID, AngleStart, AngleExtent, MinScore, NumMatches, MaxOverlap, SubPixel, NumLevels, Row, Column, Angle, Score)
- 清除:clear_ncc_model
- clear_ncc_model (ModelID)
(2)以模型轮廓的形状描述模型
包括形状、组件、局部可形变,下图概括了所有的方法;
shape原理:提取ROI中的边缘特征,结合灰度信息创建模板,并根据模板的大小和清晰度的要求生成多层级的图像金字塔模型;接着在图像金字塔层中自上而下逐层搜索模板图像,直到搜索到最底层,或得到确定的匹配结果为止。
适用场景:(1)边缘能和背景很好地区分开,或者是物体内部不同对象能很好区分开;(2)彩色图像做模板更有利于避免重叠的对象被匹配到;下图是一些可以用作模板的例子。
模型来源:(1)直接从原图中截取一部分图像作为模板;(2)从图像中提取边缘拟合对应的形状(圆、椭圆、线、带方向的矩形),或者用具体参数直接生成对应的形状。两者在创建模板时的算子有点不同,后者需要带_xld后缀。
-
创建:create_shape_model
-
create_shape_model (Image, NumLevels, AngleStart, AngleExtent, AngleStep, Optimazition, Metric, Contrast, MinContrast, ModelID)
[Out]:ModelID
Contrast:测量对象和背景之间以及对象的不同部分之间的局部灰度值差异,用来得到重要特征;
NumLevels,Optimazition:加速搜索,建议值‘auto’;
MinContrast,Metric:确定要和模型进行比较的像素;创建合适的模型,可以调整以下几个参数:
(1)Contrast:确定哪些像素被归纳为模型的一部分;
(2)NumLevels:利用下采样加速搜索;
(3)Optimization:减少模型点的数量,加速搜索;
(4)AngleStart、AngleExtent、AngleStep:指定旋转范围;
(5)ScaleMin、ScaleMax、ScaleStep:指定缩放范围,用于缩放匹配中;
(6)MinContrast、Metric:确定哪些像素和模型比较;用inspect_shape_model观察NumLevels对模型像素点数量的影响
inspect_shape_model (ImageROI, ModelImages, ModelRegions, NumLevels, 30)-
NumLevels = 1:
-
NumLevels = 2:
-
NumLevels = 3:
-
NumLevels = 4:
-
NumLevels = 5:
随着NumLevels的增大,模型的像素点越来越少。假设目前取NumLevels = 8,计算每一层金字塔模型的面积,找到最后一个面积大于等于15的金字塔层级,即为最高的金字塔级数。【原文:建议选择至少包含10-15个像素的模型为最高金字塔级,并且模型的形状仍然与物体的形状相似。】
用inspect_shape_model观察Contrast对模型质量的影响
inspect_shape_model (ImageROI, ModelImages, ModelRegions, 8, Contrast)-
Contrast = 10:
-
Contrast = 20:
-
Contrast = 30:
-
Contrast = 40:
-
Contrast = 50:
当Contrast取值为40、50时,有表示特征的像素点丢失;取值为10、20时,有许多干扰点;取30的效果比较好。建议先观察对比度的值,找到合适的对比度之后,再观察NumLevels的值。
-
-
查找:find_shape_model(s)
-
find_shape_model (Image, ModelID, AngleStart, AngleExtent, MinScore, NumMatches, MaxOverlap, SubPixel, NumLevels, Greediness, Row, Column, Angle, Score)
[Out]:Row,Column,Angle,Score
-
find_shape_models (Image, ModelIDs, AngleStart, AngleExtent, MinScore, NumMatches, MaxOverlap, SubPixel, NumLevels, Greediness, Row, Column, Angle, Score, Model)
[Out]:Row,Column,Angle,Score,Model
NumLevels:(1)单独赋值为0,表示使用建模时的值;(2)添加第二个值,这样不仅能在最高层搜索,也能在最低层搜索,如果想在图像质量差(比如很模糊)的图像上搜索,可以选择该方式,即“增加容忍模式”(increased tolerance mode,必须用负数指定最低层);
【如果搜索是在比第一个金字塔层还要高的金字塔层完成的,这对应于原始的全尺寸图像,搜索就会变得更快。另一方面,搜索的鲁棒性和准确性也比较低。】
NumLevels = [4,2]:表示匹配从第4层开始,并追踪匹配到第2层(最低层用值1表示),此机制可用于减少匹配的运行时间;
NumLevels = [4,-2]:表示匹配从第4层开始,并追踪匹配到第2层。这意味着在第2级金字塔上搜索形状模型的实例。例程:matching_defouced_pcb。【如果最后一个金字塔级别被指定为负数,则 find_shape_model 将返回找到匹配项的最低金字塔级别的匹配项。 也就是说一定会在最低层找到一个实例。】
(原文:If no instance of the model can be found on this pyramid level, the lowest pyramid level is determined on which at least one instance of the model can be found. 不太理解这句话)- Greediness:(1)值为0,启用安全搜索,相对耗时;(2)值为1,不安全搜索,罕见情况下也能找到模型,搜索速度最快;(3)值为0.9,大多数情况下能找到模型(应用到项目中一般都是设置这个值);
-
-
清除:clear_shape_model,如果有多个模板,需要多次调用
说明:
(1)假设想用同一个模型来检测不同任务(每个任务所需的角度不同),那么可以在创建模型时给出一个大的旋转值,在查找模型时给出小的旋转值;
(2)如果金字塔过大,模板不容易识别出来,这是需要将find_shape_model函数中MinScore和Greediness参数设置的低一些。匹配速度的优化步骤:
Step1:确认是否所有对象实例都被找到,如果没有,判断原因(总结了8个);-
该对象是否在图像边界处被裁剪?
-
搜索算法是否“太贪婪了”?(目标清晰,但Grediness值太大可能会找不到,将值设为0,进行强制且彻底的搜索。)
-
物体是否被部分遮挡?(MinScore值设小一点。)
-
在最高的金字塔级别上,匹配失败了吗?
-
这个物体的对比度很低吗?(MinContrast的值设小一点。)
-
对比度的极性是全局反转的还是局部反转的?(在创建模板时选择合适的Metric值。如果只有一小部分对象受到影响,那么最好是减小MinScore的值。)
-
该对象是否与该对象的另一个实例重叠?(增大 MaxOverlap的值。)
-
是否在同一个对象上找到了多个匹配项?(如果对象几乎是对称的,那么严格限制其旋转范围,或增大 MaxOverlap的值。)
对称图形的旋转范围参考值如下图所示:
Step2:调整和速度相关的具体参数。(调大MinScore,匹配成功就行;调大Grediness,直到匹配失败,此时减小MinScore的值,如果没有作用,就还是恢复原来的值吧;缩小旋转范围和缩放范围;缩小搜索Roi;确保该模型由许多轮廓点组成,并且这些轮廓具有明显的支撑结构,可以从图像中的其他结构中明显地区分出来。)
调整以下参数会很“冒险”,选的值不合适就会导致匹配失败:MinContrast、Optimization、AngleStep,以及NumLevels;-
其它形式的shape匹配查找函数:相同缩放比例和不同缩放比例
find_scaled_shape_model (ImageSearch, ModelID, rad(-45), rad(90), 0.8, 1.0, 0.5, 0, 0.5, ‘least_squares’, 5, 0.8, Row, Column, Angle, Scale, Score)
[Out]:Row, Column, Angle, Scale, Score
输入参数说明:
AngleStart
:rad(-45),AngleExtent
:rad(90);ScaleMin
:0.8,,ScaleMax
:1.0;MinScore
:0.5,NumMatches
:0,MaxOverlap
:0.5;SubPixel
:‘least_squares’,NumLevels
:5,Grediness
:0.8find_aniso_shape_model (Image, ModelID, -rad(10), rad(20), 0.9, 1.7, 0.9, 1.1, 0.7, 0, 0.5, ‘least_squares’, 0, 0.8, Row, Column, Angle, ScaleR, ScaleC, Score)
[Out]:Row, Column, Angle, ScaleR, ScaleC, Score
输入参数值说明:
AngleStart
:-rad(10),AngleExtent
:rad(20);ScaleRMin
:0.9,ScaleRMax
:1.7;ScaleCMin
:0.9,ScaleCMax
:1.1;MinScore
:0.7,NumMatches
:0,MaxOverlap
:0.5;SubPixel
:‘least_squares’,NumLevels
:0,Grediness
:0.8 -
匹配结果的轮廓可视化(
字体
为可视化的结果)(1)标准形式下的可视化:
get_shape_model_contours (ShapeModel, ModelID, 1)
vector_angle_to_rigid (0, 0, 0, Row, Column, Angle, HomMat2D)
affine_trans_contour_xld (ShapeModel,ModelAtNewPosition
, HomMat2D)(2)相同缩放比例的可视化:
get_shape_model_contours (Model, ModelID, 1)
hom_mat2d_identity (HomMat2DIdentity)
hom_mat2d_translate (HomMat2DIdentity, Row, Column, HomMat2DTranslate)
hom_mat2d_rotate (HomMat2DTranslate, Angle, Row, Column, HomMat2DRotate)
hom_mat2d_scale (HomMat2DRotate, Scale, Scale, Row, Column, HomMat2DScale)
affine_trans_contour_xld (Model,ModelTrans
, HomMat2DScale)(3)不同缩放比例的可视化:
get_shape_model_contours (ModelContours, ModelID, 1)
hom_mat2d_identity (HomMat2D)
hom_mat2d_scale (HomMat2D, ScaleR, ScaleC, 0, 0, HomMat2D)
hom_mat2d_rotate (HomMat2D, Angle, 0, 0, HomMat2D)
hom_mat2d_translate (HomMat2D, Row, Column, HomMat2D)
affine_trans_contour_xld (ModelContours,ContoursTrans
, HomMat2D)Q:可视化过程中,计算仿射变换时,先平移后拉伸,和先拉伸后平移,二者计算结果有差异吗?
A:没有,但是要注意传入的参数,主要是Row和Column。下面给出说明。先用hom_mat2d_identity生成一个矩阵HomMat2D。
hom_mat2d_identity(HomMat2D)(1)先平移后拉伸
hom_mat2d_translate (HomMat2D, Row, Column, HomMat2D)
hom_mat2d_rotate (HomMat2D, Angle, Row, Column, HomMat2D)
hom_mat2d_scale (HomMat2D, ScaleR, ScaleC, Row, Column, HomMat2D)
(2)先拉伸后平移
hom_mat2d_scale (HomMat2D, ScaleR, ScaleC, 0, 0, HomMat2D)
hom_mat2d_rotate (HomMat2D, Angle, 0, 0, HomMat2D)
hom_mat2d_translate (HomMat2D, Row, Column, HomMat2D)
-
(2)component
- 创建:create_component_model 或 train_model_components+create_train_component_model,前者从已知的位置和角度变化获取部件之间的关系;后者从训练图像中获得关系,如果不需要训练组件,可以使用clear_training_components销毁;
- 查找:find_component_model
- 清除:clear_component_model
-
(3)local deformable
即使轮廓有轻微的形变,也能匹配到,下图左是标准图,下图右说明了有形变也能匹配到;
-
创建:create_local_deformable_model
create_local_deformable_model (Template, NumLevels, AngleStart, AngleExtent, AngleStep, ScaleRMin, ScaleRMax, ScaleRStep, ScaleCMin, ScaleCMax, ScaleCStep, Optimization, Metric, Contrast, MinContrast, ParamName, ParamValue, ModelID)
[Out]:ModelID
使用说明:
(1)ScaleRMin, ScaleRMax, ScaleRStep:行方向上的缩放值,建议值,没有标准shape方法那么严格,Angle*同理;
(2)ScaleCMin, ScaleCMax, ScaleCStep:列方向上的缩放值,建议值,没有标准shape方法那么严格;
(3)ParamName:通用参数,默认值取 [],其它值包括’min_size’和 'part_size’,通常情况下用默认值就可以;
(4)ParamValue:通用参数,默认值取 ‘[]‘,通常情况下用默认值就可以;
当ParamName=‘part_size’时,ParamValue可取值为’big’,‘medium’, 或者’small’;
当ParamName='min_size’时,ParamValue给出一个具体的数值就可以;
-
查找:find_local_deformable_model
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)
[Out]:ImageRectified, VectorField, DeformedContours, Score, Row, Column
输出说明:
(1)ImageRectified:已找到模型的校正图像;
(2)VectorField:矢量变换矩阵;【原文:Vector field of the rectification transformation.】
(3)DeformedContours:已找到的模型示例的轮廓;
上述三项参数输出由输入参数ResultType决定,ResultType取值为[‘image_rectified’,‘vector_field’,‘deformed_contours’],分别对应上述三项;
-
清除:clear_local_deformable_model
-
-
(3)以一组重要的图像点描述模型
主要是基于描述符的匹配,下图概括了此类方法;
- 创建:create_(un)calib_descriptor_model
- 查找:find_(un)calib_descriptor_model
- 清除:clear_descriptor_model