一步一步实现自己机器视觉软件中工具的制作和运作,从简单开始(以抓取矩形(gaugeRect)工具为demo,一)
我们的工具盒里有八个工具,我们以抓取矩形(gaugeRect或rectcaliper)工具,我通常称他为抓框工具,为demo(例子),一步一步展开,先看一看8个工具的样子:
我们先用小画家(mspaint.exe)制作一个51*32位图icon,存为RectCaliper1.png,样子如下:,当然放在debug文件中。
程序中加载步骤如下:
一,声明变量
public mgToolBox mytoolbox;//自制的工具盒
Bitmap[] bmp=null; //用来加载八个位图icon
Rectangle[] rcs = null;//八个位图icon显示的位置
二,初始化变量
mytoolbox = new mgToolBox();
mytoolbox.m_RoiBase1.ResetRc(new RectangleF(0, 0, 100, 133));//位图50*2=100,32*4=128;刚好8个工具
temp = System.Environment.CurrentDirectory;
........七个位图加载省略,七个Rectangle初始化省略
bmp[7] = (Bitmap)Bitmap.FromFile(temp + "\\RectCaliper1.png");//工具计算50*2=100,33*4=132,8个位置刚好
rcs[7] = new Rectangle((int)mytoolbox.m_RoiBase1.m_Center.X, (int)mytoolbox.m_RoiBase1.m_Center.Y + 33, 50, 33);
三,在界面画出来
Graphics g = e.Graphics;
Pen p = new Pen(Color.Green, 1);
mytoolbox.drawtoolbox(g, p);//你可以看到上面的8个矩形覆盖在8个位图上。便于鼠标点击定位。
.......省略七个显示
g.DrawImage(bmp[7], mytoolbox.m_RoiBase1.m_Center.X, mytoolbox.m_RoiBase1.m_Center.Y + 33);
看到这里,其他都明白,这个mytoolbox是什么鬼?这才是本节的重点,有些人或许已经猜到了,这不就是我们设计的线图像工具吗?只不过放了几张图片在里边,原来是横着的,现在站着就不认识了?是的,有这种猜测的,八九不离十,可以跳过此节了,
其实他还没有线图像工具复杂,只是一个感兴趣区域,分了八个等分。变化如下:
你看位图是51*32,而分配的长宽50*33,所以整体上看起来不规整。
我们先看一看mgToolBox类,其实就是MeGauging的工具盒(箱)的意思,类代码如下,:
public class mgToolBox : ROIsimple
{
public void DrawRectFrame(bool lbtn, PointF point)
{
if (lbtn)
{
switch (m_eHandle)
{
case E_HANDLES.E_HANDLE_INSIDE:
m_RoiBase1.Drag(point);
break;
default:
break;
}
}
else
{
m_eHandle = (E_HANDLES)IsPointInRect(point);
}
Insteadof((int)m_eHandle);
return;
}
public int IsPointInRect(PointF point)
{
m_RoiBase1.IsPointInRect(point);
}
public void drawtoolbox(Graphics g, Pen p)
{
m_RoiBase1.Draw(g, p);//画主框矩形
//以下画矩形框中八条线
g.DrawLine(p, m_RoiBase1.m_Center, new PointF(m_RoiBase1.m_Center.X, m_RoiBase1.m_Center.Y - 50-(float)16.5));
g.DrawLine(p, m_RoiBase1.m_Center, new PointF(m_RoiBase1.m_Center.X, m_RoiBase1.m_Center.Y + 50 + (float)16.5));
g.DrawLine(p, new PointF(m_RoiBase1.m_Center.X, m_RoiBase1.m_Center.Y-17-17),
new PointF(m_RoiBase1.m_Center.X+50, m_RoiBase1.m_Center.Y - 17-17));
g.DrawLine(p, new PointF(m_RoiBase1.m_Center.X, m_RoiBase1.m_Center.Y - 17-17),
new PointF(m_RoiBase1.m_Center.X - 50, m_RoiBase1.m_Center.Y - 17-17));
g.DrawLine(p, new PointF(m_RoiBase1.m_Center.X, m_RoiBase1.m_Center.Y +16-16-1),
new PointF(m_RoiBase1.m_Center.X+50, m_RoiBase1.m_Center.Y + 16-16-1));
g.DrawLine(p, new PointF(m_RoiBase1.m_Center.X, m_RoiBase1.m_Center.Y + 16-16-1),
new PointF(m_RoiBase1.m_Center.X- 50, m_RoiBase1.m_Center.Y + 16-16-1));
g.DrawLine(p, new PointF(m_RoiBase1.m_Center.X, m_RoiBase1.m_Center.Y + 16 +17),
new PointF(m_RoiBase1.m_Center.X + 50, m_RoiBase1.m_Center.Y + 16 +17));
g.DrawLine(p, new PointF(m_RoiBase1.m_Center.X, m_RoiBase1.m_Center.Y + 16 +17),
new PointF(m_RoiBase1.m_Center.X - 50, m_RoiBase1.m_Center.Y + 16 +17));
}
}
这个类,三个函数,第一这个工具盒只能拖动,第二,判断鼠标位置是否进入拖动位置,第三,划线分八框。
尽是无用功,我们可以让工具盒不动啊!发发恼骚可以,我们看看 ROIsimple类,我们尝试最少代码,如下:
public class ROIsimple
{
public RoiBase1 m_RoiBase1;//关键是这个
public E_HANDLES m_eHandle;
public Cursor m_cur;
public ROIsimple()
{
m_RoiBase1 = new RoiBase1();
m_cur = Cursors.Arrow;
}
public void Insteadof(int intcursor)//改变鼠标形状
{
switch (intcursor)
{
case (int)E_HANDLES.E_HANDLE_INSIDE:
m_cur = Cursors.SizeAll;
break;
default:
m_cur = Cursors.Arrow;
break;
}
return;
}
}
只有一个构造函数和一个insteadof函数,很明白,不解释,RoiBase1,我们尝试最少代码,如下:
/// <summary>
/// ////////winRectRoi
/// </summary>
public class RoiBase1
{
public RectangleF rcWin;
public PointF m_Center;
public RoiBase1()
{
rcWin = new RectangleF(100, 100, 100, 100);
m_Center.X = rcWin.Left + rcWin.Width / 2;
m_Center.Y = rcWin.Top + rcWin.Height / 2;
}
public void ResetRc(RectangleF rc)
{
rcWin = rc;
m_Center.X = rcWin.Left + rcWin.Width / 2;
m_Center.Y = rcWin.Top + rcWin.Height / 2;
}
public void Draw(Graphics g, Pen p)
{
g.DrawRectangle(p, rcWin.Left, rcWin.Top, rcWin.Width, rcWin.Height);
}
public int IsPointInRect(PointF point)
{
if (point.X <= m_Center.X + 5 && point.X >= m_Center.X - 5
&& point.Y >= m_Center.Y - 5 && point.Y <= m_Center.Y + 5)
{
return (int)E_HANDLES.E_HANDLE_INSIDE;
}
else
{
return 0;
}
}
public void Drag(PointF point)
{
float tempX = 0, tempY = 0;
tempX = point.X - m_Center.X;
tempY = point.Y - m_Center.Y;
m_Center.X = (float)point.X;
m_Center.Y = (float)point.Y;
rcWin = new RectangleF(rcWin.Left + tempX, rcWin.Top + tempY, rcWin.Width, rcWin.Height);
}
}
看上去很像纸老虎,不难,稍微用心,击破之。线图像工具都是从这里起步的,万事开头难。
好,可拖动的工具盒搞定,第八个加载的是rectcaliper,其他七个仿照加载,也可以参考“写给父亲的语音计算器(五)”,未完,待续...