C# 亚像素精度的图像处理

C# 亚像素精度的图像处理,c#,image-processing,computer-vision,vision,subpixel,C#,Image Processing,Computer Vision,Vision,Subpixel,我正在写一个控制工业机械的用户界面程序 该机器是一种用于电子生产行业的自动在线屏幕打印机。该机器的确切用途是将锡膏印刷到裸PCB上。 该系统包括2个摄像机,构成一个视觉系统,用于定位基准点并自动化机器所涉及的过程。 我面临的问题是,我需要能够在从相机拍摄的图像中定位形状和对象,这已经足够直截了当了,但是-为了获得所需的精度,我需要能够以亚像素精度进行定位 这两个摄像头组成一个双视觉摄像头,其中一个摄像头向上看模板,另一个向下看PCB。双视觉摄像机位于一个在X和Y方向移动的移动托架上。PCB夹在一

我正在写一个控制工业机械的用户界面程序

该机器是一种用于电子生产行业的自动在线屏幕打印机。该机器的确切用途是将锡膏印刷到裸PCB上。 该系统包括2个摄像机,构成一个视觉系统,用于定位基准点并自动化机器所涉及的过程。 我面临的问题是,我需要能够在从相机拍摄的图像中定位形状和对象,这已经足够直截了当了,但是-为了获得所需的精度,我需要能够以亚像素精度进行定位

这两个摄像头组成一个双视觉摄像头,其中一个摄像头向上看模板,另一个向下看PCB。双视觉摄像机位于一个在X和Y方向移动的移动托架上。PCB夹在一张桌子上,可以在X、Y和θ方向移动。视觉系统用于检测PCB位置和模具位置之间的差异,然后调整工作台使两者对齐

编辑:

这是从现有UI程序中截取的部分屏幕快照:

模具图像是顶部图像,PCB是底部图像,这里的图像是灰度图像-在新系统中,我正在使用颜色查看,但需要使用灰度

注意:当你读到这篇文章时,你可能会想“为什么不在现有的UI中使用你所使用的任何东西呢?”现有的UI是用VB6编写的,这是我想放弃的,而程序的vision端是由不再存在的第三方公司编写的.ocx

我玩过一点Forge.NET,发现它非常容易使用,我可以用它来定位各种不同的形状,找到它们的中心,这很好,但它没有亚像素精度。然而,我可能会以此为起点,然后对单个中心像素甚至整个形状应用子像素算法

编辑:

以下是我使用Forge编写的测试程序的示例图像:

红色轮廓和十字线是我添加的视觉辅助/实验。这是我可能使用的相机拍摄的,分辨率为1280 x 1024,但是镜头不是我将使用的实际镜头,这就是为什么图像有点“鱼眼”。此外,感兴趣的对象将比这更好的光

在实际系统中,镜头将在模板和PCB上看到10mm x 8mm的平方米,这意味着每个像素将代表7.8125um^2,但是我可以一次以1.25um的增量移动XYY表,如果我不能用相机看到这些移动,这基本上是无用的。 我需要1um(亚)像素精度

有人知道我可以用什么来做这件事吗?我已经搜索了很长一段时间了,但我所能找到的似乎都是关于以亚像素精度渲染图像的信息

或者,更好的是,有人知道我如何能自己写一些东西来做这件事吗?我甚至不知道从哪里开始


任何反馈都将不胜感激。

新信息告诉我们很多。。。我认为您应该更关注粘贴应用的精度,而不是托架位置的精度。我打赌打印机的网点尺寸和误差比1um大得多,而且所需的精度取决于PCB使用情况(布线和间隙宽度)。无论如何,我会这样做:

  • 线性化图像几何体

    你需要去鱼眼图像。由于相机/光学装置的设置是固定的(特别是焦距和到PCB的距离),您应该为每个PCB厚度制作棋盘格的图像。然后创建将棋盘线性化为真实矩形的映射,以便在下一个过程之前丢弃偏差

  • 正常化照明条件

  • 亚像素精度

    图像的每个像素都是其区域内所有内容的集成。因此,如果我们知道任何边界(背景/前景)的两种颜色(
    c0,c1
    ),那么我们可以估计它们的亚像素位置。让我们从轴对齐的矩形开始。我是这样看的:

    y=y0 + pixel_size*s0 // if c0 is on the top
    y=y0 + pixel_size*s1 // if c1 is on the bottom
    

    网格的每个正方形表示一个像素区域
    c0
    为灰色,
    c1
    为绿色。在相机图像中,最终颜色是每个像素内所有颜色的组合:

    • c=s0*c0+s1*c1
    其中,
    c
    是最终像素颜色,
    s0、s1
    是与
    c0、c1
    范围内的颜色相关的区域,
    s0+s1=1.0
    。现在我们要计算
    s0,s1
    以获得亚像素精度。因此,首先检测边界上的像素位置,作为以下之一:

    x=x0 + pixel_size*s0 // if c0 is on the left
    x=x0 + pixel_size*s1 // if c1 is on the left
    
    • 水平边
    • 垂直边缘
    • 角落
    这可以通过检查相邻像素来实现
    c0,c1
    可以从具有饱和颜色的像素(所有相邻像素具有相同的颜色)中获得,这些像素位于内部区域像素中。我将忽略角点像素,因为它们的位置可以从最近的H/V边缘像素获得(不可能从上面的等式中同时获得x,y坐标)。现在,对于每个H,V边,只需求解系统:

    I.  c = s0*c0 + s1*c1
    II. s0 + s1 = 1.0;
    
    计算
    s0,s1
    ,垂直边缘的边缘位置为以下之一:

    x=x0 + pixel_size*s0 // if c0 is on the left
    x=x0 + pixel_size*s1 // if c1 is on the left
    
    水平边如下所示:

    y=y0 + pixel_size*s0 // if c0 is on the top
    y=y0 + pixel_size*s1 // if c1 is on the bottom
    
    其中,
    x0,y0
    是像素的左上角位置,坐标系是
    x+
    向右,而
    y+
    向下。如果你有不同的设置,只要改变方程

    现在,如果得到的是非轴对齐的边,则需要计算斜率(一个轴上的像素数在另一个轴上发生变化
    dy/dx
    ),并相应地处理这些区域: