目录

【Vitis AIE】FPGA图像处理 11 双线性插值 Bilinear Interpolation

双线性插值

https://github.com/Xilinx/Vitis-Tutorials/tree/2024.2/AI_Engine_Development/AIE/Design_Tutorials/11-Bilinear_Interpolation

简介

双线性插值是一种使用重复线性插值来插值两个变量函数的方法。它通常用于以下应用:

  • 图像处理和计算机视觉,用于对图像和纹理进行重采样。例如,当放大或缩小图像时,可以使用双线性插值根据原始像素的颜色值来估计新像素的颜色值。[[1]] [[2]]
  • 有限元分析,用于估计有限元网格中节点之间应力应变等变量的值。[[3]]
  • 地理信息系统,用于从点网格中插值高程或其他空间数据。[[4]]
  • 计算机图形学,用于将纹理映射到 3D 表面或执行纹理过滤。[[5]]

双线性插值是最简单和最快的插值方法之一,但它也会引入一些伪影,例如模糊或混叠。更高级的插值方法,例如双三次插值或样条插值,可以产生更平滑和更准确的结果,但它们的计算成本也更高。

计算插值

图 1 说明了双线性插值问题。假设您知道函数在点 ( x 1 , y 1 ) (x_1, y_1) (x1,y1)、 ( x 1 , y 2 ) (x_1, y_2) (x1,y2)、 ( x 2 , y 1 ) (x_2, y_1) (x2,y1) 和 ( x 2 , y 2 ) (x_2, y_2) (x2,y2) 的值,这些点定义在网格上,为了实际目的,可以假设为直线。目标是通过使用周围点的已知值来估计坐标为 ( x q , y q ) (x_q, y_q) (xq,yq) 的点处的函数值。在图 1 中,绿点表示已知值,红点表示要估计的值。

图 1 - 双线性插值问题

双线性插值可以看作是一个两步过程,其中首先在一个维度上执行线性插值,然后在另一个维度上执行线性插值。该过程的第一步如图 2 所示,其中蓝点处的函数值通过对变量 x x x 进行线性插值,从绿点处的已知值计算得出。

图 2 - 首次线性插值

这两个中间点可以用已知值表示为

f ( x q , y 1 ) = ( x 2 − x q ) ( x 2 − x 1 ) f ( x 1 , y 1 ) + ( x q − x 1 ) ( x 2 − x 1 ) f ( x 2 , y 1 ) f(x_q,y_1) = \frac{(x_2-x_q)}{(x_2-x_1)}f(x_1,y_1) + \frac{(x_q-x_1)}{(x_2-x_1)}f(x_2,y_1) f(xq,y1)=(x2−x1)(x2−xq)f(x1,y1)+(x2−x1)(xq−x1)f(x2,y1)

f ( x q , y 2 ) = ( x 2 − x q ) ( x 2 − x 1 ) f ( x 1 , y 2 ) + ( x q − x 1 ) ( x 2 − x 1 ) f ( x 2 , y 2 ) . f(x_q,y_2) = \frac{(x_2-x_q)}{(x_2-x_1)}f(x_1,y_2) + \frac{(x_q-x_1)}{(x_2-x_1)}f(x_2,y_2). f(xq,y2)=(x2−x1)(x2−xq)f(x1,y2)+(x2−x1)(xq−x1)f(x2,y2).

该过程的第二步如图 3 所示,其中红点处的期望值通过使用对变量 y y y 的线性插值,从蓝点处的计算值推导得出。

图 3 - 第二次线性插值

得到的插值点是

f ( x q , y q ) = ( y 2 − y q ) ( y 2 − y 1 ) f ( x q , y 1 ) + ( y q − y 1 ) ( y 2 − y 1 ) f ( x q , y 2 ) . f(x_q,y_q) = \frac{(y_2-y_q)}{(y_2-y_1)}f(x_q,y_1) + \frac{(y_q-y_1)}{(y_2-y_1)}f(x_q,y_2). f(xq,yq)=(y2−y1)(y2−yq)f(xq,y1)+(y2−y1)(yq−y1)f(xq,y2).

