上节说过灰度匹配的鲁棒性太差,在定位一些特殊的简单特征时,使用单方向的灰度跳变特征(和边缘检测类似)来定位的鲁棒性较好,速度快。你可以定位指定的点、边、条纹三种特征,定位的两个特征的间距即为长度、宽度等特征,所以这个模块叫做测量模块。
1.测量流程
(1).分配指定的特征Marker
使用MmeasAllocMarker函数来设置指定的特征,MIL支持三种特征:点(M_POINT),边(M_EDGE),条纹(M_STRIPE)
后两种特征如下:
(2).选取Marker
选取Marker的过程实际上是指定包含Marker一个矩形范围及包含的Marker个数(M_NUMBER)。可以看到这几种特征都是单方向的灰度跳变,所以在设置Marker位置的时候必须包含有跳变。
矩形范围包括起始点(M_BOX_ORIGIN)、大小(M_BOX_SIZE)、角度(M_BOX_ANGLE)。
角度和前面讲的灰度匹配、几何匹配一样可以开启范围匹配(M_BOX_ANGLE_MODE),设置角度范围(M_BOX_ANGLE_DELTA_POS、M_BOX_ANGLE_DELTA_NEG,0~180),设置角度误差允许值(M_BOX_ANGLE_TOLERANCE),设置多角度插补模式(M_BOX_ANGLE_INTERPOLATION_MODE)和角度精度(M_BOX_ANGLE_ACCURANCY)。
(3).设置Marker参数
使用MmeasSetMarker设置相关参数
设置搜索方向
使用参数M_ORIENTATION,可为水平或竖直或任意
设置其他值
(4).测量得到各种测量值
使用MmeasFindMarker开启测量,使用MmeasGetResult得到各种测量结果。
可使用MmeasDraw绘制测量结果
2.测量实例
(1).简单测量
void CMeasureDlg::OnReadSingle()
{
// TODO: Add your control notification handler code here
if (M_NULL != m_milSingleBuf)
{
MbufFree(m_milSingleBuf);
m_milSingleBuf = M_NULL;
}
//导入图像
MbufRestore(TEXT(".\\Image\\Lead.mim"), m_milSystem, &m_milSingleBuf);
//显示图像
MdispZoom(m_milDisplay, 0.8, 0.8);
MdispControl(m_milDisplay, M_CENTER_DISPLAY , M_ENABLE);
MdispSelectWindow(m_milDisplay, m_milSingleBuf, GetDlgItem(IDP_DISP_IMAGE)->GetSafeHwnd());
MdispControl(m_milDisplay, M_OVERLAY_CLEAR, M_DEFAULT);
}
void CMeasureDlg::OnSetSingle()
{
// TODO: Add your control notification handler code here
if (M_NULL != m_milSingleMarker)
{
MmeasFree(m_milSingleMarker);
m_milSingleMarker = M_NULL;
}
//分配Stripe Maker
MmeasAllocMarker(m_milSystem, M_STRIPE, M_DEFAULT, &m_milSingleMarker);
//设置Maker Box
MmeasSetMarker(m_milSingleMarker, M_BOX_ORIGIN, MEAS_BOX_POS_X, MEAS_BOX_POS_Y);
MmeasSetMarker(m_milSingleMarker, M_BOX_SIZE, MEAS_BOX_WIDTH, MEAS_BOX_HEIGHT);
//设置Maker Characteristics
MmeasSetMarker(m_milSingleMarker, M_POLARITY, STRIPE_POLARITY_LEFT, STRIPE_POLARITY_RIGHT);//第一边缘为上升沿,第二边缘为下降沿
MmeasSetMarker(m_milSingleMarker, M_WIDTH, STRIPE_WIDTH, M_NULL);//宽度
MmeasSetMarker(m_milSingleMarker, M_WIDTH_VARIATION, STRIPE_WIDTH_VARIATION, M_NULL);//宽度偏差
MmeasSetMarker(m_milSingleMarker, M_BOX_ANGLE_MODE, M_ENABLE, M_NULL);//角度可变(360)
//在图像的Overlay层上绘制Maker Box
MdispControl(m_milDisplay, M_OVERLAY, M_ENABLE);
MdispInquire(m_milDisplay, M_OVERLAY_ID, &m_milSingleOverlayBuf);
MdispControl(m_milDisplay, M_OVERLAY_CLEAR, M_DEFAULT);
MgraColor(M_DEFAULT, M_COLOR_RED);
MmeasDraw(M_DEFAULT, m_milSingleMarker, m_milSingleOverlayBuf, M_DRAW_BOX, M_DEFAULT, M_MARKER);
}
void CMeasureDlg::OnGetSingle()
{
// TODO: Add your control notification handler code here
//目标图像中寻找Maker,测量结果保存在Maker中
MmeasFindMarker(M_DEFAULT, m_milSingleBuf, m_milSingleMarker, M_DEFAULT);
//获得测量结果(位置、宽度、角度)
double StripeCenterX, /* Stripe X center position.*/
StripeCenterY, /* Stripe Y center position.*/
StripeWidth, /* Stripe width. */
StripeAngle; /* Stripe angle. */
MmeasGetResult(m_milSingleMarker, M_POSITION, &StripeCenterX, &StripeCenterY);
MmeasGetResult(m_milSingleMarker, M_WIDTH, &StripeWidth, M_NULL);
MmeasGetResult(m_milSingleMarker, M_ANGLE, &StripeAngle, M_NULL);
//绘制 Maker Box
MgraColor(M_DEFAULT, M_COLOR_BLACK);
MdispControl(m_milDisplay, M_OVERLAY_CLEAR, M_DEFAULT);//清除显示OverLay层
MmeasDraw(M_DEFAULT, m_milSingleMarker, m_milSingleOverlayBuf, M_DRAW_BOX, M_DEFAULT, M_RESULT);
//绘制测量结果
MgraColor(M_DEFAULT, M_COLOR_YELLOW);
MmeasDraw(M_DEFAULT, m_milSingleMarker, m_milSingleOverlayBuf, M_DRAW_POSITION, M_DEFAULT, M_RESULT);//绘制中间点
MmeasDraw(M_DEFAULT, m_milSingleMarker, m_milSingleOverlayBuf,
M_DRAW_POSITION+M_EDGE_FIRST+M_EDGE_SECOND, M_DEFAULT, M_RESULT);//绘制第一边缘和第二边缘点
CString csResult;
csResult.Format(TEXT("目标图像中Stripe的位置为(%.2f,%.2f)\n宽度为%.2f\n角度为%.2f\n"),
StripeCenterX, StripeCenterY,
StripeWidth,
StripeAngle);
MessageBox(csResult, TEXT("测量结果"));
}
(2).多角度测量
void CMeasureDlg::OnReadMulti()
{
// TODO: Add your control notification handler code here
if (M_NULL != m_milMultiBuf)
{
MbufFree(m_milMultiBuf);
m_milMultiBuf = M_NULL;
}
//导入图像
MbufRestore(TEXT(".\\Image\\chip.mim"), m_milSystem, &m_milMultiBuf);
//显示图像
MdispZoom(m_milDisplay, 0.8, 0.8);
MdispControl(m_milDisplay, M_CENTER_DISPLAY , M_ENABLE);
MdispSelectWindow(m_milDisplay, m_milMultiBuf, GetDlgItem(IDP_DISP_IMAGE)->GetSafeHwnd());
MdispControl(m_milDisplay, M_OVERLAY_CLEAR, M_DEFAULT);
}
void CMeasureDlg::OnSetMulti()
{
// TODO: Add your control notification handler code here
if (M_NULL != m_milMultiMarker)
{
MmeasFree(m_milMultiMarker);
m_milMultiMarker = M_NULL;
}
//分配Stripe Maker
MmeasAllocMarker(m_milSystem, M_STRIPE, M_DEFAULT, &m_milMultiMarker);
//设置Maker Box
MmeasSetMarker(m_milMultiMarker, M_BOX_ORIGIN, MULT_MEAS_BOX_POS_X, MULT_MEAS_BOX_POS_Y);
MmeasSetMarker(m_milMultiMarker, M_BOX_SIZE, MULT_MEAS_BOX_WIDTH, MULT_MEAS_BOX_HEIGHT);
//设置Maker Characteristics
MmeasSetMarker(m_milMultiMarker, M_NUMBER, MULT_STRIPES_NUMBER, M_NULL);//个数
MmeasSetMarker(m_milMultiMarker, M_POLARITY, MULT_STRIPES_POLARITY_LEFT,
MULT_STRIPES_POLARITY_RIGHT);//第一边缘为上升沿,第二边缘为下降沿
MmeasSetMarker(m_milMultiMarker, M_ORIENTATION, MULT_STRIPES_ORIENTATION, M_NULL);//竖直方向
//在图像的Overlay层上绘制Maker Box
MdispControl(m_milDisplay, M_OVERLAY, M_ENABLE);
MdispInquire(m_milDisplay, M_OVERLAY_ID, &m_milMultiOverlayBuf);
MdispControl(m_milDisplay, M_OVERLAY_CLEAR, M_DEFAULT);
MgraColor(M_DEFAULT, M_COLOR_RED);
MmeasDraw(M_DEFAULT, m_milMultiMarker, m_milMultiOverlayBuf, M_DRAW_BOX, M_DEFAULT, M_MARKER);
}
void CMeasureDlg::OnGetMulti()
{
// TODO: Add your control notification handler code here
//目标图像中寻找Maker,测量结果保存在Maker中
MmeasFindMarker(M_DEFAULT, m_milMultiBuf, m_milMultiMarker, M_POSITION + M_ANGLE + M_WIDTH);
//获得测量结果(位置、宽度、角度)
double MeanAngle, /* Stripe mean angle. */
MeanWidth, /* Stripe mean width. */
MeanSpacing; /* Stripe mean spacing. */
MmeasGetResult(m_milMultiMarker, M_ANGLE + M_MEAN, &MeanAngle, M_NULL);
MmeasGetResult(m_milMultiMarker, M_WIDTH + M_MEAN, &MeanWidth, M_NULL);
MmeasGetResult(m_milMultiMarker, M_SPACING + M_MEAN, &MeanSpacing, M_NULL);
//绘制 Maker Box
MgraColor(M_DEFAULT, M_COLOR_BLACK);
MdispControl(m_milDisplay, M_OVERLAY_CLEAR, M_DEFAULT);//清除显示OverLay层
MmeasDraw(M_DEFAULT, m_milMultiMarker, m_milMultiOverlayBuf, M_DRAW_BOX, M_DEFAULT, M_RESULT);
//绘制测量结果
MgraColor(M_DEFAULT, M_COLOR_YELLOW);
MmeasDraw(M_DEFAULT, m_milMultiMarker, m_milMultiOverlayBuf, M_DRAW_POSITION, M_ALL, M_RESULT);//Stripe 位置
CString csResult;
csResult.Format(TEXT("目标图像中Stripe的平均角度为%5.2f\n平均宽度为%5.2f\n平均间隔为%5.2f\n"),
MeanAngle,
MeanWidth,
MeanSpacing);
MessageBox(csResult, TEXT("测量结果"));
}