当前位置: 首页 > news >正文

【CUDA笔记】05 使用 AMGX 搭建泊松图像编辑

引言

前几节已经根据入门课程,了解了一些 CUDA 的使用技巧。 这一节想先跳出原本的课程节奏, 找点实际的应用,来看看能否从另一个角度练习一下 CUDA。

最后找到了话题 实现泊松图像编辑

类似如下的抠图编辑为 泊松图像编辑应用的一种。

输入:
在这里插入图片描述
输出
在这里插入图片描述
网上可以找到不少介绍 泊松图像编辑 的参考文章, 也可以先参考一下,了解原理与一些其他的应用

图像处理基础(九)泊松图像编辑 Possion Image Editing:https://zhuanlan.zhihu.com/p/453095752

泊松图像编辑(Possion Image Edit)原理、实现与应用:https://blog.csdn.net/weixin_43194305/article/details/104928378

不少文章的起点是 2003 年的这篇论文

《Poisson Image Editing》:https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf

本节尝试使用基于 CUDA 实现的AMGX 库,求解泊松方程,来实现泊松图像编辑。

主要梳理 泊松图像融合的原理如何使用 AMGX, 与本地试验结果

泊松图像融合的原理

泊松图像融合的大致思想是,当我们有一张 前景图 , 一张背景图, 一张通过标记 前景图中 感兴趣的区域(后面简称 ROI)后生成的 Mask 图, 通过最小化 前景图 与 背景图在ROI 范围内的像素梯度值的差异,实现前景图像 ROI 区域无缝地 融合到 背景图像 中。进而通过求导函数 = 0 ,取函数极值的思路,将求最小值问题转化为求导函数 = 0 的解。

前置概念

梯度(Gradient)

在这里插入图片描述
个人理解, 这里 梯度表示图像某个通道像素值沿着某个方向(x 或 y)的变化速度。每个像素对应一个向量, 表示包含沿着x 与 y 方向的变化速率。

常用于边缘检测(使用 Sobel 算子)

散度(Curl)

在这里插入图片描述
散度衡量向量场在某一点“发散”或“汇聚”的程度。

在图像处理中, 可以使用拉普拉斯算子来计算 图像梯度的 散度。

拉普拉斯算子

在这里插入图片描述
在数字图像中,像素是离散的,通常用卷积核来近似拉普拉斯算子。常见的 3×3 拉普拉斯核包括:
在这里插入图片描述

构建线性方程组 A * f = b

问题描述

设:

核心思想
在这里插入图片描述
将通过泛函的知识,将上述问题等价为求解泊松方程
在这里插入图片描述
在这里插入图片描述
其中:

可用共轭梯度法(CG)、多重网格法等高效求解。

扩展:混合梯度(Mixed Gradient)

在这里插入图片描述
此时构建方程组 右端的尝试项时, 便不可直接对 前景图应用拉普拉斯算子来求解, 而需要对该像素所在位置, 在两幅图上沿着各个方向求出梯度, 根据筛选条件选出四个方向(四个方向是对应前面的五点取样方法)的梯度值之后,再计算散度, 得到混合的右端项。

求解线性方程组 A * f = b

由于 A 是大型稀疏对称正定矩阵(在 Dirichlet 条件下),常用以下数值方法求解:

1. 共轭梯度法(Conjugate Gradient, CG)

  • 适用于对称正定系统;
  • 内存效率高,适合大图像;
  • 是泊松融合中最常用的迭代法之一。

2. Jacobi / Gauss-Seidel 迭代

算法基础信息可参考:https://zhuanlan.zhihu.com/p/389389672

3. 多重网格法(Multigrid Method)

算法基础信息可参考 https://zhuanlan.zhihu.com/p/337970166

4. 直接法(如稀疏 LU 分解)

  • 对小区域可行;
  • 大图内存消耗大,不实用。

使用 AMGX 求解线性方程组