组合公式,双线性插值公式可以表示为

f ( x q , y q ) = 1 ( x 2 − x 1 ) ( y 2 − y 1 ) [ x 2 − x q x q − x 1 ] [ f ( x 1 , y 1 ) f ( x 1 , y 2 ) f ( x 2 , y 1 ) f ( x 2 , y 2 ) ] [ y 2 − y q y q − y 1 ] . f(x_q,y_q) = \frac{1}{(x_2-x_1)(y_2-y_1)} \begin{bmatrix} x_2-x_q & x_q-x_1 \end{bmatrix} \begin{bmatrix} f(x_1,y_1) & f(x_1,y_2) \\ f(x_2,y_1) & f(x_2,y_2) \end{bmatrix} \begin{bmatrix} y_2-y_q \\ y_q-y_1 \end{bmatrix}. f(xq,yq)=(x2−x1)(y2−y1)1[x2−xqxq−x1][f(x1,y1)f(x2,y1)f(x1,y2)f(x2,y2)][y2−yqyq−y1].

设计假设

虽然双线性插值可以应用于各种应用中,但这里使用了一个图像处理示例。在这种情况下,函数值对应于范围 [0, 255] 中的像素值。插值像素值和插值坐标 ( x q , y q ) (x_q,y_q) (xq,yq) 假设为单精度浮点数值格式。

使用参考图像来生成查找表,该表提供 AI 引擎的输入。假设分辨率为 x r e s × y r e s x_{res} \times y_{res} xres×yres 的输入图像具有在单位间距网格上定义的像素。可以使用公式 I = x × y r e s + y I = x \times y_{res} + y I=x×yres+y 组合 x x x 和 y y y 像素坐标以导出 LUT 索引 I I I,如图 4 所示。

图 4 - 作为查找表的图像

对于任何查询点 ( x q , y q ) (x_q,y_q) (xq,yq),浮点坐标可以分为整数部分和小数部分,其中 x q = x i n t . x f r a c x_q = x_{int}.x_{frac} xq=xint.xfrac 和 y q = y i n t . y f r a c y_q = y_{int}.y_{frac} yq=yint.yfrac。整数部分用于提取插值公式中使用的像素值。使用以下关系从 LUT 中获取插值所需的四个值:

f ( x 1 , y 1 ) = L U T ( x i n t ∗ y r e s + y i n t ) f ( x 1 , y 2 ) = L U T ( x i n t ∗ y r e s + y i n t + 1 ) f ( x 2 , y 1 ) = L U T ( ( x i n t + 1 ) ∗ y r e s + y i n t ) f ( x 2 , y 2 ) = L U T ( ( x i n t + 1 ) ∗ y r e s + y i n t + 1 ) . \begin{aligned} &f(x_1,y_1) = LUT(x_{int} * y_{res} + y_{int}) \\ &f(x_1,y_2) = LUT(x_{int} * y_{res} + y_{int} + 1) \\ &f(x_2,y_1) = LUT((x_{int} + 1) * y_{res} + y_{int}) \\ &f(x_2,y_2) = LUT((x_{int} + 1) * y_{res} + y_{int} + 1). \end{aligned} f(x1,y1)=LUT(xint∗yres+yint)f(x1,y2)=LUT(xint∗yres+yint+1)f(x2,y1)=LUT((xint+1)∗yres+yint)f(x2,y2)=LUT((xint+1)∗yres+yint+1).

LUT 索引的示例在图 4 中使用标有 X 的像素显示。一旦获得了插值所需的四个像素值,坐标 ( x q , y q ) (x_q,y_q) (xq,yq) 的整数部分就不再需要了,并且可以假设为零。这简化了插值公式为

