在图像修复中使用有限元方法求偏微分方程

时间:2017-03-25 15:19:31

标签: image matlab pixels pde finite-element-analysis

如何遍历损坏的灰度图像,修复其中的所有已损坏像素而不检查未损坏的像素?

非常感谢任何帮助。

P.S。我有一个算法通过插入周围的像素来修复损坏的像素,但我不能在整个图像上使用这个算法因为它需要太长时间。

这是算法(伪代码):

Ek[m, n] = Ik[m − 1, n] + Ik[m + 1, n]+ Ik[m, n − 1] + Ik [m, n + 1] − 4I[m, n]
Ik+1[m, n] = Ik[m, n] + α Ek[m, n]

其中误差是Ek,α是系数,Ik是第k次迭代的图像。

1 个答案:

答案 0 :(得分:2)

据我了解你的问题,你正在寻找一种迭代2D阵列的每个像素的方法,并在你发现"损坏的"时执行某些操作。像素。不知道如果你的定义是"损坏了",我会假设"已损坏"你的意思是isnan - 不是数字。那么你的算法没有任何意义(因为你将NaN平均化为你的校正像素值,这将给你一个NaN)。因此,我将假设算法只是将像素完全替换为它最接近的非对角线邻居的平均值:

Ak+1[m, n] = 1/4 * ( Ak[m − 1, n] + Ak[m + 1, n]+ Ak[m, n − 1] + Ak [m, n + 1] )

如果我事实上误解了你,那么无论如何你都希望能够形成我的答案。

首先:

% Make a sample 'corrupted' array
A = rand(100,100);
A(A>0.9) = NaN; % ~10% corrupted

现在,如果两个损坏的像素彼此相邻,并且在阵列的边缘处,则该算法失败,这个问题变得复杂。我们稍后会担心。

简单(但不工作)的方法

您可以使用

找到所有损坏的像素
nA = isnan(A); % Boolean array the size of A where each corrupted pixel value is equal to 1

并且,如果您愿意,可以使用

获取其索引
I = find(nA); % Finds the indices of the above using linear indexing
[m,n] = find(nA); % Finds the indices using subscript indexing

如果你是Matlab的新手,这里有一个有趣的读物可能是:" logical arrays"," find"和" linear indexing"。 我们还需要A的大小,所以我们将其放入工作区

sA = size(A);

然后迭代所有索引并应用算法。

for j = 1:length(I)
    i = I(j); %j'th index
    [m,n] = ind2sub(sA,i); % Change linear indices to subscripts
    A(m,n) = 1/4 * ( A(m−1,n) + A(m+1,n)+ A(m,n−1) + A(m,n+1) );
end

更复杂(实际工作)的方法

如前所述,当周围存在边缘时,以及当有两个或更多NaN(可以认为是一个微小的边缘)时,算法会出现问题。为了处理边缘问题,我们将围绕边框和make your image into a torus(虽然1像素padding也可以工作)。然后,我们将迭代A,根据最近邻居方法替换像素。我不得不允许3和2邻居替换使其在严重损坏的图像上工作。可以轻松修改代码以阻止它。无论如何,这是工作的例子:

A = peaks(100);
A(rand(size(A))>0.3) = NaN; % 70% corrupted image
sA = size(A);

nrep = [1 1 1]; % Initialise as nonzero
imagesc(A); drawnow; % Show what is happening
while any(isnan(A(:)))
    getA = @(m,n) A(mod(m-1,sA(1)-1)+1,mod(n-1,sA(2)-1)+1); % Wrap the image around the edges
    numA = @(m,n) sum(isnan([getA(m+1,n),getA(m-1,n),getA(m,n+1),getA(m,n-1)])); % Number of neighbouring NaNs
    for j = 1:numel(A);
        if isnan(A(j));
            [m,n] = ind2sub(sA,j);
            switch numA(m,n)
                case 0
                    cA = 1/4 * ( getA(m-1,n) + getA(m+1,n) + getA(m,n-1) + getA(m,n+1) );
                    nrep(1) = nrep(1) + 1;
                case 1
                    cA1 = 1/3 * ( getA(m+1,n) + getA(m,n-1) + getA(m,n+1) );
                    cA2 = 1/3 * ( getA(m-1,n) + getA(m,n-1) + getA(m,n+1) );
                    cA3 = 1/3 * ( getA(m-1,n) + getA(m+1,n) + getA(m,n+1) );
                    cA4 = 1/3 * ( getA(m-1,n) + getA(m+1,n) + getA(m,n-1) );
                    cAs = [cA1 cA2 cA3 cA4];
                    ok = ~isnan(cAs); ok = find(ok,1); % find first cA# which is not a NaN
                    cA = cAs(ok);
                    nrep(2) = nrep(2) + 1;
                case 2
                        cA1 = 1/2 * ( getA(m+1,n) + getA(m,n+1) );
                        cA2 = 1/2 * ( getA(m+1,n) + getA(m,n-1) );
                        cA3 = 1/2 * ( getA(m-1,n) + getA(m,n+1) );
                        cA4 = 1/2 * ( getA(m-1,n) + getA(m,n-1) );
                        cA5 = 1/2 * ( getA(m+1,n) + getA(m-1,n) );
                        cA6 = 1/2 * ( getA(m,n+1) + getA(m,n-1) );
                        cAs = [cA1 cA2 cA3 cA4 cA5 cA6];
                        ok = ~isnan(cAs); ok = find(ok,1); % find first cA# which is not a NaN
                        cA = cAs(ok);
                        nrep(3) = nrep(3) + 1;
                case 3
                    continue
                case 4
                    continue
            end
        A(j) = cA; % Replace element
        end
    end
    imagesc(A); drawnow; pause(0.01); % Show what is happening
end

注释掉imagesc的线条以抑制绘制数字(看起来很酷;))。代码有点摇摇欲坠,可以进行很多改进,但它的工作原理很好:

原始

Original

重建形成50%的腐败

50% corruption

重建70%的腐败

70% corruption

Hive-mind方法(我的首选方法)

了解google的内容,从而得到this段代码。根据需要进行调整。