线扫描图像 Scaling

简短说明

文件: \examples\Processing\Geometry\ScalingLine\ScalingLineP16.va
\examples\Processing\Geometry\ScalingLine\ScalingLineP8.va

默认平台: mE5-MA-VCL

简要说明

线扫描图像的 Scaling 和转换

VisualApplets 设计“ScalingLineP8.va”和“ScalingLineP16.va”可按任意因子对 CameraLink Full 配置下的灰度线扫描相机图像进行 Scaling,从而转换输入和输出之间的图像宽度。“ScalingLineP8.va”专为 Parallelism 8 设计,“ScalingLineP16.va”专为 marathon VCL 平台的 Parallelism 16 设计。 本文档介绍了 VisualApplets 中的算法和实现。若要使用该设计,需要计算许多查找表值。 附带的 C++ 和 Matlab 程序提供了这些计算,以简化使用。

行中 Scaling/变换的基本思想

线图像的 Scaling/转换/Distortion Correction 是基于源图像和目标图像坐标进行的。 下面将通过示例坐标对和 Parallelism 4 来解释算法的基本原理。

目标坐标: 0 1 2 3 | 4 5 6 7 | 8 9 10 11 | 12 13 14 15
源坐标: 0.3 0.5 1.4 1.5 | 2.2 3.4 3.6 4.2| 5.4 5.5 7.8 8.5 | 9.1 11.4 13.3 14.1

我们采用 Target-To-Source 程序。对于目标图像(=发送给 PC 的输出图像)中的每个像素,我们选择相应的(四舍五入的)整数坐标以及源图像中的相应像素值。 通过同时选择源图像中当前像素坐标的前一个像素邻居,来考虑像素间的位置。 通过线性插值计算输出图像中的正确像素值。 由于 Parallelism 的原因,无法从源图像中读取单个像素。因此,必须以有用的顺序读取“字”(同时读取的像素单元)。 有时可能需要多次读取字,或者根本不需要读取。在从源图像读取的这些字中,必须选择用于创建输出字的正确像素位置。 将删除读取的字中不需要的像素。以下示例说明了源图像坐标的读取访问:

Memory Read Count 周期 请求的目标坐标 对应的源坐标 读取字 / 含像素 使用字中的像素
1 0, 1 2, 3 0.3, 0.5, 1.4, 1.5 0/ 0, 1, 2, 3 1, 1, 2, 2
2 4 2.2 0/ 0, 1, 2, 3 3, x, x, x
3 5, 6, 7, 8 3.4, 3.6, 4.2, 5.4 1/ 4, 5, 6, 7 4, 4, 5, 6
4 9 5.5 1/ 4, 5, 6, 7 6, x, x, x
5 10, 11, 12 7.8, 8.5, 9.1 2/ 8, 9, 10, 11 9, 8, 10, x
6 13, 14, 15 11.4, 13.3, 14.1 3 / 12, 13, 14, 15 12, 14, 15, x

表 24. 读取周期


其中“x”表示该像素已被删除。

在 VisualApplets 中的实现

该设计的主要组件包括(图 335):

1. 线扫描相机接口,包括触发系统和缓冲区;
2. 相机图像 Scaling(在 Transformation 中);
3. 向 PC 进行 DMA 数据传输;

Scaling 线扫描相机图像的基本设计结构

图 335. Scaling 线扫描相机图像的基本设计结构


接下来,我们将详细描述主组件 Transformation。

转型

您可以在图336中看到变换的组成部分。

转化的组成部分

图 336.变换的组成部分


相机线扫描图像的缩放操作采用目标到源 (Target-To-Source) 流程。在 WordToRead 函数中,我们选择从输入相机图像中读取 8 个像素单元(并行度为 8,位于“ScalingLineP8.va”中)或 16 个像素单元(并行度为 16,位于“ScalingLineP16.va”中)的顺序(即“字”)。在PixelPicker 函数中,我们决定需要从读取的字中选择哪些像素。插值计算输出图像中的像素值时,会考虑源图像中像素之间的位置关系。

WordToRead

模块 WordToRead 的组成部分如图337所示。

WordToRead 的组成部分

图 337. WordToRead的组成部分


待从源图像中读取的单词的顺序和频率在查找表 (LUT) WordsToRead中定义。该表的内容由外部 C++ 程序“ScalingLUTS.cpp”生成,或者也可以使用 MATLAB 模块“LUTS_Scaling.m”和“ScalingTablelLine.m”生成。请参阅相关章节。本文档中,此查找表的输入链接由CreateBlankImage和Coordinate_X定义。CreateBlankImage 的参数ImageWidth的值必须与LUT: WordsToRead中的元素数量完全相同。参数ImageHeight必须CreateBlankImage源图像在 y 方向上的图像尺寸匹配。源图像中的字按照LUT: WordsToRead定义的顺序从缓冲区LineMemoryRandomRd_1和LineMemoryRandomRd_2中读取。源图像以线性方式写入这些缓冲区。由于最大位深度为 64 位且并行度为 1,因此需要两个缓冲区。对于每个字,选择并读取前一个字的最后一个像素( SYNC之前的上行操作)。使用Merge运算符将此值添加到对应的字中。

PixelPicker

在PixelPicker模块(参见图338 )中,缩放后的输出词的像素是通过从读取的单词中选择Pick_0到Pick_15 (或并行度为 8 时选择到Pick_7 )组件来选择的。如果不需要读取的单词的像素(参见第 节),则查找表RemovePixel会删除它们。上述表格( Pick_0到Pick_15和RemovePixel )的内容可以使用外部 C++ 程序“ScalingLUTS.cpp”创建,也可以使用 MATLAB 模块“LUTS_Scaling.m”和“ScalingTablelLine.m”创建。另请参阅相关章节。本文档中。

