-1

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

任何帮助将不胜感激。

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

这是算法(伪代码):

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]

其中error是Ek,α是一个系数,Ik是第k次迭代的图像。

4

1 回答 1

2

据我了解您的问题,您正在寻找一种迭代二维数组的每个像素并在发现“损坏”像素时执行一些操作的方法。不知道您对“损坏”的定义是什么,我假设您所说的“损坏”是指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 的新手,这里的有趣读物可能是:“逻辑数组”、“查找”和“线性索引”。我们还需要大小,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 时(您可以将其视为一个很小的边缘),该算法会出现问题。为了处理边缘问题,我们将环绕边框并使您的图像变成一个圆环(尽管 1 像素的填充也可以)。然后,我们将通过 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以抑制绘制图形(看起来很酷;))。该代码有些摇摇欲坠,可以改进很多,但它的工作原理非常好:

原来的

原来的

重建形式 50% 腐败

50% 腐败

重建70%的腐败

70% 腐败

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

知道用谷歌搜索什么,从而得到这段代码。根据需要进行调整。

于 2017-03-25T18:23:40.107 回答