AMGX(Advanced MultiGrid eXtensions)是由NVIDIA开发的一个高效、可扩展的库,专门用于解决大规模稀疏线性方程组。它特别适用于需要高性能计算的应用场景,如物理模拟、图像处理、机器学习等。AMGX通过利用GPU的强大并行计算能力,提供了解决复杂计算问题的有效手段。

源码地址:https://github.com/NVIDIA/AMGX

这次练习使用的是截自目前最新的 Release 版本, AMGX v2.4.0 (也已经是 23年了)

Cuda 12.4(虽然AMGX Release 日志里说是支持到 12.2,但处理一下,走下来,依赖 12.4 也是可以编译过)
在这里插入图片描述
Visual Studio 2022win11

子模块 Trust 没有下载源码仓库对应的版本,暂时直接使用的 CUDA Toolkit 中自带的版本( 使用 源码仓库对应的版本,出现了与 CUDA 版本的兼容问题,编译不过。这边尝试, 在执行 cmake 指令之前, 将 CMakeList.txt 的这一行注释掉, 以使用 CUDA Toolkit 中的版本)。

在这里插入图片描述

编译依赖库

代码拉下之后,在项目代码根目录下一次执行如下指令

mkdir build
cd build
cmake ../
make -j16 all

执行 cmake 指令的过程中可能会遇到如下 missing 的提示。 我这边因为暂时没有使用到 MPI 的特性(可以在多个 GPU 或多个计算节点上分布式求解大型稀疏线性方程组),先忽略跳过。
在这里插入图片描述
生成 的 AMG.sln 包含一以下几个项目中,
在这里插入图片描述

其中, amgx 项目生成静态链接库
在这里插入图片描述
amgxsh 项目生成动态链接库, 供运行时加载
在这里插入图片描述
本次试验中, 生成动态库 amgxsh 这个项目。
生成成功后,把 AMGX 源码中的 include 与 动态库挑出来出来就可以用了。

在这里插入图片描述

稀疏矩阵的存储格式

在该问题中的矩阵A,通常是稀疏矩阵(大部分元素是 0),前人们设计了一些格式,来节省矩阵存储空间, 优化存储效率。

因为这里借助 AMGX 求解问题, 会使用到 CSR 格式来存储矩阵, 作为数据输入。 所以这里补充一下 CSR 格式的基本信息。

values 数组(假设长度为 N)

  • 存储矩阵中所有非零元素的值。
  • 这些值按照从上到下、从左到右的行遍历顺序排列。

colIndices 数组(长度也为 N)

  • values 数组长度相同,用于存储 values 中每个元素对应的列索引。
  • 例如,如果 values 中的第 k 个元素是矩阵第 i 行、第 j 列的非零元素,那么 colIndices 中的第 看个元素就是 j

rowPointers 数组(长度为 Matrix 行数 + 1)

  • 长度为矩阵行数加一,用于指示每一行的第一个非零元素在 values 数组中的起始位置。

  • rowPointers[i] 记录的是第 i 行第一个非零元素在 values 中的索引。

  • 惯例上,rowPointers 数组的最后一个元素(即 rowPointers[n],其中 n 是矩阵的行数)通常存储为非零元素的总数 N 加上 1,这标志着最后一行元素的结束。

举个例子
考虑一个 4×4 矩阵:

在这里插入图片描述

步骤 1:按行遍历非零元
第 0 行:1(列0)、2(列2)
第 1 行:3(列1)
第 2 行:4(列0)、5(列2)、6(列3)
第 3 行:7(列3)
步骤 2:构建三个数组
数组 内容
values [1, 2, 3, 4, 5, 6, 7]
colIndices [0, 2, 1, 0, 2, 3, 3]
rowPointers [0, 2, 3, 6, 7]

本地试验结果

试验项目源码地址:https://github.com/CC9701/possionImageEditing

试验日志

