【问题标题】:Inpaint an image matlab [duplicate]修复图像matlab [重复]
【发布时间】:2016-06-03 05:06:30
【问题描述】:

我正在尝试用邻居的平均值替换图像中具有特定值的所有像素。 interp2 在这里有用吗?我试过这个 -

I = imread('test_image.JPG');
[r c] = size(I);
class_of_image = class(I);
[xi,yi] = meshgrid(1:0.5:c,1:0.5:r);
I1 = cast(interp2(double(image),xi,yi,'linear'),class_of_image);

[x_z,y_z] = find(I1==0);
I1(x_z,y_z) = I1(x_z-1,y_z)+I1(x_z+1,y_z)+I1(x_z,y_z-1)+I1(x_z,y_z+1);

这会失败并显示错误消息 - 索引超出矩阵维度。

我意识到错误在于尝试访问 r 和 c 之外的 I1 索引。有没有一种通用的方法可以将其合并到代码中?

请帮忙!

【问题讨论】:

  • 附带说明一下,fileexchange 上有一个函数,inpaint_nans

标签: image matlab image-processing interpolation pixel


【解决方案1】:

如果您尝试将图像中某个值的像素替换为其 4 个相邻像素的平均值,则不必使用interp2。看起来您将图像的大小加倍,然后在完成后从该图像中采样。

如果您想按照您的要求进行操作,您需要使用列主索引来促进像素的矢量化访问。具体来说,您需要使用sub2ind 来帮助确定您需要在矩阵中访问的位置。

但是,您需要考虑超出范围的像素。有很多方法可以适应这种情况,但我将实现的称为 zero-padding,其中边框像素简单地设置为 0。我将创建一个零填充图像,其中顶部和底部行以及左右值都是一些标记值(如-1),在此图像上使用find找到坐标然后进行修复。确保在执行此操作之前将边框像素设置回 0,以免在修复过程中使用 -1。完成后,您将裁剪此新图像的边框像素以获得最终输出图像。

因此,如果您想执行“修复”,请尝试以下操作:

% Read in image
I = imread('test_image.JPG');

% Create padded image with border pixels set to -1
Ipad = -ones(size(I) + 2);

% Place image in the middle
Ipad(2:end-1,2:end-1) = I;

% Find zero pixels
[r,c] = find(I == 0);

% Now set border pixels to 0
Ipad(Ipad == -1) = 0;

% Find column major indices for those elements that are 0
% as well as their 4 neighbours
ind = sub2ind(size(I), r, c);
ind_up = sub2ind(size(I), r-1, c);
ind_down = sub2ind(size(I), r+1, c);
ind_left = sub2ind(size(I), r, c-1);
ind_right = sub2ind(size(I), r, c+1);

% Perform the inpainting by averaging
Ipad(ind) = (Ipad(ind_up) + Ipad(ind_down) + Ipad(ind_left) + Ipad(ind_right))/4;

% Store the output in I1 after removing border pixels
I1 = Ipad(2:end-1,2:end-1);

但是,即使您要对整个图像进行操作,执行此操作的一种可能更短的方法是使用 3 x 3 内核执行 2D 卷积,其元素在基数方向上为 1,并确保除以 4 以找到每个位置的平均值。之后,您只需复制输出中原始图像中为 0 的值。您可以使用conv2 来执行此操作,并确保指定'same' 标志以确保输出大小与输入大小相同。 conv2 在您接近边框元素时的行为是零填充,这是我在第一个实现中所做的:

% Read in image
I = imread('test_image.JPG');

% Specify kernel
kernel = [0 1 0; 1 0 1; 0 1 0] / 4;

% Perform convolution - make sure you cast image to double
% as convolution in 2D only works for floating-point types
out = conv2(double(I), kernel, 'same');

% Copy over those values from the output that match the value
% to be inpainted for the input.  Also cast back to original 
% data type.
I1 = I;
I1(I == 0) = cast(out(I == 0), class(I));

【讨论】:

  • 你有我的 +1 卷积。卷积永远是答案。
  • @Suever 当然是!
  • @rayryeng- 非常感谢。我做了 interp2 只是为了让值更接近。我尝试了卷积方法 - 现在如果我尝试在 I1 中找到零,它必须返回 null 对吗?情况似乎并非如此。 find(I1==0) 沿着索引列表返回。
  • @Learner 应该。我在几个测试图像上进行了尝试。例如,尝试I = reshape(1:25, 5, 5); I([2 6 10 19 24]) = 0;,然后使用上面的代码进行修复。您将看到最终输出没有零。您可能设置所有零的原因是浮点精度。因此,不要与精确的 0 进行比较,而是找到某个容差范围内的值……也许是 0.5 之类的值。我无法判断它是否有效,因为您尚未提供要对其执行此操作的示例图像。
  • @rayryeng - 我上传了一张测试图像,但该方法失败了。足够高的阈值也不起作用。我真的很感谢所有的帮助!我确实在应用卷积之前将其转换为灰度。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-03
  • 2011-10-19
  • 2013-08-05
相关资源
最近更新 更多