视场相关的类有两个CWindowDelegate和CRealView。 前者主要对xgui的功能接口进行了封装,后者继承了前者,增加了消息处理功能。这两个类都是从CDelegate继承。它们的继承关系如下:
CWindowDelegate m_dgt;
m_dgt.Initialize(m_hWnd);
在初始化完成以后,可以设置显示模式,显示比例,如:m_dgt.SetViewMode(CWindowDelegate:: VM_STRETCH);
然后设置其它显示内容输出:m_dgt. SetBlankColor(GRGB(0,0,0));
m_dgt. SetRvbLogoVisible(FALSE);
使用完成以后,进行销毁:m_dgt.Finalize();
当窗口进行显示的时候,如WM_PAINT消息里面,按照下面方式进行绘制:m_dgt.Refresh(CWindowDelegate::RT_REALIZE);
如果要显示用户控件:
m_dgt.AddUC(pObj);
该用户控件就会被显示到窗口上。如果需要移除用户控件,直接调用RemoveUC或RemoveAll函数进行移除。当然别忘了直接或间接地使用Refresh(CDelegate::RT_REDRAW)对窗口显示进行刷新。
如果作为相机图像显示的类,应用程序可以一般需要使用下面的方式进行:
m_dgt.SetSightFormat(RIT_RGB, 320,240);
m_dgt. FeedFrame(image, TRUE);
前一条语句设置视场的格式,参数包括图像类型,图像宽度,图像高度。图像类型支持RIT_BIN,RIT_GRAY,RIT_RGB,RIT_RGBA。设置完成后,后一个函数可以将实时采集的图像不断地输入给该类进行显示。(注意 : FeedFrame的输入的图像格式必须与视场支持的格式严格相同,如宽度,高度等)。
同样,用户程序可以使用GetCurFrame来获得当前的帧图像。
CWindowDelegate提供函数可以将绘制结果直接输出到图像对象,类似WINDOWS系统的窗口拷贝。如:
m_dgt.SaveCanvas(image);
如果image可以为RIT_RGB或RIT_RGBA.
在不同的显示模式下面,可能视场的显示边界超出了窗口本身的显示区域,这样需要移动视场,来进行部分显示。方法如下:
GSize sze =m_dgt. GetScrollBarRange();
m_dgt. SetScrollBarPos(12, FALSE);第1条语句获得水品和垂直方向的移动范围,后面的语句设置水平方向显示的当前左上角的显示位置。注意,该位置不能超出前一条语句返回的大小。
CRealView m_editor;
//执行模块里面
CRect rect;
GetDlgItem(IDC_STATIC_PREVIEW)->GetWindowRect(&rect);
ScreenToClient(&rect);
BOOL ret= m_editor.Create(m_hWnd, "my_ real_view", -1,-1, GRECT(rect.left, rect.top, rect.right, rect.bottom));
然后进行相关显示内容的调整,如调整RVB标识的显示位置,背景的风格,像素信息栏的颜色,用户鼠标的颜色等等: m_editor.SetRvbLogoAlignment(CWindowDelegate::LA_RIGHTTOP);m_editor.SetBackgroundStyle(CWindowDelegate::BS_WHITE);
m_editor.SetPixelBarColor(GRGB(255,0,0));
m_editor.SetUserCursorColor(GRGB(0,0,255));
如果需要隐藏RVB标识, 添加下的语句:m_editor.SetRvbLogoVisible(FALSE);
上面的函数全部运行以后,调用下面的语句将绘制结果显示出来m_editor.Refresh(CDelegate::RT_REDRAW);
注意:有些显示内容无法在设计状态下显示。当使用完成以后,需要进行销毁
m_editor.Destroy();
CRealView有两种模式:设计模式和运行模式。两种模式的消息相应是不一样的。设计模式下,用户可以添加各种用户控件。可以拖动控件,改变位置或控件的大小。运行模式下,控件是锁定的。无法改变大小或位置。
下面的语句将编辑窗口的模式变为设计状态:m_editor.SetDesignMode(CDelegate::DM_DESIGN);
CRealView提供了多种非标准鼠标,如目标指定鼠标,十字鼠标,甚至有支持窗口十字刻度。这些功能通过一个函数即可实现,如下:
m_editor.SetUserCursorType(CRealView::UC_PENTIP);
该语句将当前的用户鼠标设置成笔尖状鼠标。其它形状的鼠标对应的参数如下:
形状 | 参数 | 说明 |
---|---|---|
忽略 | UC_IGNORE | 使用用户默认鼠标 |
笔尖 | UC_PENTIP | |
圆形目标 | UC_TAR_S | |
方形目标 | UC_TAR_R | |
十字线 | UC_CROSS | |
水平刻度 | UC_RULER_H | 固定将刻度线显示在窗口,鼠标为系统默认鼠标 |
垂直刻度 | UC_RULER_V | 固定将刻度线显示在窗口,鼠标为系统默认鼠标 |
十字刻度 | UC_RULER_HV | 固定将刻度线显示在窗口,鼠标为系统默认鼠标 |
用户自定义图像 | UC_IMAGE |
if (IE_REPAIR == m_nType)
{
ClearCanvas();
if (m_bFeeded){
rvgPaintImage(m_dc, m_imCurFrame);
}
ASSERT(m_imRepair);
rvgDrawImage(m_dc, m_imRepair);
CWindowDelegate::Refresh(RT_REALIZE);
}
else{
CRealView::Refresh(type);
}
默认情况下,CRealView可以支持部分系统消息,支持内部功能的实现。为了响应不同的WINDOWS消息,提供灵活的控制手段,用户可以重载MsgProc函数。很多情况下,用户会从CRealView继承一个新类,然后重载MsgProc函数,实现灵活的消息响应。 除了WINDOWS消息,CRealView本身也会提供一些自定义的事件,用户可以重载EventProc来进行响应。CAreaCal
面量规类为通用的一个类,该类不提供具体的视觉分析功能,仅仅表示一个ROI形状,如圆形,方形,半环形,通常作为基类存在。如改变一个实例的形状代码如下:CAreaCal myCal ;
myCal .SetShape(CAreaCal:: CS_EX_CIRCLE);
需要获得实例对应的图象,如下:RvImage im = myCal.GetImage();
注意该图象仅为一个指针,由类本身进行销毁。作为辅助,面量规类提供了两个图象转换函数,即将图象从RVB转成灰度图或将灰度图转成二元图。这些转换分别有不同的转换方法。
CCurveCal
线量规为线状ROI,沿不同的曲线路径获取其像素,通常用于图象属性或特征分析。与面量规不同的是,线量规不提供格式转换或图象预处理。线量规根据曲线不同分为圆,弧,星状,同心圆等。 一些基本的形状特被用于加工视觉引导系统里面。CBlobExtractor
该类为BLOB提取类,主要对二元图象中的不连接的块图象进行分离,然后可以获取独立的BLOB对象,进行特性分析。该类可以用于记数或开发更具体要求的功能类。 下面的代码演示了,一个实例从获取ROI图象,设置各种分离参数,然后进行分离并筛选的过程。 m_blobExtractor.Shot(m_image); m_blobExtractor.m_nThresLower = m_nLower; m_blobExtractor.m_nThresUpper = m_nUpper; m_blobExtractor.m_bReverseBin = m_bInvert; m_blobExtractor.m_bCutEdge = m_bCutEdge;m_blobExtractor.m_bFillHole =m_bFillHoles;
m_blobExtractor.m_nEdgeSense = 5.8f;m_blobExtractor.m_nMakeReal = CBlobExtractor::BE_MR_DFEL
m_blobExtractor.m_nMinBlobWidth =6;
m_blobExtractor.m_nMinBlobHeight =6;
m_blobExtractor.Segment();
m_blobExtractor.Select(m_nMinSize);
CPatternLocater
该类为模板定位类,即将事先学习的模板与ROI的图进行匹配,找出最佳位置。类实例在使用的需要先学习,然后进行识别。CPatternLocater m_pd;
m_pd.Shot(m_image);
if (m_pd.Learn())
{m_pd.DumpPatterns("temp");
}
m_pd.SetInitScore(m_nInitScore);
m_pd.SetMinScore(m_nMinScore);
m_pd.m_nDirect = m_nDirectIndex;
int n= m_pd.Recognize(m_image);
上面的代码演示了学习模板,并将模板图输出到temp目录下面,然后按照指定的识别方向进行定位。CPixelMatch
该类使用相关性分析的方法,将模板图象与场景图象进行相关性分析,找出一个或多个模板实例。该类为通用的图象匹配类,支持旋转,缩放。m_pm.m_nStartAngle = m_startAngle;
m_pm.m_nEndAngle =m_endAngle;
m_pm.SetAngleResolution( m_nAngleRes);
m_pm.SetScaleResolutionn(m_nScaleReso);
m_pm.SetMinScale( m_nMinScale);
m_pm.SetMaxScale (m_nMaxScale);
m_pm.SetMinScaleX ( m_nMinScaleX);
m_pm.SetMaxScaleX (m_nMaxScaleX);
m_pm.SetMinScaleY (m_nMinScaleY);
m_pm.SetMaxScaleY (m_nMaxScaleY);
m_pm.m_bAnisoScale = m_bAnisoScale;
m_pm.Shot(m_image);
if (m_pm.Learn())
{
m_pm.DumpPatterns("temp");
}
m_pm.SetMaxInitInstances(m_nMaxInitPositions);m_pm.SetMaxInstances( m_nMaxPosition);
m_pm.SetInitScore(m_nInitScore);
m_pm.SetMinScore(m_nMinScore);
m_pm.m_nDirect = m_nDirectIndex;
int n= m_pm.Recognize(m_image);
if (n > 0)
{
ASSERT(n == m_pm.GetResultCount());
CString str;
m_strOutput.Format("找¨°到Ì?的Ì?数ºy量¢?:êo%d\r\n", n);
for (int i=0 ; i< n; i++){
str.Format("scale_x=%f, scale_y=%f, angle=%f, cx = %f, cy=%f, score=%f\r\n", \ m_pm.GetMatchResult(i)->scaleX, \ m_pm.GetMatchResult(i)->scaleY, \ m_pm.GetMatchResult(i)->angle, \ m_pm.GetMatchResult(i)->cx, \ m_pm.GetMatchResult(i)->cy, \ m_pm.GetMatchResult(i)->score );
m_strOutput += str;
}
}
上面的代码演示了学习模板,和实例查找的所有过程。 CDualDetect 该类从cpixelmatch类继承,进行双态的识别,如正反,左右,黑白等。在使用过程中,需要进行两次模板学习。识别完成以后,给出正反或缺失情况的结果。 m_dd.m_nStartAngle = 0; m_dd.m_nEndAngle = 360; m_dd.SetAngleResolution(3) ;m_dd.Shot(m_image);
if (m_dd.LearnOne())
{
m_dd.DumpPatterns("temp");
}
CEasyOcr
该类提供一个简单的使用最近距离方法进行字符识别。与模板匹配一样,需要事先进行学习。该类可以识别多个字符。
在学习之前,需要将字符分隔出来。 m_easyOcr.SetPatternWidth( m_nPattWidth); m_easyOcr.SetPatternHeight( m_nPattHeight); m_easyOcr.m_nMaxCharWidth = m_nMaxWidth; m_easyOcr.m_nMaxCharHeight = m_nMaxHeight;m_easyOcr.m_nMinCharWidth = m_nMinWidth;
m_easyOcr.m_nMinCharHeight = m_nMinHeight;
m_easyOcr.m_nCharSpacing =m_nCharSpace;
m_easyOcr.m_bRemoveNarrowOrFlat = m_bRemoveSmall;
m_easyOcr.m_bKeepRawBlob = m_bUseRaw;
m_easyOcr.m_bCheckAnisoRatio = m_bCheckAnisoRatio;
if (m_nTextColorIndex == 0) m_easyOcr.m_nCharColor = CEasyOcr::EO_WHITE_ON_BLACK;
else m_easyOcr.m_nCharColor = CEasyOcr::EO_BLACK_ON_WHITE;
int n = m_easyOcr.Build();
然后,进行字符学习,每次学习一个字符,如:m_easyOcr.Learn(m_nBlobIndex, -1, ‘A’);
学习完成以后,对新的视场图象里面的内容进行识别:m_easyOcr.m_nMinScore =m_nScore;
m_easyOcr.Build();int n = m_easyOcr.Recognize(-1);
char buff[2] ={0,0};
//CString tmp;
m_strResult.Empty();
for (int i=0; i< n; i++)
{
int ch = m_easyOcr.GetCharAt(i);
buff[0] =(char)ch;
m_strResult += buff;
}
CBarcode条码读取类可以识别一维码和二维码。不需要事先学习,支持360度旋转,可以同时识别多个条码。 如:
m_barcode.Shot(m_image);
m_barcode.m_bRotation =TRUE;
m_barcode.m_nMinWidth = (RV_MIN( rviGetWidth(m_image), rviGetHeight(m_image))/ 8 -2);
m_barcode.m_nMinHeight = m_barcode.m_nMinWidth ;
m_barcode.Read2D();
m_strOutput = "";for(int i=0; i< m_barcode.GetReadingCount(); i++)
{
const char* pTxtShow = m_barcode.GetReadingAt(i);
m_strOutput += pTxtShow;
m_strOutput +="\r\n";
}
上面的代码将图象中的二维条码识别出来。具体支持的条码类型请参考附表6。检测相关的类目前大部分从CAreaCal类继承,该类也是从CCaliber继承。这个类主要实现产生不同形状的ROI,如果形状满足要求,新的功能类可以直接从该类继承产生,然后实现新的功能需求即可。
CLabel* pLabel = new CLabel;
ASSERT(pLabel);
ASSERT(pLabel);
int my_id = rand();
pLabel->Create((CDelegate*)&m_sight , "my_label", my_id,RV_UCS_ENABLE | RV_UCS_VISIBLE);
pLabel->SetURLText("www.kingpool.net");
pLabel->m_bActiveURL = TRUE;
m_sight.AddUC(pLabel);
m_sight.AddUC(pLabel);
m_sight.Refresh(CDelegate::RT_REDRAW);
抖音视频号: 第一感机器视觉
微信公众号: 精浦科技
深圳市软云动力科技有限公司
东莞办事处: 广东省东莞市松湖智谷B6栋225b
公司地址: 广东省深圳市南山区桃园路金桃园大厦2191
深圳市软云动力科技有限公司 版权所有 鄂ICP备2022015826号-2