Just a FYI post…
For next version 3.5.1 of G’MIC, I’ve implemented a new math function abscut()
(and its associated native command abscut
), and I’d like to say a word of two about it here.
1. How abscut()
is defined?
It’s actually a simple math function that takes 4 arguments, and compute:
\text{abscut}(x,m,M,o) = \text{sign}(x)\;\text{cut}(|x| + o,m,M)
where
\text{sign}(x) = \left\{\begin{array}{lcr}-1 & \text{if} & x<0\\0 & \text{if} & x=0\\1 & \text{if} & x>0\end{array}\right.
and
\text{cut}(x,m,M) = \left\{\begin{array}{lcr}m & \text{if} & x<=m\\x & \text{if} & m<x<M\\M & \text{if} & x>=M\end{array}\right.
It is intended to “do something on x” (details in next section ).
In practice, this mathematical function can be used directly in the G’MIC math evaluator (e.g. in conjunction with commands fill
or eval
, like in fill "abscut(i,0,1,0)"
), or with the new pipeline command abscut min,max,offset
.
2. What it does?
Not sure you’ll understand the interest of abscut
directly from the equations (I wouldn’t have!), so basically what abscut
does to a value x is:
- It keeps the sign of x unchanged.
- It clamps and/or shifts its absolute value |x|.
That’s all: A pretty cool function to control the range of the “amplitude” of a value, without having to care about its sign.
So to sum up :
- m is the minimum absolute value allowed for \text{abscut}(x).
- M is the maximal absolute value allowed for \text{abscut}(x).
- o is an offset applied to the absolute value of x.
3. Let me see that!
I illustrate the use of abscut
with a toy example. We start from a sinusoidal 1D signal:
$ gmic 1024,1,1,1,"X=cos(20*x/w)" plot
This signals ranges from -1
to 1
, and intersects the x-axis.
Now, you can easily apply a maximal threshold on the absolute value of this signal, so to saturate the extremum values of the sine:
$ gmic 1024,1,1,1,"X=cos(20*x/w);abscut(X,0,0.7)" plot
which would be equivalenty obtained using:
$ gmic 1024,1,1,1,"X=cos(20*x/w);X<-0.7?-0.7:X>0.7?0.7:X" plot
(but see how much complex is the latter ).
Or you can do the opposite: You can also use abscut
to impose a minimal absolute value, like this:
$ gmic 1024,1,1,1,"X=cos(20*x/w);abscut(X,0.25,inf)" plot
And in this case, your signal is either strictly higher than 0.25 or lower than -0.25.
Of course, you can mix the two, to have both a lower and a higher threshold:
$ gmic 1024,1,1,1,"X=cos(20*x/w);abscut(X,0.25,0.75)" plot
In the examples above, I’ve only use the m and M arguments of abscut()
.
Finally, let’s illustrate the role of the offset o, first with a positive offset:
$ gmic 1024,1,1,1,"X=cos(20*x/w);abscut(X,0,inf,1)" plot
which is basically equivalent to:
$ gmic 1024,1,1,1,"X=cos(20*x/w);X<0?X-1:X+1" plot
But you can also use a negative offset:
$ gmic 1024,1,1,1,"X=cos(20*x/w);abscut(X,0,inf,-0.5)" plot
And in this case, it is equivalent to:
$ gmic 1024,1,1,1,"X=cos(20*x/w);X>0?max(0,X - 0.5):min(0,X + 0.5)" plot
I like this toy example of a simple sinusoidal signal, because it clearly shows the different behaviors of the abscut()
function. And it shows that the different equivalent formulations (that do not use abscut()
) look very different.
3. But, in which situation does I need this?
Personally, I’ve implemented this function because I needed it for the development of my nn_lib
: Often, I had to deal with the usual numerical trick to avoid “division by zero” cases.
Basically, when you have to compute a fraction a/b
, you have to be sure that b
is non zero (and even not too close from zero), to avoid a/b
returning inf
or very large values that would lead to numerical instabilities.
The classical trick is to write a/(eps + b)
or a/max(eps,b)
where eps
is a small value, like 1e^-8. But that works only when b
is >=0.
Now, I’m able to write a/abscut(b,1e-8)
or a/abscut(b,0,inf,1e-8)
and I’m good.
But I’m pretty sure there are lot of other use cases where abscut()
can help.
If you think of one in particular, don’t hesitate to share your thoughts