f ( x q , y q ) = [ 1 − x f r a c x f r a c ] [ f ( x 1 , y 1 ) f ( x 1 , y 2 ) f ( x 2 , y 1 ) f ( x 2 , y 2 ) ] [ 1 − y f r a c y f r a c ] f(x_q,y_q) = \begin{bmatrix} 1-x_{frac} & x_{frac} \end{bmatrix} \begin{bmatrix} f(x_1,y_1) & f(x_1,y_2) \\ f(x_2,y_1) & f(x_2,y_2) \end{bmatrix} \begin{bmatrix} 1-y_{frac} \\ y_{frac} \end{bmatrix} f(xq,yq)=[1−xfracxfrac][f(x1,y1)f(x2,y1)f(x1,y2)f(x2,y2)][1−yfracyfrac]

或表示为内积

f ( x q , y q ) = [ ( 1 − x f r a c ) ( 1 − y f r a c ) ( 1 − x f r a c ) y f r a c x f r a c ( 1 − y f r a c ) x f r a c y f r a c ] [ f ( x 1 , y 1 ) f ( x 1 , y 2 ) f ( x 2 , y 1 ) f ( x 2 , y 2 ) ] . f(x_q,y_q) = \begin{bmatrix} (1-x_{frac})(1-y_{frac}) & (1-x_{frac})y_{frac} & x_{frac}(1-y_{frac}) & x_{frac}y_{frac} \end{bmatrix} \begin{bmatrix} f(x_1,y_1) \\ f(x_1,y_2) \\ f(x_2,y_1) \\ f(x_2,y_2) \end{bmatrix}. f(xq,yq)=[(1−xfrac)(1−yfrac)(1−xfrac)yfracxfrac(1−yfrac)xfracyfrac] f(x1,y1)f(x1,y2)f(x2,y1)f(x2,y2) .

AI 引擎代码向量化

为了实现 AI 引擎处理的优势,必须对计算进行向量化。将此应用于像素插值,计算可以重述为

f ( x q , y 1 ) = x f r a c f ( x 2 , y 1 ) + f ( x 1 , y 1 ) − x f r a c f ( x 1 , y 1 ) f(x_q,y_1) = x_{frac}f(x_2,y_1) + f(x_1,y_1) - x_{frac}f(x_1,y_1) f(xq,y1)=xfracf(x2,y1)+f(x1,y1)−xfracf(x1,y1)

f ( x q , y 2 ) = x f r a c f ( x 2 , y 2 ) + f ( x 1 , y 2 ) − x f r a c f ( x 1 , y 2 ) f(x_q,y_2) = x_{frac}f(x_2,y_2) + f(x_1,y_2) - x_{frac}f(x_1,y_2) f(xq,y2)=xfracf(x2,y2)+f(x1,y2)−xfracf(x1,y2)

用于 x 坐标中的前两个插值,以及

f ( x q , y q ) = y f r a c f ( x q , y 2 ) + f ( x q , y 1 ) − y f r a c f ( x q , y 1 ) f(x_q,y_q) = y_{frac}f(x_q,y_2) + f(x_q,y_1) - y_{frac}f(x_q,y_1) f(xq,yq)=yfracf(xq,y2)+f(xq,y1)−yfracf(xq,y1)

用于 y 坐标中的最终插值。通过以这种方式重新表述计算,每个公式中的前两项表示乘加 (MAC) 运算,该运算可用于后续的从累加器 (MSC) 运算中进行乘法和减法以获得结果。每个插值像素需要 3 个 MAC 加 3 个 MSC 运算。

此示例使用单精度浮点数进行计算。图 5 显示了 AI 引擎的浮点向量单元,其中可以观察到乘法器和累加器单元设计为并行处理八个通道。SIMD 并行性通过使用每个通道一个像素的方法来实现。由于每个像素需要 3 个 MAC 加 3 个 MSC 运算,每个运算都可以在一个时钟周期内执行,因此计算要求的下限为每个像素 0.75 个周期。此计算界限应被视为预期性能的大致估计,由于开销、带宽限制和流水线效率低下,这可能无法实现。

图 5 - 浮点向量单元

数据接口