[Time] 1. 读取图像 elapsed: 13 ms
All images loaded successfully.
Background size: [614 x 461]
Foreground size: [400 x 300]
Mask size: [400 x 300]
Warning: Image sizes do not match! Poisson fusion requires same dimensions.
Number of foreground pixels: 40800
[Time] 4. 构建线性方程组 Af = b elapsed: 45 ms
Linear system constructed successfully.
NonZeroValueVec size: 199952
Column index size: 199952
Row pointer size: 40801
AMGX version 2.4.0
Built on Nov 26 2025, 21:23:18
Compiled with CUDA Runtime 12.4, using CUDA driver 13.0
[Time]  5. 使用 AMGX 求解线性方程组 单个通道 elapsed: 1003 ms
[Time]  5. 使用 AMGX 求解线性方程组 三个通道 elapsed: 2365 ms
All three channels solved successfully.
[Time]  6. 合成结果图像 elapsed: 1 ms

融合结果

未使用梯度混合
在这里插入图片描述
可以看到飞机周围的一圈还是有一点糊
使用梯度混合
在这里插入图片描述
也可以根据实际情况再拓展一下 梯度混合的方式, 比如混合梯度筛选梯度时, 看看如何给不同来源的梯度值分配胜选的权重。

http://www.jsqmd.com/news/359286/

相关文章:

  • **AI仿真人剧制作工具2025推荐,解锁沉浸式内容创作新范
  • 58.DevOps进阶
  • P5713 【深基3.例5】洛谷团队系统
  • 小程序毕设项目:基于springboot+小程序的校园点餐系统小程序的设计与实现(源码+文档,讲解、调试运行,定制等)
  • Xget 使用指南
  • 告别徒手掏数据!给JSON配上“GPS导航”:JSONPath零基础入门
  • DP 超大杯训练
  • BISHI23 小红书推荐系统
  • 小程序计算机毕设之基于微信小程序的校园跑腿小程序基于springboot+小程序的校园跑腿小程序设计与实现(完整前后端代码+说明文档+LW,调试定制等)
  • Thymeleaf 核心用法全解析
  • 大数据BI工具的性能测试报告
  • 小程序计算机毕设之基于springboot和mysql的模拟驾校考试系统基于springboot+小程序的驾校考试模拟系统小程序(完整前后端代码+说明文档+LW,调试定制等)
  • 实用指南:使用 Apache Jena 构建 Java 知识图谱
  • 企业智能体系统架构的存储方案:AI应用架构师的选型指南
  • 【毕业设计】基于springboot+小程序的驾校考试模拟系统小程序(源码+文档+远程调试,全bao定制等)
  • Redis集群搭建及验证
  • 小程序毕设项目推荐-基于SpringBoot+Vue+Uniapp的校园任务通平台微信小程序设计与实现【附源码+文档,调试定制服务】
  • 小程序毕设项目推荐-基于springboot+小程序的城市公交查询系统线路查询、站点搜索设计与实现【附源码+文档,调试定制服务】
  • 基础功能能否满足需求?10款主流AI效率工具深度评测
  • 小程序毕设选题推荐:基于微信小程序的城市公交查询系统的设计与实现基于springboot+小程序的城市公交查询系统设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】
  • 游戏规则从来不是“1%的人定的”,而是“人性定的”:突破困境的关键,不是“对抗规则”,不是“抱怨1%的人”,而是“突破人性弱点,聚焦自己的价值,掌握规则的主动权”
  • 项目开发中代码合并全流程解析
  • Excel革命!Python让表格处理从“加班到哭”到“准时下班”
  • 小程序毕设选题推荐:基于springboot+小程序的校园跑腿小程序设计与实现基于SpringBoot+Vue的校园跑腿小程序的设计与实现【附源码、mysql、文档、调试+代码讲解+全bao等】
  • 构建之法阅读笔记1
  • 洛谷P2518
  • 【Docusarous】首页增加链接形式进入文档
  • Excel数据分析太慢?Python让你秒变报表大神,三天搞定一个月工作
  • AI系统灾备职业发展:架构师如何提升竞争力?
  • 为什么好心的金钱奖励,反而杀死了孩子的自律与热爱:人有两种动力:内在动机、外在动机。当强外在物质奖励,介入本身有内在动机的行为时,内在动机会被逐渐驱逐,行为最终依赖外部奖励,一旦奖励消失/不足,行为立