勇哥花了点时间学习了一下工业相机镜头的各类参数与选型原则。
成果就放在下面的程序里了。(程序需要安装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
版权声明:本文为博主原创文章,转载请附上博文链接!


少有人走的路



















