33
$\begingroup$

I found this cat a month ago, and I'm not his owners' friend so the mosquito grid was the inevitable problem. I would like to post-process this photo to get rid of it, but I don't know exactly how this should be done and it would be interesting to see what can you do with this.

meow

UPD: link to higher resolution (4928x3264) and quality (fixed)

$\endgroup$
  • 2
    $\begingroup$ Maybe find the Fourier transform of the mosquito grid and subtract that from the frequency domain? It does seem to be quite a regular pattern. $\endgroup$ – LLlAMnYP Jul 17 '15 at 14:50
  • 3
    $\begingroup$ My immediate thought is to use Inpaint, but then the problem becomes: how do I find an appropriate mask for Inpaint... $\endgroup$ – Arnoud Buzing Jul 17 '15 at 14:58
  • 2
    $\begingroup$ Somewhat ... i1 = Import["http://i.stack.imgur.com/XroGQ.jpg"]; truncate[data_, f_] := Module[{i, j}, {i, j} = Floor[Dimensions[data]/Sqrt[f]]; PadRight[Take[data, i, j], Dimensions[data], 0.] ]; id = Transpose[ImageData[i1, "Byte"], {3, 2, 1}]; t = FourierDCT /@ ((256 - #) & /@ id); fdct = FourierDCT[truncate[#, 50], 3] & /@ t; rfdct = Round[fdct]; ImageReflect[ ColorCombine[Image[#, "Byte"] & /@ ((256 - #) & /@ rfdct)], Left -> Top] $\endgroup$ – Dr. belisarius Jul 17 '15 at 15:47
  • $\begingroup$ The above by using FourierDCT docs example $\endgroup$ – Dr. belisarius Jul 17 '15 at 15:47
  • 5
    $\begingroup$ That cat looks pissed. $\endgroup$ – kale Jul 17 '15 at 16:08
54
$\begingroup$

Here's a crude first attempt: First find the mosquito grid using RidgeFilter

img = Import["http://i.stack.imgur.com/XroGQ.jpg"];
ridges = ImageAdjust[ColorConvert[RidgeFilter[img, 2], "Grayscale"]]

enter image description here

(Note that I'm using ColorConvert after RidgeFilter, so RidgeFilter can find ridges in all color channels. Since RidgeFilter is nonlinear, the order makes a difference.)

Next, binarize with a low threshold to get a mask:

mask = MorphologicalBinarize[ridges, {0.05, 0.5}]

enter image description here

And finally: use Inpaint magic (where Diffusion is a compromise between quality and time):

Inpaint[img, mask, Method -> "Diffusion"]

enter image description here

I've played around with a few alternatives for mask, but none of them produced significantly better results, so I'm sticking with the KISS version. Maybe someone else can use this as a basis for a better reconstruction.


ADD In response to @Rahul's comment, here's a different mask that removes more of the grid, and also darker parts of the grid.

I'm using two separate LoG filters for the X- and Y-parts of the grid

logX = ImageData@LaplacianGaussianFilter[img, {50, {1, 20}}];
logY = ImageData@LaplacianGaussianFilter[img, {50, {20, 1}}];

I then use the square (to get dark and bright details)...

{logX, logY} = Map[Total, #^2, {2}] & /@ {logX, logY};

and rescale the resulting grid with the "average grid brightness" in the area, to get a more or less homogeneous image of the grid:

{logX, logY} = 
  Rescale[#/(GaussianFilter[#, 10] + 10^-10)] & /@ {logX, logY};

grid = Image[Rescale@(logX + logY)];

enter image description here

which I then binarize:

mask = MorphologicalBinarize[Image@grid, {0.15, 0.5}]

enter image description here

and use for inpainting:

res = Inpaint[img, Dilation[mask, 1], Method -> "Diffusion"]

enter image description here

A zoom on the cat's face shows that the grid is mostly gone:

ImageTrim[res, {{1130, 630}}, 200]

enter image description here

but so are details of the whiskers, and every edge in the image has "grid-shaped artifacts" from the inpainting.

$\endgroup$
  • 4
    $\begingroup$ the cat looks well satisfied, +1. $\endgroup$ – user9660 Jul 17 '15 at 17:24
  • 4
    $\begingroup$ That's a pretty fine result for a "first crude attempt"! +1, despite the first sub-result looking like Satan's cat ;-) $\endgroup$ – ciao Jul 17 '15 at 21:39
  • 1
    $\begingroup$ Well, if you zoom in, you can still see the grid, and the whiskers look more like "dashed" lines. Room for improvement, but I don't think you can get much further with Inpaint $\endgroup$ – Niki Estner Jul 18 '15 at 6:25
  • 1
    $\begingroup$ I think the reason the grid is still left is because RidgeFilter looks for thin bright ridges, so in the regions where the grid is darker than the background, RidgeFilter is selecting parts not in the grid to be part of the mask. For illustration, take a look at ImageMultiply[img, mask] and zoom in on the white window frame behind the cat. Not sure what would be a better way of doing it though. $\endgroup$ – Rahul Jul 22 '15 at 3:46
  • $\begingroup$ Thank you for answer. You might be willing to apply and tweak your solution to the same photo with higher resolution and quality. I've used Google Drive hosting instead of default Imgur -- see question UPD. $\endgroup$ – Nakilon Jul 23 '15 at 10:34
13
$\begingroup$

I tried the FFT idea just to see what it looks like. Here is a very quick and dirty version

t = 80;
fft = Table[Fourier[img[[All, All, x]]], {x, 1, 3}];
fft[[All, t ;; 1356 - t, All]] = 0;
fft[[All, All, t ;; 2048 - t]] = 0;
red = Image[Re[InverseFourier[fft[[1, All, All]]]]];
green = Image[Re[InverseFourier[fft[[2, All, All]]]]];
blue = Image[Re[InverseFourier[fft[[3, All, All]]]]];
ImageAdjust[ColorCombine[{red, green, blue}, "RGB"], .7]

Cat after low pass filtering

Probably could be improved with a more sophisticated approach (wavelets?)

$\endgroup$
  • $\begingroup$ Thank you for answer. You might be willing to apply and tweak your solution to the same photo with higher resolution and quality. I've used Google Drive hosting instead of default Imgur -- see question UPD. $\endgroup$ – Nakilon Jul 23 '15 at 10:34
  • 1
    $\begingroup$ Well it was just a quick experiment as nikie's method produced very good results. I'll take another look, but I wasn't able to access the link for the higher resolution image (I get 403 forbidden). $\endgroup$ – user9444 Jul 23 '15 at 16:28
  • $\begingroup$ Sorry about 403. Fixed now. $\endgroup$ – Nakilon Jul 23 '15 at 19:44
  • $\begingroup$ Played around with it quite a bit. Tried creating a mask to improve the result. Nothing really worked that well. It seems like there 'should' be a way to improve it, but none of my experiments accomplished much. $\endgroup$ – user9444 Jul 24 '15 at 2:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.