I’ve added a new command rand_pdf
in the G’MIC standard library today, and I’d like to show you what it is about. It is a surprisingly short function (5 actual lines of G’MIC code ), but it’s still pretty cool I think.
As its name suggests, this command generates random numbers that follow a custom (user-defined) probability density function (pdf).
When generating random numbers (e.g. with command noise
or rand
), we implicitely deal with pdf that are either uniform or gaussian functions. The figure below shows those pdf and the corresponding noisy image you get.
With rand_pdf
, you are now able to specify a custom pdf, as a discrete 1D function passed to the command.
But what’s it all for? I’m not going to lie, this could be useful mainly to developers of future new filters or commands. I propose you a few examples of use below:
Generating “exotic” kind of noise.
Suppose I’d like to generate a 256x256 image of noise that contains only values 10
,128
and 245
, but each having a difference probablity of occurence. Let’s say the value 10
should appear 3 \times more than 128
, which itself should appear 3 \times more than 245
.
Now, that’s easy! →
$ gmic 256,1,1,1,"x==10?9:x==128?3:x==245?1:0" 256,256 rand_pdf. ..,0,255 o. out1.png
This generates this image:
We can verify that the histogram of this output image indeed looks like the pdf we used for command rand_pdf
:
$ gmic out1.png histogram 256,0,255 plot
And it works for quite exotic pdf, like:
foo :
1024,1,1,1,"abs(cos(x/100))" # Define custom pdf
400,400,1,3 rand_pdf. ..,0,255 # Generate noisy image
# Visualize result.
+histogram. 1024,0,255
dg[0,2] 640,400,3,0,0,255
to[0] "User-defined pdf"
to[1] "Noisy image"
to[2] "Histogram of noisy image"
frame 1,1,0
a x
gives this:
So, good point, now it’s super easy to generate noisy data that follow a custom distribution in G’MIC.
Hiding data in noisy image.
But wait, if we can generate noisy image according to any distribution we want, why not hiding a “message” in an image by representing the message in the distribution of the generated pixel values ?
Ok, let’s do it.
foo :
# Generate 16bits pdf (65536 values), from a 256x256 image.
sp colorful,256 luminance. y. x
# Generate noisy color image that follow this distribution.
1024,1024,1,3 rand_pdf. ..,0,65535,1e7
o. out3.png
Generates this 1024x1024 image (it’s a 16bits .png image) :
Now, let’s check we are able to retrieve the hidden message. We just takes the 16bits histogram of this image, and view the 65536 values of the histogram as a 256x256 image, et voilà !
$ gmic out3.png histogram 65536,0,65535 r 256,256,1,1,-1 n 0,255 o message.png
and we see the secret hidden image appearing :
Isn’t it nice ?
Depending on the resolution of the generated noisy image, you’ll get more or less precision for the recovered data, as shown below:
Function code:
Well, that’s it for now. I’ll finish with the function code, as I’ve added it to the standard G’MIC library. As you can see, it’s quite short
#@cli rand_pdf : [probability_density_function],_min_value,_max_value,_precision>0
#@cli : Fill selected images with random values which follow the given probability distribution.
#@cli : Default values: 'min_value=-1', 'max_value=1' and 'precision=65536'.
#@cli : (1,0,1) 50,50 rand_pdf[1] [0],0,255
#@cli : 256 gaussian[-1] 30 500,500 line[-1] rand_pdf[-1] [-2],0,255 +histogram[-1] 256 display_graph[0,2] 640,480,3,0
rand_pdf : check ${"is_image_arg $1"}" && isnum(${2=-1}) && isnum(${3=1}) && isint(${4=65536}) && $4>0"
e[^-1] "Fill image$? with random values in [$2,$3], according to probability distribution $1, with precision $4."
# Compute normalized cumulated density function (cdf).
pass$1 0 y. x max. 0 cumulate. *. {($4-1)/i[-1,2]}
# Compute inverse cdf.
$4,1,1,1,">begin(k = 0); while (p = i[#-1,k]; k<w#-1 && (!p || p<x), ++k); lerp($2,$3,k/(w#-1-1))" rm..
# Sample random numbers according to given pdf.
f[^-1] "ind = int(lerp(0,w#-1,u))%w#-1; i[#-1,ind]" rm.
Hope you enjoyed this post, and that you will find plenty of cool uses for this new command rand_pdf
!