在工业相机的深度应用的前三节里面,针对工业相机的选型、参数、应用计算等做了一些说明。
其中,在【深度3】里面,在说明工业相机在速度场景下的应用的时候,专门开了一节介绍线扫描相机【线阵相机】行频速度的计算公式和镜头的选型的大致说明,感觉说的还是不够透彻,应用举例也不充分,这里特别开一个章节,基于线扫描相机的特点对比面阵相机的特点进行比较详细的说明,尤其对线扫描相机的选型实践,线扫描相机的分辨率选择计算、行频选择计算进行了充分的说明和计算说明,希望能够给用到线扫描工业相机的同学给予一定的参考:
在编写这章之前,参阅了CSDN等不少博客,发现很多内容是重复的,甚至错误的,我之前在【深度3里面的一个例子也是摘抄了一篇博客的计算参数,我发现其实是错误的】,甚至在一些国外的线阵相机的官网也有类似的错误,导致在演算公式的时候百思不得其解,本文在提问环节会提出一些质疑算是对博客原创的一种尊重。
在前一节的线阵相机的讨论模型里面:【工业相机】【深度3】相机选择-精度和曝光需求计算 - 输入:1 被测试物体的最小体积 2 被测物体的移动相对速度_Franklin的博客-CSDN博客_相机选型精度计算方法
https://dimensionspacex.blog.csdn.net/article/details/113657634

现在看来有至少下列问题:
【Franklin案,这是一个很多博客采用的例子,可是,如果我们仔细计算,28K的行频其实是不能满足要求的】
如幅宽为1600毫米、精度1毫米、运动速度22000mm/s
相机:1600/1=1600像素
最少2000像素,选定为2k相机【案,2K = 2048】
1600/2048=0.8实际精度 【 = 0.78125】
22000mm/0.8mm=27.5KHz 【= 28160】
应选定相机为2048像素28kHz相机 【28K 其实还差一点】
【Franklin案,同样是这里例子】
如幅宽为1600毫米、精度1毫米、运动速度22000mm/s
相机:1600/1=1600像素【这里违反了那奎斯特的采样定理要求,要达到1mm的精度,你至少要在1mm的精度下有2到3倍的采样率,也就是1/3的采样精度要求,也即0.33mm】
1600 /1 *3 = 4800 pixel ,应该考虑4K的相机才对,
1600/4096=0.39 mm/pixel 实际精度 【注意单位】
22000mm/0.39mm=56410Hz = 56KHZ
应选定相机为4096像素57kHz相机
线阵相机的选型,其实并非只是计算一下线阵相机的最小测试精度+最小行频就完事了,针对不同的具体应用,线阵相机还有许多关键的因素需要考虑。
本节,从基本的要素出发,先从常规的考虑参数入手,并逐渐加深讨论的深度。
首先:要从被测的场景出发,包括:测试场景的光照情况(影响相机的曝光,QE等的选传感器选型)、测试场景的精度要求和被测物体的最小探测尺寸大小要求-比如探测缺陷的宽度(决定相机的分辨率和带宽)、测试物体距离相机的距离和大小(决定相机的焦距)、被测物体的测试视野FOV(在线阵相机一般指的就是测试宽度W,或者说是被测区域的横轴的大小)、被测物体的纵向速度等因素决定的。
第二,要针对基本的测试要求,对相机进行选型,例如,选择符合精度要求的相机分辨率,这时候,选择的相机的参数值一般会高于测试要求。
第三,针对选型后的相机参数,进行参数分析,再进一步依据相机的参数依赖性,进一步选择相机,例如包括相机的扫描行频,接口选择等等
第四,更加相机选型,进行系统参数的调整和选择,例如,设定线阵相机的触发和同步方式
最后,通过实验进一步验证和调整之前的选择。
一般先确定,测试的视野大小(比如,传送带的宽度),测试的精度要求,测试的速度:
| 编号 | 被测物参数(预设) | 举例: | 说明: |
| 1 | 视野 FOV (W宽度\幅宽) Object width | 370 mm | |
| 2 | 速度 V物: | 3 m/s | |
| 3 | 测试精度:(Dx)x轴横向 | 0.2 mm/pixel | Franklin 案1 Franklin 案2 |
【Franklin 案1,测试精度的计算,在国内一般不是这么表述,一般说,比如精度保证1mm(这里 的1mm是被测物体),或者说我要至少探测1mm的缺陷,拍摄1mm的物体,这时候,我们就需要依据采样定理,在1mm的被测物体视野至少放2到3个像素才能分辨出来,也就是3pixel/mm,注意这个单位和上表第3个参数其实就是定义倒了一下,也就是,0.33mm/pixel】
【Franklin 案2,参数3的定义,在国外比较普遍,又被叫做:【Spatial resolution:】0.2mm/pixel,就是5pixel/mm的精度】
| 编号 | 计算参数 | 举例: | 说明: |
| 1 | 视野 FOV (W宽度\幅宽) Object width | 370 mm | |
| 2 | 速度 V物: | 3 m/s | |
| 3 | 测试精度:(Dx)x轴横向 | 0.2 mm/pixel | |
| 4 | 相机计算分辨率:x轴横向 | = FOV / Dx = 1850 pixel | |
线扫相机的规格,往往为用1024的整数倍来定义,1850对应的应该是2K(2048个pixel)分辨率的相机。
| 编号 | 计算参数 | 举例: | |
| 4 | 相机计算分辨率:x轴 | = FOV / Dx = 1850 pixel | |
| 5 | 相机分辨率选择:Res | = 2048 > 1850 | |
| 6 | 相机实际测试精度(Dx) x轴横向 | = 1/ (5pixel * 2048 / 1850) = 0.18 mm/pixel | |
【Franklin 案,这里要特别强调一下,计算line rate普遍遵循的一个原则: 就是横向x,纵向y的Resolution 这里应该是解析率Ratio的意思,应该保持一致,也就是每个像素都是对应了同一个长度的实际物体的尺寸大小】

