Generic contour smoothing with shading

Update: Collecting the steps in a function:

ClearAll[smoothCP]
smoothCP = Module[{pr = PlotRange @ #, 
  nF =  Nearest[Join @@ Cases[Normal @ #, Line[a_] :> Transpose[#2 /@ Transpose@a], ∞]]},
  # /. GraphicsComplex[a_, b__] :> GraphicsComplex[ 
    If[Or @@ MemberQ @@@ Thread @ {pr, #}, #, First @ nF @ #] & /@ a, b] ] &;

Examples:

p1 = ContourPlot[x^2 + y^2 + RandomReal[{-0.1, 0.1}], {x, -2., 2.}, {y, -2., 2.}, 
     PlotPoints -> 6, Contours -> 4, ContourStyle -> Thick, ImageSize -> 400]; 
Row[{p1, smoothCP[p1, GaussianFilter[#, {5, 5}] &]}]

enter image description here

Row[{p1, smoothCP[p1, GaussianFilter[#, 2.5]&]}] 

enter image description here

Row[{p1, smoothCP[p1, GaussianFilter[#, {25, 25}] &]}] 

enter image description here

Row[{p1, smoothCP[p1, Downsample[#, 4]&]}] 

enter image description here

p2 = ContourPlot[x^2 + y^2 + RandomReal[{-0.1, 0.1}], {x, -2., 2.}, {y, -2., 2.}, 
   PlotPoints -> 6, Contours -> 4, ContourStyle -> Thick, 
   ContourShading -> False, ImageSize -> 400]; 
Row[{p2, smoothCP[p2, GaussianFilter[#, {5, 5}] & ]}] 

enter image description here

lcp = ListContourPlot[Table[Sin[j^2 + i] + 3 RandomReal[{-0.05, 0.05}],
   {i, -Pi, Pi, 0.1}, {j, -Pi, Pi, 0.1}], Contours -> 2, ImageSize -> 400, 
   ColorFunction -> "Rainbow"];
Row[{lcp, smoothCP[lcp, GaussianFilter[#, 10] &]}, Spacer[5]]

enter image description here

Original answer:

pl = ContourPlot[ x^2 + y^2 + RandomReal[{-0.1, 0.1}], {x, -1, 1}, {y, -1, 1}, 
   Contours -> 3, PlotPoints -> 3, ContourStyle -> Thick, ImageSize -> 400];
pnts =  Join @@ Cases[Normal[pl],  Line[a_] :> 
   Transpose[GaussianFilter[#, {5, 5}]& /@ Transpose[a]], ∞]; 
nf = Nearest[pnts];

pl2 = pl /. GraphicsComplex[a_, b__] :>  
  GraphicsComplex[If[Or @@ (Abs[#] == 1. & /@ #), #, nf[#][[1]]] & /@ a, b];
Row[{pl, pl2}]

enter image description here


Mean curvature flow and Laplacian smoothing can also be applied to the graph of a piecewise linear function for smoothing. Here a very brief and imperfect demonstration (using the function GraphDiffusionFlow from the cited post):

RandomSeed[20180506];
mesh2D = DiscretizeRegion[Rectangle[{-1, -1}, {1, 1}], 
   MaxCellMeasure -> {1 -> 0.05}];
vals = With[{pts2D = MeshCoordinates[mesh2D]},
   (pts2D^2).ConstantArray[1., 2] + 
    RandomVariate[NormalDistribution[0, 0.075], Length[pts2D]]
   ];
mesh3D = MeshRegion[Join[pts2D, Partition[vals, 1], 2], 
   MeshCells[mesh2D, 2, "Multicells" -> True]];
smoothedmesh3D = GraphDiffusionFlow[mesh3D, 20, 0.1, 0.8];
g = GraphicsRow[{mesh3D, smoothedmesh3D}, ImageSize -> Large]

enter image description here

This how the resulting height function looks as ContourPlot away from the boundary.

f = Interpolation[pts3D, InterpolationOrder -> 1];
fsmoothed = 
  Interpolation[MeshCoordinates[smoothedmesh3D], 
   InterpolationOrder -> 1];
r = .8;
g = GraphicsRow[{
   ContourPlot[f[u, v], {u, -r, r}, {v, -r, r}, Contours -> 20],
   ContourPlot[fsmoothed[u, v], {u, -r, r}, {v, -r, r}, Contours -> 20]
   }, ImageSize -> Large]

enter image description here

However, the current boundary conditions for the 3D-flow are not well-suited for this task:

r = 1.;
g = GraphicsRow[{
   ContourPlot[f[u, v], {u, -r, r}, {v, -r, r}, Contours -> 20],
   ContourPlot[fsmoothed[u, v], {u, -r, r}, {v, -r, r}, Contours -> 20]
   }, ImageSize -> Large]

enter image description here

There are certainly ways to fix that, though.


Not perfect but a good start, the idea is to use your method to transform boundaries and then use this transformation rules for points used by original output:

pl = ContourPlot[
  x^2 + y^2 + RandomReal[{-0.1, 0.1}], {x, -1, 1}, {y, -1, 1}, 
  Contours -> 3, PlotPoints -> 3, ContourShading -> True, 
  ContourStyle -> Thick];

rules = Flatten@
  Cases[Normal[pl], 
   Line[a__] :> 
    Thread[a -> 
      Transpose@{GaussianFilter[First /@ a, {5, 5}], 
        GaussianFilter[Last /@ a, {5, 5}]}], \[Infinity]];

pl /. rules

enter image description here