【问题标题】:Creating Filter's Laplacian Matrix and Solving the Linear Equation for Image Filtering创建滤波器的拉普拉斯矩阵并求解图像滤波的线性方程
【发布时间】:2014-06-03 13:41:12
【问题描述】:

为了过滤图像,我有一个优化问题要解决。
我创建了一个处理稀疏矩阵的问题的线性方程。

首先我会展示问题。
一、问题的拉普拉斯(邻接)矩阵:

矩阵 Dx / Dy 是前向差分算子 -> 因此它的转置是后向差分算子。
矩阵 Ax / Ay 是对角矩阵,其权重是图像梯度的函数(逐点,即该值仅取决于该像素本身的梯度)。
权重为:

其中 Ix(i) 是输入图像在第 i 个像素处的水平梯度(当对输入图像进行矢量化时)。

假设输入图像 G -> g = vec(G) = G(:)。
我想找到并成像 U -> u = vec(U) = U(:) s.t.:

我的问题是:

  1. 如何有效地构建矩阵 Dx / Dy / Ax / Ay(它们都是稀疏的)?
  2. 通过设置M = (I + \lambda * {L}_{g}),有没有优化的方式直接创建M?
  3. 在 MATLAB 中解决此线性问题的最佳方法是什么?有没有办法绕过内存限制(即处理大图像并且仍然能够解决它)?
  4. 有没有开源库可以在内存资源有限的情况下解决?任何带有 MATLAB API 的库?

谢谢。

【问题讨论】:

  • 您可以使用sparse 命令构建稀疏矩阵。如果您知道那些非零条目的行和列索引以及这些数字在那些非零位置中应该是什么,您可以轻松地在稀疏中构建它。要开始构建矩阵,请慢慢开始并使用for 循环制作它们。我们希望确保您正确获取矩阵。一旦你这样做了,你可以简单地应用 \ 运算符来求解逆,并且非常针对稀疏矩阵进行了优化。
  • 对于开源库,\ 的速度几乎与您将得到的一样快。有 iterative 方法,以防 \ 由于内存限制而无法工作。你可以看看连续的过度放松方法。以下是一些帮助您入门的代码:github.com/burakbayramli/kod/blob/master/books/Olver/sor.mw是控制方法收敛的权重,在0 < w < 2之间。
  • @rayryeng,你能帮我完成第一个“循环”步骤吗?谢谢。
  • 您能否进一步了解DxDy 的结构?
  • 它们是应用前向差分的矩阵算子。在 MATLAB 中,我认为您可以通过 diff(eye(size(inputImage))) 获得它。

标签: matlab image-processing optimization mathematical-optimization


【解决方案1】:

鉴于您的 cmets,让我们在概要中回答每个问题,然后从那里开始:

  1. 我将使用sparse 和其他相关函数回答下面的问题
  2. 使用 (1),我们绝对可以以优化的方式构建 M
  3. 简单地说,\ 运算符是求解逆时的最佳选择。 MathWorks 花了很多时间来优化它,而且它在后台几乎使用了 LAPACK 和 BLAS,如果你不使用它会发疯的。在 (4) 中回答了您唯一无法使用它的情况。
  4. 有一些 MATLAB 脚本可以迭代地处理矩阵求解,例如连续过度松弛技术,但您应该只在内存不足时使用这些脚本(即如果 \ 没有给您答案)。由于矩阵的稀疏表示,这不应该(希望)发生,所以让我们暂时避免使用这些函数。

回到您的问题,我们可以很好地生成L_g 的稀疏表示。给定DxDy 的定义,我们可以使用eye 命令的sparse 版本,称为speye。因此,DxDy 可以通过 Dx = diff(speye(size(inputImage))); 计算得到。例如,如果您尝试在 7 x 5 图像上执行此操作,将会产生这样的结果。

>> diff(speye(7,5))

ans =

(1,1)       -1
(1,2)        1
(2,2)       -1
(2,3)        1
(3,3)       -1
(3,4)        1
(4,4)       -1
(4,5)        1
(5,5)       -1

如您所见,我们仅引用非零条目。第 1 行第 1 列的系数为 -1,第 1 行第 2 列的系数为 1,依此类推。至于你的AxAy,这也很容易做到。我们有一个对角矩阵,我们可以手动设置每个条目。我们要做的就是指定一组行索引、列索引以及每个点的值。因此,我们可以这样做:

inputImage = im2double(inputImage); %//Important
rows = 1 : numel(inputImage); %// Assuming a 2D matrix
cols = rows; % // Row and column indices are the same
valuesDx = exp(-(gradX(rows).^2 / 2*sigma*sigma ));
valuesDy = exp(-(gradY(rows).^2 / 2*sigma*sigma ));

第一次调用的原因是因为我们要确保像素是双精度的,因为在 MATLAB 中求逆需要您这样做。它还确保我们不会溢出类型,因为我们正在规范 0 和 1 之间的强度。您可能需要调整标准偏差以反映这一点。现在我们只需要构造我们的AxAy 矩阵,我们把它和DxDy 放在一起:

numberElements = numel(inputImage);
Ax = sparse(rows, cols, valuesDx, numberElements, numberElements);
Ay = sparse(rows, cols, valuesDy, numberElements, numberElements);
identity = speye(numberElements, numberElements); 
Dx = diff(identity);
Dy = Dx.'; %// Transpose

我之所以将Dx 转置为Dy,是因为垂直方向上的差异运算符应该只是转置(对我来说很有意义)。这些都应该是您想要的每个矩阵的稀疏表示。矩阵运算也可以在稀疏矩阵上执行,包括乘法和逆。因此:

Lg = Dx.' * Ax * Dx + Dy.' * Ay * Dy;

您现在可以通过以下方式求解u

u = (identity + lambda*Lg) \ g;

这假定g 的结构是您的图像中的像素采用column-major 格式。我对像素进行采样以构建 AxAy 的方式自然遵循这一点。因此,请执行g = inputImage(:);,假设我们已转换为双精度并在 0 和 1 之间进行归一化。

当您最终解决 u 时,您可以通过以下操作将其重新整形为图像:

u = reshape(u, size(inputImage, 1), size(inputImage, 2));

u 也可能是稀疏的,所以如果你想要返回原始图像,请使用full() 投射它:

u = full(u);

希望这会有所帮助!

【讨论】:

  • @Drazick 您需要任何进一步的帮助吗?
  • @Drazick - ...那么发生了什么事伙计?这有帮助吗?
  • 嗨,不知怎的,我错过了。让我在接下来的几周内尝试一下。谢谢你!!!我现在会 +1。
  • 顺便说一下,任何库都可以在内存资源有限的情况下解决这种特征向量问题(实际上,对于 6000x4000 像素的大图像,即使是 8GB 也会受到限制,因此任何实用的求解器都需要能够做到资源有限)。
猜你喜欢
  • 2011-04-28
  • 2019-02-02
  • 2013-09-21
  • 2021-11-18
  • 1970-01-01
  • 2020-07-05
  • 2011-02-02
  • 2023-03-24
  • 2019-05-01
相关资源
最近更新 更多