如果不一致,就会出现上图拉长或者压扁的问题:
也就是在纵向 - Y的方向 - 传送带方向 - 物体运动方向【一般线扫相机不动】也有:
Dy = 0.18mm/pixel = Dx
| 编号 | 计算参数 | 举例: | |
| 6 | 相机实际测试精度(Dx) x轴横向 | = 1/ (5pixel * 2048 / 1850) = 0.18 mm/pixel | |
| 7 | 相机实际测试精度(Dy) y轴纵向 | = Dx = 0.18 mm/pixel | |
【Franlin 案,现在我们来仔细思考一下下面的计算:】

每个pixel 在物体移动方向是0.18mm的实际物体大小,那么,现在物体移动的速度V已知,且如果我们默认的线阵相机的列的元素是1【也有大于1的,现在我们假设行扫描相机或者是线阵相机每行只有一个传感器像素点】,那么,如果要连续保持物体的连贯拍摄,就需要在每一行拍摄结束后,理解接着下一行的拍摄,如上图,我们可以理解为把运动的物体在Y方向进行切割,并且切割到每个像素解释行,也就是0.18mm,切割要连续进行,那么,拍摄的速度也要依据物体的速度连续进行,也就是拍摄的速度和运动的速度一致,而拍摄的速度就是由线扫描相机的行频决定的,于是有:
每行的解析的物体长度是S= 0.18mm,
Dy = S = V*T = V物 *T = 0.18mm -> T = S/V
Line Rate = F行频 = 1 / T = V/S = V/Dy
| 编号 | 计算参数 | 举例: | 说明: |
| 2 | 速度 V物: | 3 m/s | |
| 7 | 相机实际测试精度(Dy) y轴纵向 | 0.18 mm/pixel | |
| 8 | Line Rate | = V/Dy = 3 * 1000mm / 0.18mm = 16,667Hz =16.7KHZ | |
下表是某款线阵相机的参数列表,其中1,2,参数是我们前面几节已经计算得出的,接口定义【参数3】往往要依据相机具体的规格才能决定。例如,在行频80KHZ的使用下,必须采用CameraLink接口,而不能采样Medium等支持的USB3.0接口。

