Update
Silvia proposed a much faster algorithm that I believe produces I uniform distribution.
Here is my implementation of it.
pointsInMask2[mask_Image, n_Integer, range : {_, _} : {0, 1/2}] :=
Reverse @ ImageData @ Binarize[mask, range]\[Transpose] //
SparseArray[#]["NonzeroPositions"] & //
RandomChoice[#, n] + RandomReal[{-1, 0}, {n, 2}] &
img = Import["https://i.sstatic.net/yoPNX.png"];
Graphics[{
AbsolutePointSize[1], Opacity[0.3],
pointsInMask2[img, 75000] // Point
}]
The optional range parameter specifies the range of values in the mask image that are valid target area.
Graphics[{
AbsolutePointSize[1], Opacity[0.3],
pointsInMask2[img, 75000, {1/2, 1}] // Point
}]
A "brute force" method
Although my first method will be superior if one wishes to generate many points there is a more direct and simple approach, though it does not benefit from any of the optimizations in the linked question. That is simply to generate random points and select the ones for which the matching ImageValue
is closer to black than white. This requires redundant sampling and will be increasingly slow on images with a small percentage of black pixels. (For now I am simply estimating the number of samples needed and not performing a check to make sure the requested number are actually produced; if this method proves useful I shall refine my approach.)
pointsInMask[mask_Image, n_Integer] :=
Module[{dims, pts, n2},
dims = ImageDimensions[mask];
n2 = ⌈ 1.1 n #/(# - ImageData[mask] ~Total~ 2) &[Times @@ dims] ⌉;
pts = RandomReal[#, n2] & /@ dims // Transpose;
Select[pts, ImageValue[mask, #] < 0.5 &, n]
]
Test:
mask = Binarize @ Import["https://i.sstatic.net/yoPNX.png"]
pts = pointsInMask[mask, 5000];
Graphics[{AbsolutePointSize[1], Point @ pts}]
RandomReal[{-1, 1}, 2]
on it. $\endgroup$RandomReal
pair within that "cell"; do this as many times as points are needed. Are you going to write that up as an answer? $\endgroup$