勇哥花了点时间学习了一下工业相机镜头的各类参数与选型原则。
成果就放在下面的程序里了。(程序需要安装netMarketing类库)
程序只是验证了一下部分的计算公式,所以不要拿来做项目的选型,错了勇哥可不负责任哦,仅供学习选型知识时做参考。
我会在实际项目中完善这个程序,让它变得实用起来。
几点说明:
Sensor长度与高度,跟相机芯片尺寸是一个东西,只不过相机芯片尺寸在商家的相机参数页面上见得多,它可以查表方式转为Sensor长度与高度。
这个选型软件还没有考虑景深的需求,在实际选型中这个也是重要的参数,还需要再完善。
靶面尺寸其实就是Sensor的长宽。
工作距离也叫物距。
视野长宽,与叫视场长宽。
定焦镜头那个示焦环(也可以叫聚焦环,勇哥叫法)不是用来调整焦距,而是调整像距的,保证清晰图像落在焦平面上,如果能调焦距的话,镜头就不叫定焦镜头了。
程序源码比较简单,勇哥就不废话了。
有疑问可以留言。
using sharClass; 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; namespace lens { public partial class Form1 : Form { psetting pset = new psetting(); public string[] caltypeEnumExplain = new string[] { "焦距f = 工作距离WD × 靶面尺寸( H or V) / FOV( H or V)", "(一式)视场FOV( H or V) = WD × 靶面尺寸( H or V) / 焦距f\r\n(二式)视场FOV( H or V) = 靶面尺寸( H or V) / 光学倍率", "(一式)视场FOV( H or V) = WD × 靶面尺寸( H or V) / 焦距f\r\n(二式)视场FOV( H or V) = 靶面尺寸( H or V) / 光学倍率", "工作距离WD = f(焦距)× 靶面尺寸/FOV( H or V)", "光学倍率 = 靶面尺寸( H or V) / FOV( H or V)", "求靶面尺寸H", "求靶面尺寸V", "求像元尺寸H", "求像元尺寸V", "计算求sensor尺寸H", "计算求sensor尺寸V", "已知视野_工作距离_相机求镜头", "已知视野_工作距离求相机", "已知镜头_工作距离求相机", "求最小相机精度(多少万像素的相机),需要用户参数:视野长边,视野短边,精度mm,边缘像素数量", "已知物距_视野长度_相机分辨率_相机像元大小求焦距" }; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { pset.Load(); propertyGrid1.SelectedObject = null; propertyGrid1.SelectedObject = pset; comboBox1.Items.AddRange(new enumHelper<caltypeEnum>().getEnumItemArray()); } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { if(comboBox1.SelectedIndex>=0) { richTextBox2.Text = caltypeEnumExplain[comboBox1.SelectedIndex]; } } private void button2_Click(object sender, EventArgs e) { MessageBox.Show( pset.Save()?"保存成功":"保存失败"); } private void button1_Click(object sender, EventArgs e) { try { //计算 switch (comboBox1.SelectedIndex) { case 0: //求焦距f richTextBox1.AppendText(string.Format("焦距:{0}\r\n", 求焦距f(pset, true))); richTextBox1.AppendText(string.Format("焦距:{0}\r\n", 求焦距f(pset, false))); break; case 1: //求视场FovH richTextBox1.AppendText(string.Format("视场FovH:{0}\r\n", 求视场FOV(pset, true))); break; case 2: //求视场FovV richTextBox1.AppendText(string.Format("视场FovV:{0}\r\n", 求视场FOV(pset, false))); break; case 3: //求工作距离WD richTextBox1.AppendText(string.Format("工作距离WD:{0}\r\n", 求工作距离WD(pset))); break; case 4: //求光学倍率 richTextBox1.AppendText(string.Format("光学倍率:{0}\r\n", 求光学倍率(pset) )); break; case 5: //求靶面尺寸H richTextBox1.AppendText(string.Format("由相机芯片尺寸查表求靶面尺寸H:{0}\r\n", 查表取靶面尺寸(pset).Item1)); break; case 6: //求靶面尺寸V richTextBox1.AppendText(string.Format("由相机芯片尺寸查表求靶面尺寸V:{0}\r\n", 查表取靶面尺寸(pset).Item2)); break; case 7: //求像元尺寸H richTextBox1.AppendText(string.Format("像元尺寸H:{0}um\r\n", 求像元尺寸(pset).Item1)); break; case 8: //求像元尺寸V richTextBox1.AppendText(string.Format("像元尺寸V:{0}um\r\n", 求像元尺寸(pset).Item2)); break; case 9: //计算求sensor尺寸H richTextBox1.AppendText(string.Format("计算求Sensor尺寸H:{0}mm\r\n", 求Sensor长宽尺寸(pset).Item1)); break; case 10: //计算求sensor尺寸V richTextBox1.AppendText(string.Format("计算求Sensor尺寸V:{0}mm\r\n", 求Sensor长宽尺寸(pset).Item2)); break; case 11: //已知视野_工作距离_相机求镜头 break; case 12: break; case 13: //已知镜头_工作距离求相机 richTextBox1.AppendText(string.Format("视野长边短边:{0}mm\r\n工作距离:{1}mm\r\n边缘像素数量:{2}\r\n求出相机分辩率为:{3}万像素", pset.视野长边 + "," + pset.视野短边, pset.工作距离, pset.边缘像素数量, 求相机最小精度(pset).Item3)); break; case 14: //相机最小精度 richTextBox1.AppendText(string.Format("求相机最小精度:{0}万像素\r\n", 求相机最小精度(pset).Item3)); break; case 15: //已知物距_视野长度_相机分辨率_相机像元大小求焦距 var sensorH= pset.水平分辨率*pset.像元尺寸H/1000; var sensorV=pset.垂直分辨率*pset.像元尺寸V/1000; var scale=sensorH/pset.视野长边; var 焦距=pset.工作距离*scale; var 实际光学放大倍率=焦距 / pset.工作距离; richTextBox1.AppendText( string.Format("物距:{0}mm\r\n视野长边:{1}mm\r\n相机水平分辨率:{2}\r\n相机水平像元:{3}\r\nSensor长度:{4}\r\n光学放大倍率:{5}\r\n求出镜头的焦距为:{6}mm\r\n实际光学放大倍率为:{7}\r\n视野长度:{8}\r\n视野高度:{9}", pset.工作距离, pset.视野长边, pset.水平分辨率, pset.像元尺寸H, sensorH, scale, 焦距, 实际光学放大倍率, sensorH / 实际光学放大倍率, sensorV / 实际光学放大倍率 )); break; } } catch(Exception ex) { MessageBox.Show(ex.Message); } } /// <summary> /// 求像元尺寸 /// </summary> /// <param name="config"></param> /// <returns></returns> public Tuple<double,double> 求像元尺寸(psetting config) { if (config.Sensor长度 <= 0 || config.水平分辨率 <= 0 || config.Senso高度 <= 0 || config.垂直分辨率 <= 0) throw new ArgumentException("函数求要提供硬件参数:[Sensor长度,Senso高度,水平分辨率,垂直分辨率],请检查这些参数是否有误!"); Tuple<double, double> res = new Tuple<double, double>(0, 0); res = new Tuple<double, double>((config.Sensor长度 / config.水平分辨率)*1000, (config.Senso高度 / config.垂直分辨率)*1000); return res; } /// <summary> /// 求Sensor长宽尺寸 /// </summary> /// <param name="config"></param> /// <returns>Sensor长、宽</returns> public Tuple<double, double> 求Sensor长宽尺寸(psetting config) { if (config.水平分辨率 <= 0 || config.垂直分辨率 <= 0 || config.像元尺寸H <= 0 || config.像元尺寸V <= 0) throw new ArgumentException("函数求要提供硬件参数:[水平分辨率,垂直分辨率,像元尺寸H,像元尺寸V],请检查这些参数是否有误!"); Tuple<double, double> res = new Tuple<double, double>(0, 0); res = new Tuple<double, double>(config.水平分辨率* config.像元尺寸H/1000.0, config.垂直分辨率 * config.像元尺寸V/1000.0); return res; } /// <summary> /// 求相机最小精度 /// </summary> /// <param name="config"></param> /// <returns>水平方向H最小精度,垂直方向V最小精度,最小精度为多少万像素</returns> public Tuple<double,double,double> 求相机最小精度(psetting config) { if (config.视野长边 <= 0 || config.视野短边 <= 0 || config.精度mm <= 0 || config.边缘像素数量<=0) throw new ArgumentException("本函数用户需要提供参数:[视野长边,视野短边,精度mm,边缘像素数量],请检查这些参数是否有问题!"); Tuple<double, double,double> res = new Tuple<double, double,double>(0, 0,0); res = new Tuple<double, double, double>(config.视野长边 / config.精度mm, config.视野短边 / config.精度mm, ((config.视野长边 / config.精度mm) * (config.视野短边 / config.精度mm)*config.边缘像素数量) / 10000.0); return res; } /// <summary> /// 查表取靶面尺寸,这个值由相机芯片尺寸查表取得,非计算取得 /// </summary> /// <param name="config"></param> /// <returns>返回靶面H,靶面V</returns> public Tuple<double, double> 查表取靶面尺寸(psetting config) { Tuple<double, double> res=new Tuple<double,double>(0,0); if(config.相机芯片尺寸== SensorSizeEnum.一英寸) { res = new Tuple<double, double>(12, 12); } else if (config.相机芯片尺寸 == SensorSizeEnum.一点八分之一英寸) { res = new Tuple<double, double>(7.2, 5.4); } else if (config.相机芯片尺寸 == SensorSizeEnum.四分之一英寸) { res = new Tuple<double, double>(3.2, 2.4); } else if (config.相机芯片尺寸 == SensorSizeEnum.三分之一英寸) { res = new Tuple<double, double>(4.8, 3.6); } else if (config.相机芯片尺寸 == SensorSizeEnum.三分之二英寸) { res = new Tuple<double, double>(8.8, 6.6); } else if (config.相机芯片尺寸 == SensorSizeEnum.二点五分之一英寸) { res = new Tuple<double, double>(5.7, 4.3); } return res; } /// <summary> /// 求焦距f /// </summary> /// <param name="config"></param> /// <param name="isH">默认使用靶面尺寸H参加计算</param> /// <returns></returns> public double 求焦距f(psetting config, bool isH = true) { if (config.工作距离 <= 0 || config.视野长边 <= 0 || config.视野短边 <= 0) throw new ArgumentException("本函数需要用户提供参数:[工作距离,视野长边,视野长边,视野短边],请检查这些参数是否有误!"); double res = 0; if (isH) res = config.工作距离 * (查表取靶面尺寸(config).Item1 / config.视野长边); // 求视场FOV(config)); else res = config.工作距离 * (查表取靶面尺寸(config).Item2 / config.视野短边); // 求视场FOV(config, false)); return res; } /// <summary> /// /// </summary> /// <param name="config"></param> /// <param name="求FOVH">真则求fovH,否则求fovV</param> /// <param name="公式1">真则使用公式1,否则使用公式2</param> /// <returns></returns> public double 求视场FOV(psetting config,bool 求FOVH=true, bool 公式1=true) { double res = 0; if (求FOVH) { if(公式1) { res = config.工作距离 * 查表取靶面尺寸(config).Item1 / config.焦距mm; } else { res = 查表取靶面尺寸(config).Item1 / 求光学倍率(config); } } else { if(公式1) { res = config.工作距离 * 查表取靶面尺寸(config).Item2 / config.焦距mm; } else { res = 查表取靶面尺寸(config).Item2 / 求光学倍率(config); ; } } return res; } /// <summary> /// 求光学倍率 /// </summary> /// <param name="config"></param> /// <param name="isH">默认使用靶面尺寸H参加计算</param> /// <returns></returns> public double 求光学倍率(psetting config,bool isH = true) { double res=0; if (isH) res = 查表取靶面尺寸(config).Item1 / config.视野长边; else res = 查表取靶面尺寸(config).Item2 / config.视野短边; return res; } /// <summary> /// 求工作距离WD /// </summary> /// <param name="config"></param> /// <param name="isH">默认使用靶面尺寸H参加计算</param> /// <returns></returns> public double 求工作距离WD(psetting config, bool isH = true) { double res = 0; if (isH) res = 求焦距f(config) * (查表取靶面尺寸(config).Item1 / config.视野长边); else res = 求焦距f(config) * (查表取靶面尺寸(config).Item2 / config.视野短边); return res; } } public enum caltypeEnum { 求焦距f, 求视场FovH, 求视场FovV, 求工作距离WD, 求光学倍率, 求靶面尺寸H, 求靶面尺寸V, 求像元尺寸H, 求像元尺寸V, 计算求sensor尺寸H, 计算求sensor尺寸V, 已知视野_工作距离_相机求镜头, 已知视野_工作距离求相机, 已知镜头_工作距离求相机, 相机最小精度, 已知物距_视野长度_相机分辨率_相机像元大小求焦距 } public enum SensorSizeEnum { 四分之一英寸, 三分之一英寸, 二点五分之一英寸, 一点八分之一英寸, 三分之二英寸, 一英寸 } public class psetting:Settings { [Config, Description("Sensor长度"), Category("相机硬件参数"), DefaultValue("")] public double Sensor长度 { get; set; } [Config, Description("Sensor高度"), Category("相机硬件参数"), DefaultValue("")] public double Senso高度 { get; set; } [Config, Description("相机芯片尺寸"), Category("相机硬件参数"), DefaultValue("")] public SensorSizeEnum 相机芯片尺寸 { get; set; } [Config, Description("像元尺寸H"), Category("相机硬件参数"), DefaultValue("")] public double 像元尺寸H { get; set; } [Config, Description("像元尺寸V"), Category("相机硬件参数"), DefaultValue("")] public double 像元尺寸V { get; set; } [Config, Description("水平分辨率"), Category("相机硬件参数"), DefaultValue("")] public int 水平分辨率 { get; set; } [Config, Description("垂直分辨率"), Category("相机硬件参数"), DefaultValue("")] public int 垂直分辨率 { get; set; } [Config, Description("焦距mm"), Category("镜头硬件参数"), DefaultValue("")] public double 焦距mm { get; set; } [Config, Description("最大光圈"), Category("镜头硬件参数"), DefaultValue("")] public double 最大光圈 { get; set; } [Config, Description("最小光圈"), Category("镜头硬件参数"), DefaultValue("")] public double 最小光圈 { get; set; } [Config, Description("像面尺寸(inch)"), Category("镜头硬件参数"), DefaultValue("")] public SensorSizeEnum 像面尺寸 { get; set; } [Config, Description("分辨率M"), Category("镜头硬件参数"), DefaultValue("")] public string 分辨率M { get; set; } [Config, Description("视野长边"), Category("用户需求参数"), DefaultValue("")] public double 视野长边 { get; set; } [Config, Description("视野短边"), Category("用户需求参数"), DefaultValue("")] public double 视野短边 { get; set; } [Config, Description("工作距离"), Category("用户需求参数"), DefaultValue("")] public double 工作距离 { get; set; } [Config, Description("精度mm"), Category("用户需求参数"), DefaultValue("")] public double 精度mm { get; set; } [Config, Description("边缘像素数量"), Category("用户需求参数"), DefaultValue("")] public double 边缘像素数量 { get; set; } } }
《本文源代码下载》
有关选型的知识,勇哥收集了一下本站的相关贴子如下:
《远心镜头原理及使用范围 》
《如何测试成像畸变? 》
《勇哥的视觉实验:工业相机镜头焦距、工作距离、视野等选型的计算 》
《远心镜头的十大参数介绍 》
《远心镜头的原理及选型 》
《视觉硬件:镜头的选型知识 》
《工业相机、镜头的选型 》
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!