相机的镜头选型,其实基本上和面阵相机的选型计算一致,这个参考我之前的前三篇博文。

在这个例子里面,我们讨论一个传送带上的缺陷检测问题,在这个例子里面,我们加入了,
| 参数编号 | 输入参数 | 举例 | 说明 |
|---|---|---|---|
| 1 | 最小疤痕尺寸 最小划痕长度 | 1 mm 10mm | |
| 2 | 缺陷最小像素数 Pixels to span minimum defect | 3 pixels | |
| 3
| 传送带宽度 横向 (FOV) Web width | 670 mm 到 680mm | |
| 4 | 传送带速度 纵向 Vp | 550mm/s 到 640 mm/s | |
| 5 | 空间分辨率 横向 Spatial resolution | 1 mm/ 3 pixels = 0.33 mm/ pixel | |
| 6 | 过扫描余量 Overscan allowance | 5% | |
| 7 | 缺陷标记要求长度: 在距离相机100mm的地方用2mm的墨点标记缺陷 | 也可以理解为滚筒的周长 |
【Franklin案,由于2163像素在2K像素相机的边缘,从Price/pixel考虑可以选用2048的2K相机,也可选4K相机,看项目成本】
| 参数编号 | 输入参数 | 举例 | 说明 |
|---|---|---|---|
| 5 | 空间分辨率 横向 Spatial resolution | 1 mm/ 3 pixels = 0.33 mm/ pixel = 0.33mm/扫描周期 | |
| 6 | 过扫描余量 Overscan allowance | 5% | |
| 3
| 传送带宽度 横向 (FOV) Web width | 670 mm 到 680mm | |
| 计算参数 | 计算公式 | 举例 | |
| 8 图像分辨率 | 最大FOV / 空间分辨率 * 过扫描余量 | = (680mm / 0.33mm/pixel) * 1.05 = 2163 pixel | |
| 9 相机选型 相机分辨率 | > 2163 / 1024 | 2K 或者 4K | 因为2163和2048比较接近可选2046 当然选4096也可以 |
上一节,我们已经讨论,横向和纵向的空间分辨率需要一致,才能正确拼接还原原来的图像:也就是纵向的空间分辨率 (纵向)= 0.33mm/pixel
由于,线阵相机,默认只有一行像素点,且每行一个像素点:0.33mm/pixel =0.33mm/每扫描行周期,也就是在纵向方向,每个扫描周期应该移动0.33mm,在已知速度的情况下,知道了扫描的空间分辨率,就可以计算出,每个行扫描需要的时间 : scan rate。 如下表
| 参数编号 | 输入参数 | 举例 | 说明 |
|---|---|---|---|
| 5 | 空间分辨率 横向 Spatial resolution | 1 mm/ 3 pixels = 0.33 mm/ pixel = 0.33mm/扫描周期 = 0.33mm/scan | 可理解为扫描分辨率 |
| 4 | 传送带速度 纵向 (物体运动速度) | 550mm/s 到 640 mm/s | |
|
| |||
| 5.2 | 空间分辨率 纵向 Spatial resolution | 1 mm/ 3 pixels = 0.33 mm/ pixel = 0.33mm/扫描周期 | |
| 计算参数 | 计算公式 | 举例 | |
| 10 扫描周期/频率 scan rate
| 空间分辨率 / 传送带速度 | 0.33 (mm /扫描周期) / 640 (mm / s) = 0.515 ms /扫描周期 0.33 (mm /扫描周期) / 550 (mm / s) = 0.600 ms /扫描周期 也即 T scan rate min = 0.515 ms T scan rate max = 0.600 ms | 【注意不是行扫描频率】 |
上一节,我们得出scan rate = 0.6 ms / scan 或者 0.515ms ,因为,题设的条件,传送带纵向速度是有一定变化范围,这时候,需要用辅助的工具协助线扫描相机工作,比较常见的就是触发器和编码器。编码器的主要作用: 配合相机行频率,控制相机采集速度,从而实现稳定的拍摄。