将算法映射到 AI 引擎时,该过程通常会成为计算效率、数据带宽和内存利用率之间的权衡。在上一节中,每个像素 0.75 个周期被推导为计算效率的下限。接下来检查数据接口以确定它们施加的限制,并为选择合适的数据接口提供指导。

可编程逻辑组件

在考虑系统分区时,从查找表中检索数据以及提取浮点数的整数和小数部分等任务更适合在可编程逻辑中执行。当 AI 引擎被编程为持续对稳定的输入数据流执行向量处理时,可以实现 AI 引擎的有效利用。

处理单个像素所需的数据由四个参考像素和 x q x_q xq 和 y q y_q yq 坐标的小数部分组成。假设这六个数据值中的每一个都表示为 32 位单精度浮点值。图 6 显示了如何在可编程逻辑中为每个像素导出输入数据的概念图。此示例设计不包括可编程逻辑组件,但假设已使用此类组件来生成 AI 引擎处理的测试输入数据。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6 - 输入像素数据的推导

PLIO 接口

考虑到输入需要每个像素 6 个浮点值,而输出是单个浮点值,很明显输入流对可实现的像素处理速率施加了更严格的限制。PLIO 接口支持每个周期 1 个浮点值的传输速率,根据 AMD Versal™ 设备的 speed grade,这相当于每秒 1.0 到 1.25 亿个浮点值的传输速率。由于输入需要每个像素 6 个浮点值,因此输入 PLIO 会将速率限制为每个像素 6.0 个周期。为了使输入限制更接近计算效率,使用了 3 个输入 PLIO 接口,这将限制降低到每个像素 2.0 个周期。每个输入 PLIO 接口的数据格式如图 7 所示。

图 7 - 输入 PLIO 数据格式

AI 引擎测试向量

当 AI 引擎图与可编程逻辑和处理系统分开模拟时,使用文本文件来提供输入数据。此示例使用 MATLAB® 来生成测试向量,这些向量是 int32 数字序列。虽然实际数据是单精度浮点数,但很难以文本格式表达此类数字。为了捕获完整精度,用于表示浮点数 (符号、指数、尾数) 的 32 位被写为等效的 int32 值。包含输出数据的文件也使用类似的格式。

AI 引擎内核处理

内核数据接口

此处提供的内核示例使用缓冲 I/O 进行输入和输出。这允许更高效的 VLIW 并行性,其中加载和存储指令可以在与向量处理器指令相同的时钟周期内执行。权衡是初始延迟增加了。此外,编译器会为从 AI 引擎 tile 内存分配的每个 I/O 插入乒乓缓冲区。由于此示例有三个输入和一个输出,因此总共需要八个内存库。这意味着使用额外的 AI 引擎 tile 来满足内存需求。

I/O 的另一个选项是使用直接流式传输到或从 AI 引擎传输。有两个 32 位输入流和两个 32 位输出流可用。虽然这可以消除对乒乓缓冲区的需求,但内核代码中会使用额外的周期来移动向量数据。例如,如果大小为 8 的 float 向量被发送到输出流,则需要八个时钟周期。

如果数据的来源或目的地是另一个 AI 引擎 tile,则可以使用内核 I/O 的最终选项。在这种情况下,可以使用级联接口。可以使用级联接口每个时钟周期传输大小为 8 的 float 向量。

内核代码

为了提高计算效率,创建内核代码以利用执行同时向量乘法、加载和存储操作的 VLIW 指令。内核的每次调用处理 256 个像素,但在为模拟生成测试向量时可以更改此值。此处显示的内核代码处理在每个循环中使用大小为 8 的向量,对 x 坐标进行两次插值,然后对 y 坐标进行插值。计算是使用 AI 引擎向量固有函数执行的。

