上节说过灰度匹配的鲁棒性太差,在定位一些特殊的简单特征时,使用单方向的灰度跳变特征(和边缘检测类似)来定位的鲁棒性较好,速度快。你可以定位指定的点、边、条纹三种特征,定位的两个特征的间距即为长度、宽度等特征,所以这个模块叫做测量模块。
使用MmeasAllocMarker函数来设置指定的特征,MIL支持三种特征:点(M_POINT),边(M_EDGE),条纹(M_STRIPE)
后两种特征如下:
选取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)。
使用MmeasSetMarker设置相关参数
设置搜索方向
使用参数M_ORIENTATION,可为水平或竖直或任意
设置其他值
使用MmeasFindMarker开启测量,使用MmeasGetResult得到各种测量结果。
可使用MmeasDraw绘制测量结果
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("测量结果")); }
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("测量结果")); }