如何高效地找到并去除1个像素带的图像强度变化?
How to efficiently find and remove 1 pixel bands of image intensity changes?
我们在着色器的法线贴图上有一些视觉伪像,因为一些单像素带与其周围环境形成鲜明对比。需要明确的是,边缘不是问题,只是这些单个像素带。
在这种情况下,使用典型的 Sobel 边缘检测之类的东西将不起作用,因为在这样的带之上,它会检测到 0。我可以想到对内核进行的其他修改可能会起作用,例如
-1 -2 -1
2 4 2
-1 -2 -1
但我假设可能有一种 "correct" 数学方法来执行这样的操作。
最后,我想使用周围的像素来平滑这些线条(因此是选择性模糊)。这些线条可以出现在任何方向,所以如果我要使用上面的内核,我需要在两个方向上应用它并添加它以获得类似于应用 Sobel 内核时的线条强度。
我假设您的图像中有 1 像素宽的线条比周围环境更亮或更暗,您想要找到它们并将它们从图像中移除,并用局部邻域的平均值替换移除的像素.
我为此开发了一种算法,它适用于我的示例数据(因为您没有提供任何数据)。它有两部分:
识别行
我想不出一个简单而有效的过滤器来检测线(它们是相连的,因此可能需要查看相关性)。所以我使用了一个简单的单像素检测过滤器:
-1 -1 -1
-1 8 -1
-1 -1 -1
然后是一些合适的阈值。
将掩码外的数据外推到掩码
一个非常优雅的解决方案(仅使用卷积)是将掩码外的数据与高斯函数进行卷积,然后采用负掩码与相同的高斯函数进行卷积,然后将两者按像素划分。蒙版内的结果是所需的模糊。
数学上的含义:数据的加权平均。
这是我的幻像数据:
这是行的标识
而最后的结果表明失真被抑制了十倍:
最后是我的代码(在 Matlab 中):
%% create phantom data with lines (1pixel wide bands)
[x, y] = ndgrid(1:100, 1:100);
original = 3 * x - 2 * y + 100 * sin(x / 2) + 120 * cos(y / 3); % funny shapes
bw = original > mean(original(:)); % black and white
distortion = bwmorph(bw,'remove'); % some lines
data = original + max(original(:)) * distortion; % phantom
% show
figure();
subplot(1,3,1); imagesc(original); axis image; colormap(hot); title('original');
subplot(1,3,2); imagesc(distortion); axis image; title('distortion');
subplot(1,3,3); imagesc(data); axis image; title('image');
%% line detection
% filter by single pixel filter
pixel_filtered = filter2([-1,-1,-1;-1,8,-1;-1,-1,-1], data);
% create mask by simple thresholding
mask = pixel_filtered > 0.2 * max(pixel_filtered(:));
% show
figure();
subplot(1,2,1); imagesc(pixel_filtered); axis image; colormap(hot); title('filtered');
subplot(1,2,2); imagesc(mask); axis image; title('mask');
%% line removal and interpolation
% smoothing kernel: gaussian
smooth_kernel = fspecial('gaussian', [3, 3], 1);
smooth_kernel = smooth_kernel ./ sum(smooth_kernel(:)); % normalize to one
% smooth image outside mask and divide by smoothed negative mask
smoothed = filter2(smooth_kernel, data .* ~mask) ./ filter2(smooth_kernel, ~mask);
% withing mask set data to smoothed
reconstruction = data .* ~mask + smoothed .* mask;
% show
figure();
subplot(1,3,1); imagesc(reconstruction); axis image; colormap(hot); title('reconstruction');
subplot(1,3,2); imagesc(original); axis image; title('original');
subplot(1,3,3); imagesc(reconstruction - original); axis image; title('difference');
我们在着色器的法线贴图上有一些视觉伪像,因为一些单像素带与其周围环境形成鲜明对比。需要明确的是,边缘不是问题,只是这些单个像素带。
在这种情况下,使用典型的 Sobel 边缘检测之类的东西将不起作用,因为在这样的带之上,它会检测到 0。我可以想到对内核进行的其他修改可能会起作用,例如
-1 -2 -1
2 4 2
-1 -2 -1
但我假设可能有一种 "correct" 数学方法来执行这样的操作。
最后,我想使用周围的像素来平滑这些线条(因此是选择性模糊)。这些线条可以出现在任何方向,所以如果我要使用上面的内核,我需要在两个方向上应用它并添加它以获得类似于应用 Sobel 内核时的线条强度。
我假设您的图像中有 1 像素宽的线条比周围环境更亮或更暗,您想要找到它们并将它们从图像中移除,并用局部邻域的平均值替换移除的像素.
我为此开发了一种算法,它适用于我的示例数据(因为您没有提供任何数据)。它有两部分:
识别行
我想不出一个简单而有效的过滤器来检测线(它们是相连的,因此可能需要查看相关性)。所以我使用了一个简单的单像素检测过滤器:
-1 -1 -1
-1 8 -1
-1 -1 -1
然后是一些合适的阈值。
将掩码外的数据外推到掩码
一个非常优雅的解决方案(仅使用卷积)是将掩码外的数据与高斯函数进行卷积,然后采用负掩码与相同的高斯函数进行卷积,然后将两者按像素划分。蒙版内的结果是所需的模糊。
数学上的含义:数据的加权平均。
这是我的幻像数据:
这是行的标识
而最后的结果表明失真被抑制了十倍:
最后是我的代码(在 Matlab 中):
%% create phantom data with lines (1pixel wide bands)
[x, y] = ndgrid(1:100, 1:100);
original = 3 * x - 2 * y + 100 * sin(x / 2) + 120 * cos(y / 3); % funny shapes
bw = original > mean(original(:)); % black and white
distortion = bwmorph(bw,'remove'); % some lines
data = original + max(original(:)) * distortion; % phantom
% show
figure();
subplot(1,3,1); imagesc(original); axis image; colormap(hot); title('original');
subplot(1,3,2); imagesc(distortion); axis image; title('distortion');
subplot(1,3,3); imagesc(data); axis image; title('image');
%% line detection
% filter by single pixel filter
pixel_filtered = filter2([-1,-1,-1;-1,8,-1;-1,-1,-1], data);
% create mask by simple thresholding
mask = pixel_filtered > 0.2 * max(pixel_filtered(:));
% show
figure();
subplot(1,2,1); imagesc(pixel_filtered); axis image; colormap(hot); title('filtered');
subplot(1,2,2); imagesc(mask); axis image; title('mask');
%% line removal and interpolation
% smoothing kernel: gaussian
smooth_kernel = fspecial('gaussian', [3, 3], 1);
smooth_kernel = smooth_kernel ./ sum(smooth_kernel(:)); % normalize to one
% smooth image outside mask and divide by smoothed negative mask
smoothed = filter2(smooth_kernel, data .* ~mask) ./ filter2(smooth_kernel, ~mask);
% withing mask set data to smoothed
reconstruction = data .* ~mask + smoothed .* mask;
% show
figure();
subplot(1,3,1); imagesc(reconstruction); axis image; colormap(hot); title('reconstruction');
subplot(1,3,2); imagesc(original); axis image; title('original');
subplot(1,3,3); imagesc(reconstruction - original); axis image; title('difference');