cpp 复制代码
void bilinear_kernel::interp(input_buffer<int32, extents<BUFFER_SIZE_IN>>& __restrict in_A, 
                             input_buffer<int32, extents<BUFFER_SIZE_IN>>& __restrict in_B, 
                             input_buffer<int32, extents<BUFFER_SIZE_IN>>& __restrict in_C, 
                             output_buffer<int32, extents<BUFFER_SIZE_OUT>>& __restrict out)
{
    // iterators for input & output buffers
    auto pInA = aie::begin_vector<8>(in_A);
    auto pInB = aie::begin_vector<8>(in_B);
    auto pInC = aie::begin_vector<8>(in_C);
    auto pOut = aie::begin_vector<8>(out);

    for (unsigned i = 0; i < PXLPERGRP/8; i++)
        chess_prepare_for_pipelining
        chess_loop_count(PXLPERGRP/8)
    {
        // get data for first x interpolation
        auto xfrac = (*pInA++).cast_to<float>();
        auto p11 = (*pInB++).cast_to<float>();
        auto p21 = (*pInC++).cast_to<float>();

        // compute first x interpolation
        auto tempy1 = fpmac(p11,xfrac,0,0x76543210,p21,0,0x76543210);
        auto pxy1 = fpmsc(tempy1,xfrac,0,0x76543210,p11,0,0x76543210);

        // get data for second x interpolation
        auto p12 = (*pInB++).cast_to<float>();
        auto p22 = (*pInC++).cast_to<float>();

        // compute second x interpolation
        auto tempy2 = fpmac(p12,xfrac,0,0x76543210,p22,0,0x76543210);
        auto pxy2 = fpmsc(tempy2,xfrac,0,0x76543210,p12,0,0x76543210);

        // get data for y interpolation
        auto yfrac = (*pInA++).cast_to<float>();

        // compute y interpolation
        auto tempxy = fpmac(pxy1,yfrac,0,0x76543210,pxy2,0,0x76543210);
        auto pxy = fpmsc(tempxy,yfrac,0,0x76543210,pxy1,0,0x76543210);

        // write interpolated pixels to output
        *pOut++ = as_v8int32(pxy);
    }
}

运行示例

运行示例需要正确安装和配置 MATLAB 和 AMD Vitis™ 工具。下载文件后,cd 进入 .../11-Bilinear_Interpolation/aie/ 目录并使用 make 构建过程。

生成测试向量

在运行 AI 引擎图模拟之前,需要测试向量来提供输入。还提供了文件,用于与 AI 引擎模拟器输出进行比较以进行验证。要生成向量,请运行以下命令:

bash 复制代码
$ make gen_vectors

运行 x86 模拟

要执行功能性 x86 模拟,请输入以下命令序列:

bash 复制代码
$ make x86com
$ make x86sim
$ make check_x86sim

第一个命令编译图代码以在 x86 处理器上进行模拟,第二个命令运行模拟,最后一个命令调用 MATLAB 以将模拟器输出与测试向量进行比较。

运行 AI 引擎模拟

要使用 SystemC 模拟器执行 AI 引擎仿真,请输入以下命令序列:

bash 复制代码
$ make aiecom
$ make aiesim
$ make check_aiesim

第一个命令编译图代码以用于 SystemC 模拟器,第二个命令运行模拟,最后一个命令调用 MATLAB 以将模拟输出与测试向量进行比较。如果需要在模拟期间生成跟踪和配置文件数据,请使用以下序列:

bash 复制代码
$ make aiecom
$ make profile
$ make check_aiesim

分析结果

Vitis 分析器

Vitis 分析器是访问有关 AI 引擎图的编译、模拟和实现信息的必要工具。它可用于获取有关配置数据的摘要,并以图形方式显示跟踪事件。可以使用 vitis_analyzer 命令调用该工具,或者对于此示例,可以通过输入以下命令:

bash 复制代码
$ make analyze

"图形"视图显示 AI 引擎图的连接性,对于此示例,如图 8 所示。此简单示例显示了内核以及与输入和输出端口关联的乒乓缓冲区。

图 8 - Vitis 分析器图形视图

