本文将通过Visual Studio 2019运行VisionPro软件计算旋转中心,可用于旋转标定。
前期准备
程序框架
引用内容
窗体设计
程序设计
运行结果
首次在Visual Studio进行二次开发时,工具箱中不包含VisionPro中工具的控件,需要手动添加控件到工具箱中,具体参考VisionPro二次开发——C#显示卡尺极性 。
MainForm窗体为主窗体,ToolBlockForm窗体用于显示工具块VPP,FitCircleToolForm用于显示拟合圆工具的结果。
使用VisionPro软件中封装的工具必须添加对应的引用才能添加对应的命名空间,具体操作如下:
点击添加引用后选择以下引用:
<不推荐将全部与VisionPro相关的引用都添加,这样会造成程序占用空间非常的大>
<最好的方法是需要一个添加一个>
其中cogRecordDisplay控件用于显示拟合圆的结果图像,TabelLayoutPanel控件用于调整窗体控件的布局,具体可看C#控件自适应布局。
其中cogToolBlockEdit控件用于显示ToolBlock工具,并可以编辑,运行,保存等。
其中cogToolBlockEdit控件用于显示FitCircle工具,并可以设置,查看结果,运行等。
Step1 点击编辑图像按键后,打开选择图像窗体,并将图像路径存储
/* 当点击编辑图像按键时运行 */
private void btnPicture_Click(object sender, EventArgs e)
{
/* using完后空间会被释放 */
using (OpenFileDialog ofd = new OpenFileDialog()) //ofd类
{
ofd.Title = "编辑图像"; //窗口名
ofd.InitialDirectory = @"D:\"; //打开的路径
ofd.Multiselect = true; //是否允许多选
ofd.Filter = "图像文件|*.JPG"; //支持的文件格式
ofd.ShowDialog(); //打开选择窗口
picPath = ofd.FileNames; //将图片路径保存到数组中
}
}
Step2 点击编辑VPP按键后,打开ToolBlockForm窗体
/* 当点击编辑VPP按键时运行 */
private void btnSettingVPP_Click(object sender, EventArgs e)
{
ToolBlockForm toolBlockForm = new ToolBlockForm(mToolBlock);
toolBlockForm.ShowDialog(); //打开ToolBlockForm窗体
}
Step3 点击运行VPP按键后,将每次ToolBlock定位的点传入到FitCircleTool中,利用这些点拟合出圆,并将圆心即旋转中心的坐标显示到MainForm主窗体中
/* 当点击运行VPP按键时运行 */
private void btnRunVPP_Click(object sender, EventArgs e)
{
mFitCircle.RunParams.NumPoints = picPath.Length; //拟合圆的点数
Point[] point = new Point[picPath.Length];
/* 方法一:拟合圆工具计算旋转中心 */
for (int pointIndex = 0; pointIndex < mFitCircle.RunParams.NumPoints; pointIndex++)
{
mImageFileTool.Operator.Open(picPath[pointIndex], CogImageFileModeConstants.Read); //利用图像文件工具打开文件夹中的图像
/// 参数1:图像路径,参数2:运行模式
mImageFileTool.Run(); //运行图像文件工具
mToolBlock.Inputs["Image"].Value = mImageFileTool.OutputImage; //给工具块输入图像
mToolBlock.Run(); //运行工具块
mFitCircle.RunParams.SetPoint(pointIndex, (double)mToolBlock.Outputs["JiPianX"].Value, (double)mToolBlock.Outputs["JiPianY"].Value); //将工具块输出的点输入到拟合圆工具中
/// 参数1:第几个点,参数2:点的横坐标,参数3:点纵坐标
point[pointIndex].x = (double)mToolBlock.Outputs["JiPianX"].Value;
point[pointIndex].y = (double)mToolBlock.Outputs["JiPianY"].Value;
}
mFitCircle.InputImage = mImageFileTool.OutputImage; //将图像文件工具的最后一张输入到拟合圆工具中
mFitCircle.Run(); //运行拟合圆工具
/* 方法二:两点一角度计算旋转中心 */
//Point centerPoint = new Point();
//centerPoint = calCenter(point[0], point[1], 2.5);
cogRecordDisplay.Record = mFitCircle.CreateLastRunRecord().SubRecords["InputImage"]; //显示拟合圆工具的结果图像
fitXTextBox.Text = mFitCircle.Result.GetCircle().CenterX.ToString("F"); //显示利用拟合圆工具确定的旋转中心的横坐标X
fitYTextBox.Text = mFitCircle.Result.GetCircle().CenterY.ToString("F"); //显示利用拟合圆工具确定的旋转中心的纵坐标Y
}
<除了用FitCircle工具计算旋转中心以外可以用数学的方法计算旋转中心>
mFitCircle.RunParams.SetPoint(pointIndex, (double)mToolBlock.Outputs["JiPianX"].Value, (double)mToolBlock.Outputs["JiPianY"].Value); //将工具块输出的点输入到拟合圆工具中
其中利用YourToolBlock.Outputs["XXX"].Value来获取工具块的结果,工具块VPP设计如下,利用模板工具和定位工具定位特征,利用找线工具和交点工具获取点坐标,设计如下图所示:
Step4 点击查看标定按键后,打开FitCircleForm窗体
/* 当点击查看标定按键时运行 */
private void btnCheckCalib_Click(object sender, EventArgs e)
{
FitCircleToolForm fitCircleToolForm = new FitCircleToolForm(mFitCircle);
fitCircleToolForm.ShowDialog(); //打开FitCircleToolForm窗体
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Cognex.VisionPro;
using Cognex.VisionPro.ImageFile;
using Cognex.VisionPro.ToolBlock;
using Cognex.VisionPro.CalibFix;
using Cognex.VisionPro.Caliper;
namespace CenterCalib
{
public partial class MainForm : Form
{
/* 定义变量 */
public static string vppPath = "D:\\Code\\visionpro\\CenterCalib\\bin\\Debug\\CenterCalib.vpp"; //VPP保存路径
public string[] picPath = null; //数组保存图片路径
private static double theath = 1; //角度制
CogToolBlock mToolBlock = CogSerializer.LoadObjectFromFile(vppPath) as CogToolBlock; //实例化工具块
CogImageFileTool mImageFileTool = new CogImageFileTool(); //实例化图像文件工具
CogFitCircleTool mFitCircle = new CogFitCircleTool(); //实例化拟合圆工具
struct Point //定义结构体: 点
{
public double x;
public double y;
public Point(double _x,double _y) //有参构造函数
{
x = _x;
y = _y;
}
}
public MainForm()
{
InitializeComponent();
}
/* 当点击编辑图像按键时运行 */
private void btnPicture_Click(object sender, EventArgs e)
{
/* using完后空间会被释放 */
using (OpenFileDialog ofd = new OpenFileDialog()) //ofd类
{
ofd.Title = "编辑图像"; //窗口名
ofd.InitialDirectory = @"D:\"; //打开的路径
ofd.Multiselect = true; //是否允许多选
ofd.Filter = "图像文件|*.JPG"; //支持的文件格式
ofd.ShowDialog(); //打开选择窗口
picPath = ofd.FileNames; //将图片路径保存到数组中
}
}
/* 当点击编辑VPP按键时运行 */
private void btnSettingVPP_Click(object sender, EventArgs e)
{
ToolBlockForm toolBlockForm = new ToolBlockForm(mToolBlock);
toolBlockForm.ShowDialog(); //打开ToolBlockForm窗体
}
/* 当点击运行VPP按键时运行 */
private void btnRunVPP_Click(object sender, EventArgs e)
{
mFitCircle.RunParams.NumPoints = picPath.Length; //拟合圆的点数
Point[] point = new Point[picPath.Length];
/* 方法一:拟合圆工具计算旋转中心 */
for (int pointIndex = 0; pointIndex < mFitCircle.RunParams.NumPoints; pointIndex++)
{
mImageFileTool.Operator.Open(picPath[pointIndex], CogImageFileModeConstants.Read); //利用图像文件工具打开文件夹中的图像
/// 参数1:图像路径,参数2:运行模式
mImageFileTool.Run(); //运行图像文件工具
mToolBlock.Inputs["Image"].Value = mImageFileTool.OutputImage; //给工具块输入图像
mToolBlock.Run(); //运行工具块
mFitCircle.RunParams.SetPoint(pointIndex, (double)mToolBlock.Outputs["JiPianX"].Value, (double)mToolBlock.Outputs["JiPianY"].Value); //将工具块输出的点输入到拟合圆工具中
/// 参数1:第几个点,参数2:点的横坐标,参数3:点纵坐标
point[pointIndex].x = (double)mToolBlock.Outputs["JiPianX"].Value;
point[pointIndex].y = (double)mToolBlock.Outputs["JiPianY"].Value;
}
mFitCircle.InputImage = mImageFileTool.OutputImage; //将图像文件工具的最后一张输入到拟合圆工具中
mFitCircle.Run(); //运行拟合圆工具
/* 方法二:两点一角度计算旋转中心 */
//Point centerPoint = new Point();
//centerPoint = calCenter(point[0], point[1], 2.5);
cogRecordDisplay.Record = mFitCircle.CreateLastRunRecord().SubRecords["InputImage"]; //显示拟合圆工具的结果图像
fitXTextBox.Text = mFitCircle.Result.GetCircle().CenterX.ToString("F"); //显示利用拟合圆工具确定的旋转中心的横坐标X
fitYTextBox.Text = mFitCircle.Result.GetCircle().CenterY.ToString("F"); //显示利用拟合圆工具确定的旋转中心的纵坐标Y
}
/* 迭代法计算旋转中心 */
Point calCenter(Point point0, Point point1, double theath)
{
double distance = Math.Pow(Math.Pow(point1.x - point0.x, 2) + Math.Pow(point1.y - point0.y, 2), 0.5); //distance为两点之间的距离
double radius = (distance / 2) / Math.Sin(theath / 2);
double xt = (1 - radius / distance) * point0.x + (radius / distance) * point1.x; //xt为垂线段
double yt = (1 - radius / distance) * point1.y + (radius / distance) * point1.y; //yt为垂线段
double b = ((90.0 / 180) * Math.PI) - (theath / 2); //角度转换
Point centerPoint = new Point(Math.Round(-1*(Math.Cos(b) * (xt - point0.x) - Math.Sin(b) * (yt - point0.y) + point0.x), 3), Math.Round(Math.Cos(b) * (xt - point0.x) - Math.Sin(b) * (yt - point0.y) + point0.x, 3));
return centerPoint;
}
/* 当点击查看标定按键时运行 */
private void btnCheckCalib_Click(object sender, EventArgs e)
{
FitCircleToolForm fitCircleToolForm = new FitCircleToolForm(mFitCircle);
fitCircleToolForm.ShowDialog(); //打开FitCircleToolForm窗体
}
}
}
Step1 跨窗口传入参数,传入ToolBlock。
public ToolBlockForm(CogToolBlock tempToolBlock)
{
/* 跨窗口传入参数 */
mToolBlock = tempToolBlock; //工具块
InitializeComponent();
}
Step2 实例化工具块并显示到窗体中。
/* 当打开窗体时运行 */
private void ToolBlockForm_Load(object sender, EventArgs e)
{
cogToolBlockEdit.Subject = mToolBlock;
}
Step3 关闭窗体时,提示是否保存VPP。
/* 当关闭窗体时运行 */
private void ToolBlockForm_FormClosing(object sender, FormClosingEventArgs e)
{
DialogResult res = MessageBox.Show("是否保存?", "提示", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question); //保存结果信息
/// 参数1:显示文本,参数2:标题,参数3:按键类型,参数4:显示图标
if (res == DialogResult.Yes) //保存VPP
{
CogSerializer.SaveObjectToFile(cogToolBlockEdit.Subject, CenterCalib.MainForm.vppPath); //保存工具块
e.Cancel = false; //确认关闭窗体
}
else if (res == DialogResult.No) //不保存VPP
{
e.Cancel = false; //确认关闭窗体
}
else //取消
{
e.Cancel = true; //取消关闭窗体
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Cognex.VisionPro;
using Cognex.VisionPro.ToolBlock;
namespace CenterCalib
{
public partial class ToolBlockForm : Form
{
CogToolBlock mToolBlock;
public ToolBlockForm(CogToolBlock tempToolBlock)
{
/* 跨窗口传入参数 */
mToolBlock = tempToolBlock; //工具块
InitializeComponent();
}
/* 当打开窗体时运行 */
private void ToolBlockForm_Load(object sender, EventArgs e)
{
cogToolBlockEdit.Subject = mToolBlock;
}
/* 当关闭窗体时运行 */
private void ToolBlockForm_FormClosing(object sender, FormClosingEventArgs e)
{
DialogResult res = MessageBox.Show("是否保存?", "提示", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question); //保存结果信息
/// 参数1:显示文本,参数2:标题,参数3:按键类型,参数4:显示图标
if (res == DialogResult.Yes) //保存VPP
{
CogSerializer.SaveObjectToFile(cogToolBlockEdit.Subject, CenterCalib.MainForm.vppPath); //保存工具块
e.Cancel = false; //确认关闭窗体
}
else if (res == DialogResult.No) //不保存VPP
{
e.Cancel = false; //确认关闭窗体
}
else //取消
{
e.Cancel = true; //取消关闭窗体
}
}
}
}
Step1 跨窗口传入参数,传入ToolBlock。
public FitCircleToolForm(CogFitCircleTool tempFitCircleTool)
{
/* 跨窗口传入参数 */
mFitCircleTool = tempFitCircleTool; //拟合圆工具
InitializeComponent();
}
Step2 实例化拟合圆工具并显示到窗体中。
/* 当打开窗体时运行 */
private void FitCircleToolForm_Load(object sender, EventArgs e)
{
cogFitCircleEdit.Subject = mFitCircleTool;
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Cognex.VisionPro;
namespace CenterCalib
{
public partial class FitCircleToolForm : Form
{
CogFitCircleTool mFitCircleTool;
public FitCircleToolForm(CogFitCircleTool tempFitCircleTool)
{
/* 跨窗口传入参数 */
mFitCircleTool = tempFitCircleTool; //拟合圆工具
InitializeComponent();
}
/* 当打开窗体时运行 */
private void FitCircleToolForm_Load(object sender, EventArgs e)
{
cogFitCircleEdit.Subject = mFitCircleTool;
}
}
}