Closing Holes in Images

Post a reply


This question is a means of preventing automated form submissions by spambots.
Smilies
:D :) ;) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :!: :?: :idea: :arrow: :| :mrgreen: :geek: :ugeek:

BBCode is ON
[img] is ON
[flash] is OFF
[url] is ON
Smilies are ON

Topic review
   

Expand view Topic review: Closing Holes in Images

Re: Closing Holes in Images

Post by Creator » Mon Jun 06, 2011, 15:14

It is also possible to use OpenCV Inpainting methods.
Read more here http://en.wikipedia.org/wiki/Inpainting

Re: Closing Holes in Images

Post by Creator » Mon May 16, 2011, 17:31

The algorithm first calculates the mask which designates pixels, belonging to holes. Then the hole pixels are initialized with the "last-good-value" from previouse pixels. That is done in order to speed up the convergence, but also multigrids could be applied. Afterwards the the linear diffusion (the Laplassian filter) is applied. Here is one result of processing a test image (the black color stay for the hole region):
cat.jpg
Original image with a hole (black-color-coded)

cat_closed.jpg
Restored image

Closing Holes in Images

Post by Creator » Thu May 12, 2011, 00:28

Here I suggest to concider an "CloseHoles" algorithm, based on linear interpolation. The algorithm is realized by application of an iterative linear diffusion process to the areas of arbitrary image, marked as hole.
How about to optimize its main loop or discuss some more sophisiticated algorithms ?

Code: Select all

void closeHoles()
{
   const int nIt = 250;      // Number of iterations
   
   register int x, y;
   register int c, i;
   Mat tmp;

   // Creating mask for informative pixels. (for simplicyty, pixel values = 0, are holes => mask there is 0, otherwise 1)
   cvtColor(*this, tmp, CV_RGB2GRAY);
   Mat mask(this->size(), CV_8UC1);
   mask.setTo(1);
   for (x = 0; x < this->cols; x++)
      for (y = 0; y < this->rows; y++)
         if (tmp.at<unsigned char>(y,x) == 0) mask.at<unsigned char>(y,x) = 0;
   tmp.release();
   erode(mask, mask, Mat());
   
   // Converting "this" image to floating-point tmp image.
   this->convertTo(tmp, CV_MAKETYPE(CV_32F, this->channels()));

   vector<Mat> channels(tmp.channels());
   split(tmp, channels);
   // Initializing holes to speed up convergence (for simplicity)   
   float val = 0;
   for (c = 0; c < tmp.channels(); c++)
      for (x = 0; x < tmp.cols; x++)
         for (y = 0; y < tmp.rows; y++) {
            if (mask.at<unsigned char>(y,x) == 0) channels[c].at<float>(y,x) = val;
            val = channels[c].at<float>(y,x);
         }
   
   // Main Loop
   for (c = 0; c < tmp.channels(); c++) {
      Mat buf;
      channels[c].copyTo(buf);
      for(i = 0; i < nIt; i++) {
         for (x = 1; x < tmp.cols - 1; x++)
            for (y = 1; y < tmp.rows - 1 ; y++)
               if (mask.at<unsigned char>(y,x) == 0) buf.at<float>(y,x) = 0.25f * (channels[c].at<float>(y,x+1) + channels[c].at<float>(y,x-1)+channels[c].at<float>(y+1,x)+channels[c].at<float>(y-1,x));
         buf.copyTo(channels[c]);
      } // j
   } // i
   merge(channels, tmp);
   mask.release();

   for (c = 0; c < tmp.channels(); c++) channels[c].release();
   channels.clear();

   tmp.convertTo(*this, this->type());
   tmp.release();
}

Top