"数组"视图显示 AI 引擎图如何映射到指定设备的 AI 引擎数组。此示例使用包含 400 个 AI 引擎 tile 的 VC1902 Versal AI Core 设备。如图 9 所示,此示例使用一个 tile 进行内核处理,并使用两个额外的 tile 进行乒乓缓冲区和系统内存。如果需要更多地控制内存的放置,可以指定设计约束。

图 9 - Vitis 分析器数组视图

图 10 包含来自"配置文件"视图的信息。突出显示的字段显示双线性插值内核需要 537 个周期来处理 256 个像素的数据。对于最低速度的 Versal 设备,这会将峰值处理速率转换为约 476.7 MP/s。最高速度的设备将具有约 595.9 MP/s 的峰值处理速率。可以通过编码来利用更高效的软件流水线来进一步提高内核计算,这表明可以实现 667 MP/s 的速率。

图 10 - Vitis 分析器配置文件视图

此特定示例未达到提到的速率,因为它受到数据带宽的限制。图 11 显示了 Vitis 分析器跟踪视图的一部分。光标显示一个内核调用结束到下一个内核调用结束之间的时间为 484.0 ns。在此期间,处理了 256 个像素,导致速率为 528.9 MP/s。

图 11 - Vitis 分析器跟踪视图

测试向量比较

将模拟结果与测试向量进行比较时,会调用 MATLAB 脚本来执行处理。图 12 显示了成功比较的示例。

图 12 - 模拟验证

输出提供了三种不同的模拟性能指示。第一个指示是模拟输出是否与相应的测试向量匹配。对于每个模拟的内核,都将进行一次比较。该脚本比较代表浮点插值像素值的 int32 值。由于浮点计算可能存在细微差异,因此比较允许浮点数的最低有效尾数位不匹配,并且可以在比较脚本中指定。

第二个比较指示 AIE 模拟结果与单精度 MATLAB 生成的向量之间的最大像素值差异。像素采用范围 [0, 255] 中的值,此结果提供了所有成对的对应像素之间差异的最大值。

最后一个比较指示 AI 引擎模拟结果与 MATLAB interp2 函数生成的双精度浮点结果之间的最大像素值差异。

自定义示例

可以轻松自定义此示例以使用不同的测试图像、使用指定的输出分辨率或使用多个并行处理核心来提高吞吐量。生成测试向量时,可以手动在 MATLAB 中使用所需的函数参数运行脚本,而不是使用 Makefile。例如,以下命令等效于

bash 复制代码
$ make gen_vectors

调用 MATLAB 并运行

bash 复制代码
>> image_transform
>> genvectors_bilinear_interp

指定测试图像和输出分辨率

image_transform 函数默认使用文件 ../images/epyc.jpg 作为测试图像。可以在 MATLAB 中调用该函数时指定一个名为 image_file 的不同文件。

bash 复制代码
>> image_transform('image_file')

默认输出分辨率为 1024 × \times × 1024 像素。可以通过调用

bash 复制代码
>> image_transform('image_file', [ xres  yres ])

来指定 x r e s × y r e s x_{res} \times y_{res} xres×yres 的不同分辨率。

image_transform 函数读取测试图像文件,对图像像素坐标执行一系列线性变换,并将这些变换与测试图像像素数组一起存储在名为 bli_coords.mat 的文件中。当此函数在 MATLAB 中执行时,将显示一系列图像变换。

多核处理

genvectors_bilinear_interp 函数假设使用单个 AI 引擎内核进行处理来生成测试向量文件。要并行使用多个内核,请按以下方式调用该函数:

bash 复制代码
>> genvectors_bilinear_interp(N)

其中,N 是所需的内核数。此函数从文件 bli_coords.mat 中提取坐标变换之一,对像素执行双线性插值,并创建 AI 引擎模拟的输入和输出测试向量。该函数还会生成一个名为 config.h 的文件,供 AI 引擎编译器和模拟器使用,以指定内核数和处理整个测试图像所需的内核调用数。此函数还使用 MATLAB interp2 函数以双精度执行双线性插值,并将结果存储在文件 golden_ref.mat 中。