我们这个例子,用一个每毫米为3次的编码器就来避免上述扫描的传送带的纵向速度偏差。
| 参数编号 | 输入参数 | 举例 | 说明 |
|---|---|---|---|
| 7 | 缺陷标记要求: 在距离相机100mm的地方用2mm的墨点标记缺陷 | 100mm +/- 2mm | |
| 5 | 空间分辨率 横向 Spatial resolution | 1 mm/ 3 pixels = 0.33 mm/ pixel = 0.33mm/扫描周期 = 0.33mm/scan | 可理解为扫描分辨率 |
| 11 | 单位长度计数 | Count3 / mm 每毫米为3次 | |
| 计算参数 | 计算公式 | 举例 | |
| 12 触发器计数 | 标记长度 * 单位长度计数 | (100±2) * 3 = 294 or 306 |
在物体运动的时候,曝光的模式,会导致运动模糊Motion Blur,

一般选取最小扫描周期的0.5倍做完曝光周期:
| 参数编号 | 输入参数 | 举例 | 说明 |
|---|---|---|---|
| 10 扫描周期/频率 scan rate
| 空间分辨率 / 传送带速度 | 0.33 (mm /扫描周期) / 640 (mm / s) = 0.515 ms /扫描周期 0.33 (mm /扫描周期) / 550 (mm / s) = 0.600 ms /扫描周期 也即 T scan rate min = 0.515 ms T scan rate max = 0.600 ms | 【注意不是行扫描频率】 |
| 计算参数 | 计算公式 | 举例 | |
| 11 曝光时间: | = 0.5 * T scan rate min | = 0.515 msec / 2 = 0.257 msec | |
曝光位移,为在曝光时间周期内,运动物体发生的偏移误差:
我们定义的曝光时间,为scan rate的一半,也即扫描分辨率的一半, Blur = Te / scan rate * Vp = 0.257ms*0.640 mm/ms = 0.16448mm
Pixel clock frequency = 相机分辨率 / T scan rate min = 7.94Mhz

主要数据接口比较如上,对比数据带宽可以进行选择:

线扫相机的选型,如果仔细考虑的话,有太多需要考虑的系统延迟因素,除了我们前面提到的依据物体的运动来定义的行频或者叫扫描周期scan period,还包括触发的时间 Trigger , 相机的曝光时间,接口的传输时间,系统内的RAM时间,图像处理和数据传送时间等。
硬实时性要求,是依据线扫相机的硬件极限而设定的最小响应的时间要求。其中,包括高速运动不拖尾需要考虑的系统曝光时间要求。

为了保证切割(slices)后的图像复原后正确,需要增加同步的设备,可以采用主动的触发来告知相机,或者也可以采用被动的编码器直接在时间上和相机拍摄频率同步。




好处就是,针对在拍摄纵向(传送带方向)有明显规律变化的部件,进行拍摄的不同光源和曝光模式的选择,这样有利于工业生产重复的检测需求。

HDR模式,对拍摄物体采用不同曝光然后融合的方式,提高拍摄的精度,并避免不同材质和重叠下的影响:

Burst Mode,系统将采样的行采样频率保持最高,保证每次高速度下的采样精度,同时,只抽取部分的行数据上传给服务器,这样保证了采样检测的需求,同时又降低了系统带宽的需求。


ROI能够在感兴趣的区域进行定制,比如图中,只关心铁轨的道钉的部分。这样减少系统的数据提取的带宽和存储需求。
提高超高速的数据传输接口
提供通用的数据接口访问,方便不同的相机进行系统集成

GigE, Camera Link, and USB 3.0 give the widest camera selection and best performance
Camera Link advantages
- • Speed
- • Determinism
GigE advantages:
- • Low cost
- • Simplicity (no frame grabber)
- • Cable length
USB3 advantages:
- • Low cost
- • Simplicity (no frame grabber)
- • Speed


