4

I want to create binary images by upsampling a series of greyscale images (192 x 144 resolution) by a factor of 10 with the new pixel values being a pseudorandom distribution of 0's & 1's based on the original grey level value. The new resolution would be 1920 x 1440.

Here is a small example of a greyscale image:

i = Image[{{0.16, 0.22, 0.32}, {0.73, 0.06, 0.13}, {0., 0.86, 0.18}}, ImageSize->100]

enter image description here

The following function gives the desired result for such small images/arrays:

SeedRandom[123]
resize[dat_] :=
 Map[SparseArray[
  Partition[
   RandomSample[
    ConstantArray[0, IntegerPart[(1 - #)*100]]~Join~
     ConstantArray[1, IntegerPart[100 #]]
  ], 10]] &, dat, {2}]

s = resize[ImageData@i]; bin = ArrayFlatten[s]; Image[bin, ImageSize -> 100]

enter image description here

However, when I try to uses it for a larger image ArrayFlatten gets upset...

SeedRandom[123]
bigi = Image@RandomReal[1, {50, 50}, WorkingPrecision -> 2]

enter image description here

ArrayFlatten[resize[ImageData@bigi]]

enter image description here

Obviously, I am stepping outside of ArrayFlatten's defined parameters, but I am unable to decipher the meaning of the error message...

Why is this happening?

Is there a simpler way to achieve my desired result for larger greyscale images?

geordie
  • 3,693
  • 1
  • 26
  • 33

2 Answers2

3

Maybe using RandomChoice works better (it does so for me).

f[img_, k_] := Image[ArrayFlatten[
    Map[
     RandomChoice[{1 - #, #} -> {0, 1}, {k, k}] &,
     ImageData[img],
     {2}
     ]
    ]];

Example:

f[ExampleData[{"Texture", "Bark"}], 5]
Henrik Schumacher
  • 106,770
  • 7
  • 179
  • 309
  • This works, although the cell tally's have a probabilistic weight rather than an exact representation of the grey-value. I'm still curious as to why this would be easier for ArrayFlatten to handle for large images than shuffling two ConstantArray's and partitioning. Is it a packed-/unpacked-array issue? – geordie Oct 11 '20 at 00:10
3

This method is short, but slow at higher resolutions:

ImageApply[RandomVariate@*BernoulliDistribution, ImageResize[img, {100, 100}]]

Instead, it makes more sense to pre-generate a random image first which is much faster at high resolutions:

With[{dims = {1920, 1440}}, 
 Binarize[ImageSubtract[ImageResize[img, dims], RandomImage[1, dims]],0]]

See also my answer here.

flinty
  • 25,147
  • 2
  • 20
  • 86
  • Fascinating! While the original pixel shapes are obliterated, the overall binary distributions appear to be spatially similar. – geordie Oct 11 '20 at 00:08