PixelPicker 的组成部分

图 338. PixelPicker的组成部分


图339显示了 HierarchicalBox Pick_0的内容。查找表PickComponent0定义了从读取的单词( SelectFromParallel:单词和Coordinate_X:数字)中哪个像素是当前输出单词的第 0 个分量。使用运算符 CASE选择相应的像素。将其与其前一个像素一起写入当前像素( MergePixel )。与上述过程类似,使用模块Pick_1到Pick_15 (或到Pick_7 )选择当前输出单词的第 1 到 15 个像素(或并行度为 8 时的第 7 个像素)。单个像素Pick_0到Pick_15 (或到Pick_7 )以并行度 16 或 8 合并到当前变换/缩放后的单词中(图338中的MergeParallel )。

Pick_0 的内容

图 339. Pick_0的内容


Interpolation

为了获得发送到 PC 的输出图像中像素位置的正确值,必须考虑源图像中的像素间位置。在插值模块(图336 )中,执行线性插值 [ Bur06 ]:

公式 30。


在此 是输出图像中的像素值,对应于值 在源图像中,位置 x 处。此外 和 是像素坐标处的值 和 在源图像中。像素间距为 有关线性插值的更多信息,例如,您可以在[此处]找到。Bur06].

模块的内容 Interpolation 如图所示。 340。 当前像素的值 与其 前一个像素 使用运算符进行隔离 SelectBitField: Current 和 SelectBitField: Previous。以下各项的值 和 乘以 和 根据公式 30。有关子像素位置的信息 包含在四个查找表中 Fractional_Part0 更改为 Fractional_Part3 在设计“ScalingLineP16.va”中。每个表包含当前输出字的 4 个像素的子像素位置 。 每个子像素位置的位深为 6 位。LUT 的内容 可以通过外部 C++ 程序“ScalingLUTS.cpp”创建,或者使用 MATLAB 模块“LUTS_Scaling.m”和 “ScalingTablelLine.m”来创建。为此,请参见 本文档中的节 Fractional_Part0 更改为 Fractional_Part3 可以使用外部 C++ 程序“ScalingLUTS.cpp”创建,或者使用 MATLAB 模块“LUTS_Scaling.m”和“ScalingTablelLine.m”创建。另请参阅相关章节。 。 设计“ScalingLineP8.va”包含一个包含子像素位置的表 Fractional。其内容也可以使用外部 C++ 和 Matlab 程序模块创建。 最后,通过 DMA 传输将转换/Scaling 后的行图像发送到 PC(参见图 336)。

插值组件

图 340. Interpolation 组件


VisualApplets 设计的查找表

设计“ScalingLineP16.va”和“ScalingLineP8.va”(参见节 )所需的查找表可以通过 C++ 程序 “ScalingLUTs.cpp”(在文件夹“LUTS_Cpp”中)或 MATLAB 程序模块“LUTS_Scaling.m”和“ScalingTableLine.m”(在 文件夹“LUTS_MATLAB”中)创建。

ScalingLUTs.cpp

1. 请在程序(或命令提示符)中定义以下参数:

//////////////////////Parameter////////////////////

/* 请指定这些参数!*/////////////////

uint64_t parallelism = 8; // 对于“ScalingLineP8.va”设为 =8,对于“ScalingLineP16.va”设为 =16

uint64_t fractionalBits = 6; // = 6:“ScalingLineP8.va”和“ScalingLineP16.va”中的默认值

uint64_t noOfFractionalLUTs = parallelism == 8 ? 1 : 4; // 小数表数量 = “ScalingLineP8.va”中的 1 且 = “ScalingLineP16.va”中的 4

int InputWidth; // 输入图像的宽度

int OutputWidth; // 发送到 PC 的图像宽度

对于 VisualApplets 设计“ScalingLineP16.va”,将 parallelism 参数设置为 16,对于“ScalingLineP8.va”则设置为 8。 fractionalBits 的值 6 是 两个设计中的默认值。设计“ScalingLineP16.va”具有四个表(const int noOfFractionalLUTs = 4),其中包含 用于插值的 子像素位置(参见图 340)。而设计“ScalingLineP8.va”则 有一个表(const int noOfFractionalLUTs = 1)。线扫描图像的 Scaling 由 InputWidth 与 OutputWidth 之间的关系决定。

2. 运行程序!

3. 创建了以下文件,这些文件可加载到 VisualApplets 设计中的查找表中:

文件 VA LUT
FractionalTable_0.txt 到 FractionalTable_3.txt Fractional_Part0(对于 parallelism 8 则为 Fractional)到 FractionalPart_3
PickerTable_0.txt 到 PickerTable_15.txt(或到 PickerTable_7.txt) PickComponent0 到 PickComponent15(或到 PickComponent7)
TableWordsToRead.txt WordsToRead
RemoveTable.txt RemovePixel

表 25. Visual Applets 中的文件及其对应的查找表


此外,还创建了文本文件 ScalingTable.txt。它包含源图像中 每个输出图像像素对应的坐标(另请参阅章节 )。

ScalingTableLine.m and LUTS_Scaling.m

请打开模块“ScalingTableLine.m”并定义参数

InputWidth=…;

OutputWidth=…;

1. 运行程序!

2. 已创建文本文件 ScalingTableLine.txt。它包含源图像中 每个输出图像像素对应的坐标。

3. 请打开模块“LUTS_Scaling.m”并定义参数

parallelism = ...;

NoOfFractionalBits=...;

NoOfFractionalTables=...;

运行程序!创建的文件对应于 Tab. 25 中的文件,这些文件可以加载到 VisualApplets 设计中的查找表中。