Here's a crude first attempt: First find the mosquito grid using RidgeFilter
img = Import["https://i.sstatic.net/XroGQ.jpg"];
ridges = ImageAdjust[ColorConvert[RidgeFilter[img, 2], "Grayscale"]]
(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}]
And finally: use Inpaint
magic (where Diffusion
is a compromise between quality and time):
Inpaint[img, mask, Method -> "Diffusion"]
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)];
which I then binarize:
mask = MorphologicalBinarize[Image@grid, {0.15, 0.5}]
and use for inpainting:
res = Inpaint[img, Dilation[mask, 1], Method -> "Diffusion"]
A zoom on the cat's face shows that the grid is mostly gone:
ImageTrim[res, {{1130, 630}}, 200]
but so are details of the whiskers, and every edge in the image has "grid-shaped artifacts" from the inpainting.
Inpaint
, but then the problem becomes: how do I find an appropriate mask forInpaint
... $\endgroup$i1 = Import["https://i.sstatic.net/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$FourierDCT
docs example $\endgroup$