线阵相机知识汇总_fantasysolo的博客-CSDN博客_线阵相机
Line scan cameras - Quality right down the line | STEMMER IMAGING (stemmer-imaging.com)
线扫相机 编码器_面阵和线扫工业相机选型_weixin_39560066的博客-CSDN博客
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal
📢博客主页:https://blog.csdn.net/weixin_43197380📢欢迎点赞👍收藏⭐留言📝如有错误敬请指正!📢本文由Loewen丶原创,首发于CSDN,转载注明出处🙉📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨文章预览:一.分辨率(Resolution)1、工业相机的分辨率是如何定义的?2、工业相机的分辨率是如何选择的?二.精度(Accuracy)1、像素精度(PixelAccuracy)2、定位精度和重复定位精度(RepeatPrecision)三.公差(Tolerance)四.课后作业(Post-ClassExercises)视觉行业的初学者,甚至是做了1~2年
我认为我的问题最好用一个例子来描述。假设我有一个名为“Thing”的简单模型,它有一些简单数据类型的属性。像...Thing-foo:string-goo:string-bar:int这并不难。数据库表将包含具有这三个属性的三列,我可以使用@thing.foo或@thing.bar之类的东西访问它们。但我要解决的问题是当“foo”或“goo”不再包含在简单数据类型中时会发生什么?假设foo和goo代表相同类型的对象。也就是说,它们都是“Whazit”的实例,只是数据不同。所以现在事情可能看起来像这样......Thing-bar:int但是现在有一个新的模型叫做“Whazit”,看起来
我有一个要在我的Rails3项目中使用的数组扩展方法。它应该住在哪里?我有一个应用程序/类,我最初把它放在(array_extensions.rb)中,在我的config/application.rb中我加载路径:config.autoload_paths+=%W(#{Rails.root}/应用程序/类)。但是,当我转到railsconsole时,未加载扩展。是否有一个预定义的位置可以放置我的Rails3扩展方法?或者,一种预先定义的方式来添加它们?我知道Rails有自己的数组扩展方法。我应该将我的添加到active_support/core_ext/array/conversion
参见下面的示例,我想最好使用第二种方法,但第一种也可以。哪种方法最好,使用另一种的后果是什么?classTestdefstartp"started"endtest=Test.newtest.startendclassTest2defstartp"started"endendtest2=Test2.newtest2.start 最佳答案 我肯定会说第二种变体更有意义。第一个不会导致错误,但对象实例化完全过时且毫无意义。外部变量在类的范围内不可见:var="string"classAvar=A.newendputsvar#=>strin
如果我构建了一个应用程序来访问来自Gmail、Twitter和Facebook的一些数据,并且我希望用户只需输入一次他们的身份验证信息,并且在几天或几周后重置,那会怎样是在Ruby中动态执行此操作的最佳方法吗?我看到很多人只是拥有他们客户/用户凭证的配置文件,如下所示:gmail_account:username:myClientpassword:myClientsPassword这看起来a)非常不安全,b)如果我想为成千上万的用户存储此类信息,它就无法工作。推荐的方法是什么?我希望能够在这些服务之上构建一个界面,因此每次用户进行交易时都必须输入凭据是不可行的。
深度学习12.CNN经典网络VGG16一、简介1.VGG来源2.VGG分类3.不同模型的参数数量4.3x3卷积核的好处5.关于学习率调度6.批归一化二、VGG16层分析1.层划分2.参数展开过程图解3.参数传递示例4.VGG16各层参数数量三、代码分析1.VGG16模型定义2.训练3.测试一、简介1.VGG来源VGG(VisualGeometryGroup)是一个视觉几何组在2014年提出的深度卷积神经网络架构。VGG在2014年ImageNet图像分类竞赛亚军,定位竞赛冠军;VGG网络采用连续的小卷积核(3x3)和池化层构建深度神经网络,网络深度可以达到16层或19层,其中VGG16和VGG
我想扫描未知数量的行,直到扫描完所有行。我如何在ruby中做到这一点?例如:putreturnsbetweenparagraphsforlinebreakadd2spacesatend_italic_or**bold**输入不是来自"file",而是通过STDIN。 最佳答案 在ruby中有很多方法可以做到这一点。大多数情况下,您希望一次处理一行,例如,您可以使用whileline=getsend或STDIN.each_linedo|line|end或者通过使用-n开关运行ruby,例如,这意味着上述循环之一(在每次迭代中将