$\begingroup$

This solution uses Perlin noise to generate the blobs.

To generate the noise we use the following function. Here, range is the domain on which we will generate the noise, res is the number of points in x and y direction, and seed is the seed for the random number generator.

perlinNoise[range_: {{0, 1}, {0, 1}}, res_: {30, 30}, seed_: 1] := With[{ grid = (SeedRandom[seed]; Table[With[{t = RandomReal[2 Pi]}, {Cos[t], Sin[t]}], {res[[1]]}, {res[[2]]}]), intf = 3 #^2 - 2 #^3 &}, Function[{x, y}, Module[{ind, xr, yr, pmat}, (* ind=={{xmin,xmax},{ymin, ymax}} *) {xr, yr} = MapThread[Rescale[#1, #2, {1, #3}] &, {{x, y}, range, res}]; ind = Floor[{xr, yr}]; ind = MapThread[Min[#1, #2 - 1] &, {ind, res}]; {xr, yr} -= ind; pmat = {{{xr, yr}.grid[[ind[[1]], ind[[2]]]], {xr, yr - 1}.grid[[ind[[1]], ind[[2]] + 1]]}, {{xr - 1, yr}.grid[[ind[[1]] + 1, ind[[2]]]], {xr - 1, yr - 1}.grid[[ind[[1]] + 1, ind[[2]] + 1]]}}; {1 - intf[xr], intf[xr]}.pmat.{1 - intf[yr], intf[yr]}]]]

Next we're going to superpose some noise on top of a two-dimensional Gaussian function and we use ListContourPlot to plot the region where the resulting function is larger than some level (note that we could use RegionPlot as well, but ListContourPlot is faster). There are a lot of parameters to play with here, such as the resolution of the noise, the ratio between the noise and Gaussian surface, and the level of the contour. For example for

res = 30; seed = 3; level = .6; ratio = .15;

we get

f = perlinNoise[{{-1, 1}, {-1, 1}}, {res, res}, seed]; tab1 = Table[Exp[-(x^2 + y^2)] + ratio*f[x, y], {x, -1, 1, 1/(2 res)}, {y, -1, 1, 1/(2 res)}]; pl = ListContourPlot[ArrayPad[tab1, {{1, 1}, {1, 1}}], InterpolationOrder -> 2, Contours -> {level}, ContourShading -> None, Frame -> False]; pl/. {___, a__Line} :> FilledCurve[Thread[{{a}}]]

By increasing the ratio get more splattering:

res = 30; seed = 3; level = .6; ratio = .8;

And by lowering the resolution you get smoother blobs: