Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

remove the holes in an image by average values of surrounding pixels

Gray Scale Image with Holes

can any one please help me in filling these black holes by values taken from neighboring non-zero pixels. thanks

like image 541
crack_addict Avatar asked Jul 05 '12 05:07

crack_addict


2 Answers

One nice way to do this is to is to solve the linear heat equation. What you do is fix the "temperature" (intensity) of the pixels in the good area and let the heat flow into the bad pixels. A passable, but somewhat slow, was to do this is repeatedly average the image then set the good pixels back to their original value with newImage(~badPixels) = myData(~badPixels);.

I do the following steps:

  1. Find the bad pixels where the image is zero, then dilate to be sure we get everything
  2. Apply a big blur to get us started faster
  3. Average the image, then set the good pixels back to their original
  4. Repeat step 3
  5. Display

You could repeat averaging until the image stops changing, and you could use a smaller averaging kernel for higher precision---but this gives good results:

enter image description here

The code is as follows:

numIterations = 30;
avgPrecisionSize = 16; % smaller is better, but takes longer

% Read in the image grayscale:
originalImage = double(rgb2gray(imread('c:\temp\testimage.jpg')));

% get the bad pixels where  = 0 and dilate to make sure they get everything:
badPixels = (originalImage == 0);
badPixels = imdilate(badPixels, ones(12));

%# Create a big gaussian and an averaging kernel to use:
G = fspecial('gaussian',[1 1]*100,50);
H = fspecial('average', [1,1]*avgPrecisionSize);

%# User a big filter to get started:
newImage = imfilter(originalImage,G,'same');
newImage(~badPixels) = originalImage(~badPixels);

% Now average to
for count = 1:numIterations
   newImage = imfilter(newImage, H, 'same');
   newImage(~badPixels) = originalImage(~badPixels);
end

%% Plot the results
figure(123);
clf;

% Display the mask:
subplot(1,2,1);
imagesc(badPixels);
axis image
title('Region Of the Bad Pixels');

% Display the result:
subplot(1,2,2);
imagesc(newImage);
axis image
set(gca,'clim', [0 255])
title('Infilled Image');

colormap gray

But you can get a similar solution using roifill from the image processing toolbox like so:

newImage2 = roifill(originalImage, badPixels);

figure(44);
clf;
imagesc(newImage2);
colormap gray

notice I'm using the same badPixels defined from before.

like image 140
Steve Avatar answered Oct 22 '22 02:10

Steve


There is a file on Matlab file exchange, - inpaint_nans that does exactly what you want. The author explains why and in which cases it is better than Delaunay triangulation.

like image 44
Andrey Rubshtein Avatar answered Oct 22 '22 01:10

Andrey Rubshtein