例如,指定四个内核应导致 MATLAB 控制台窗口显示类似的内容

复制代码
>> genvectors_bilinear_interp(4)
Number of output pixels interpolated = 453221 out of 1048576 (43.22252 %)
Maximum pixel error is 0.000052940
Mean square pixel error is 0.000000000

以及图 13 中所示的图像。

图 13 - MATLAB genvectors_bilinear_interp 输出

运行这些 MATLAB 脚本后,AI 引擎构建和模拟过程的其余部分将以相同的方式进行。图 14 显示了如何将四个内核分配给 AI 引擎数组中的 tile。

图 14 - AI 引擎数组中的多核内核放置

图 15 显示了将多核 AI 引擎模拟输出与测试向量进行比较的结果。根据配置文件结果,四个内核将支持大约 1.7 到 2.1 GP/s 范围内的峰值处理速率,具体取决于设备速度等级。

图 15 - 多核模拟验证

参考

\[1\]\]: 双线性插值。2023 年 5 月 17 日,14:05 UTC。在维基百科中:自由百科全书。Wikimedia Foundation Inc. 百科全书在线。可从 https://en.wikipedia.org/wiki/Bilinear_interpolation 获取。互联网。2023 年 8 月 4 日检索。 \[\[2\]\]: K. T. Gribbon 和 D. G. Bailey,"实时双线性插值的一种新方法",论文集。DELTA 2004。第二届 IEEE 电子设计、测试和应用国际研讨会,澳大利亚珀斯,2004 年,第 126-131 页,doi:10.1109/DELTA.2004.10055。 \[\[3\]\] Chen, J. (2023, March 5). *插值公式:了解基础知识和应用.* The Daily Scoup News. https://en.thedailyscoup.news/2023/03/05/interpolation-formula-understanding-the-basics-and-applications/ \[\[4\]\] P. He 等人,"具有局部隐式函数表示的数字高程模型的超分辨率",2022 年机器学习和智能系统工程国际会议 (MLISE),中国广州,2022 年,第 111-116 页,doi:10.1109/MLISE57402.2022.00030。 \[\[5\]\] Wronski, B. (2020, April 14). *双线性纹理过滤 -- 伪影、替代方案和频域分析.* https://bartwronski.com/2020/04/14/bilinear-texture-filtering-artifacts-alternatives-and-frequency-domain-analysis/ ### 支持 GitHub 问题将用于跟踪请求和错误。如有疑问,请访问 [support.xilinx.com](http://support.xilinx.com/)。 ~版权所有 © 2020--2024 Advanced Micro Devices, Inc~ ^[条款和条件](https://www.amd.com/en/corporate/copyright)^

本文是转载文章,点击查看原文
如有侵权,请联系 xyy@jishuzhan.net 删除
相关推荐
失业写写八股文1 小时前
Java性能调优三板斧:CPU与Full GC问题定位的解决方案
java·性能优化
北城笑笑3 小时前
FPGA 34 ,FPGA 与 DSP 技术,赋能工业 4.0 时代,理论解析( FPGA 与 DSP技术,工业界的「硬件快手」与「软件大脑」)
fpga开发·fpga
转转技术团队7 小时前
"慢SQL"治理的几点思考
数据库·mysql·性能优化
cckkppll9 小时前
vivado 创建主时钟
fpga开发
苦练fpga9 小时前
数字电路基础
fpga开发
这张生成的图像能检测吗10 小时前
开个坑记录一下树莓派4B部署yolo的一些问题
yolo·边缘计算·持续部署
桂月二二12 小时前
边缘计算场景下的分布式推理系统架构设计
分布式·系统架构·边缘计算
zonda的地盘13 小时前
‌Flutter 树手术(Tree Surgery)机制与 GlobalKey 的深度解析
flutter·性能优化
zonda的地盘13 小时前
Reprojection 模式
flutter·性能优化
Yesheldon13 小时前
高度电路中时序设计之二
嵌入式硬件·fpga开发·硬件架构·硬件工程·智能硬件