G'MIC exercises

Image size is 800x600. The big artefact is the line from the centre to the right of the image.

Sorry, poor choice of words. I can clearly see the artifact. What I meant is when I use test_angular_blur myself I don’t get a problem so I wonder what the setting is.

There are no problems besides this artefact.

Using convolve_FFT instead of regular blur was finally easier than expected. This version of blur_angular doesn’t exhibit the boundary artefact anymore:

#@cli blur_angular : amplitude[%],_center_x[%],_center_y[%]
#@cli : Apply angular blur on selected images.
#@cli : Default values: 'center_x=center_y=50%'.
#@cli : $ image.jpg blur_angular 2%
#@cli : $$
blur_angular : skip ${2=50%},${3=50%}
  e[^-1] "Apply angular blur on image$?, with amplitude $1 and center point ($2,$3)."
  v - euclidean2polar $2,$3,1.3,1
  repeat $! l[$>] 1,100% =. 1,50%,50% b. y,$1 convolve_fft.. . rm. endl done
  polar2euclidean $2,$3,1.3,1 v +

This has been pushed in the updateXXX.gmic, so this should be available after a filter refresh, or $ gmic up.
Let me know if that fixes your issues.

1 Like

@Joan_Rake1 hah I think we’ll leave it there, I’m obviously struggling to express the question properly. David has solved it anyway!

Two additional comments maybe:

  1. The usual blur command (and derivative) does not manage periodic or mirrored boundary conditions, mainly because it is based on fast recursive filters that do not handle these boundary conditions easily (by nature). Fortunately, FFT-based filtering is, on the contrary, tied to the use of periodic boundary conditions by nature. So they are complentary, and this was our luck :slight_smile:
  2. (brag) I must say I love using G’MIC so much when I see I’m able to change the core of the blur_angular algorithm with a one-liner :heart_eyes:

Amazing, butter-smooth. I suggest using a power or a square for the exponential to give greater control for lesser blurs and access to higher blurs:

#@gui : Amplitude = float(0.4,0,3)

ac "blur_angular {(($1)^2.5)*5}%,$2%,$3% sharpen $4",$6,$7

There is a minimum blur between 0.1-0.2 but that would require a more precise and more CPU-intensive FFT algorithm.

I like the idea of having the blur amplitude proportional to a number of pixels, i.e. spatial distance. Having a non-linear variation wouldn’t be intuitive to me.
I can still increase the higher bound to allow even more blurry results (tried with 20 instead of 10 and I don’t really see why people would like to go above this :slight_smile: ).

20 is a good maximum but it means that on a GUI it’s harder to have control over less-intense blurs, for which the differences are more noticeable with small changes in blur amplitude. I use powers and whatnot across many of my filters for similar reasons.

Glad someone else is using this thread. Makes it more meaningful. :+1:

I have a new problem for you to solve. So far, I have only been doing things in a haphazard way. I find a way to select the offending lights (e.g., high chroma) and then inpaint or desaturate them. However, it leaves much to be desired. I could probably better address it in the raw processor or clone / heal it in GIMP but, hey, why not attempt something in G’MIC? :slight_smile:

Preview (actual file oog.zip (3.7 MB))


Sorry @afre this is really bad, not only hijacking again but avoiding your question! I doubt I can answer it well in any case since I avoid colour space issues as much as possible :slight_smile:

I’ve been looking at poisson disc noise and one of the first things a search returns is this paper coupled with this example public domain source code in c++, both of which look really quite simple (honestly!). Simple enough that I might even attempt in g’mic, but it does use lists/arrays with removable elements which I think might be awkward in gmic.

On to the question: is there already something in gmic for poisson disc noise and if not is there a good way to implement it? What are the chances of it being added to cimg?

Edit: I think now this might not be the type of “break” you were looking for!

I don’t think so at a first glance.

To CImg, probably very few chances :slight_smile: To G’MIC, high chances, if we get an implementation as a G’MIC script :slight_smile:

Not so awkward. There are already some commands that make use of list/arrays with removable elements. But, as there are several ways to do it, it requires some experience to choose the best way to do it. It can be done inside a math expression, or in a more regular pipeline.
What matters is for instance :

  • The number of elements you’ll have to manage in your list.
  • Will you have to add or remove elements only at the end or beginning of the list, or on arbitrary positions ?
  • What is the type of each element ? Can they be stored with a fixed number of values, or are they themselves of arbitrary size ?

Are you able to provide some of those? The most obvious is the image stack itself but it has some noticable overhead if the list is large. I don’t mind reading through them myself of course. Indeed the size of the data will determine the best method, what I’ll probably do is prototype it in an obvious way then optimise (once I get an idea of the extents).

For instance, command colormap implements the median-cut algorithm that needs to partition the RGB space using a dynamic list of blocs. In this case, the list is indeed stored in the image stack itself.

Another example is command _pixelsort which implements a stack with push() and pop() functions in a local vector variable. It can be done because we know the maximal size a vector can have.
I think this should be quite easy to have a kind of dynamic list structure in the math parser. I’ll take a break and try writing an example now. Stay tuned :slight_smile:

1 Like

So here is an example of using the math expression compiler to manage a list as a vector variable. The only real constraint here is to know a maximal number of elements. Insertion and removal of elements in the list can be done at arbitrary index, and should be reasonably fast (thousands of insertions should be OK).
I’ve written only two functions insert() and remove() that manage only insertion and removal of one element at a time, but of course we can do this easily for multiple insertions / removals if needed (not sure you need it).

The code below does nothing more than initializing such a list, inserting and removing some elements and display the result on the console. Nothing really sexy, but at least this shows how to set up such a dynamic structure easily.

test :
  eval "
    list = vector16();
    siz_list = 0;

    # Macro that insert a new element 'elt' into the list, at index 'pos' ('pos' must be in [0,siz_list]).
    insert(elt,pos) = (
      _pos = pos;
      if (_pos<=siz_list,
        copy(list[_pos+1],list[_pos],siz_list - _pos);
        list[_pos] = elt;

    # Macro that remove an element from the list, located at index 'pos' ('pos' must be in [0,siz_list]).
    remove(pos) = (
      _pos = pos;
      if (_pos<=siz_list,
        copy(list[_pos],list[_pos+1],siz_list - _pos);
        list[siz_list] = 0;

    echo('---- Initial state ------------');
    print(list,siz_list); # Empty list.


    echo('---- After three insertions ---');
    print(list,siz_list); # List with three elements.


    echo('--- After one removal ---------');
    print(list,siz_list); # List with two elements.

EDIT : note that this can be done exactly by storing the data in an image defined in the image stack. In this case, we don’t have to worry about a maximal size as we can resize the image on the fly directly in the math parser if needed.

Good example thanks, I’ve not yet used macros in the math parser! It’s obviously a commonly required algorithm type, therefore very useful to know :slight_smile:

Edit: should’ve added, yes it’s random single elements being removed so this fits the case perfectly.

I’ll write one version that stores the data in an image stack instead, just to show it is as easy. As we can manage several images at the same time, this means having multiple dynamic lists is possible.

Here is a version with an image rather than a vector :

test :

  i[list] 1,1,1,3,-1  # List of RGB colors

  eval "

    # Macro that inserts a new element 'elt' into the image #ind, at index 'pos' ('pos' must be in [0,siz_list]).
    insert(ind,siz_list,elt,pos) = (
      _pos = pos;
      if (_pos<=siz_list,
        for (k = 0, k<s#ind, ++k, copy(i(#ind,_pos+1,0,0,k),i(#ind,_pos,0,0,k),siz_list - _pos));
        I[#ind,_pos] = elt;

    # Macro that removes an element from the image #ind, located at index 'pos' ('pos' must be in [0,siz_list]).
    remove(ind,siz_list,pos) = (
      _pos = pos;
      if (_pos<=siz_list,
        for (k = 0, k<s#ind, ++k, copy(I(#ind,_pos,0,0,k),I(#ind,_pos+1,0,0,k),siz_list - _pos));
        I[#ind,siz_list] = -1;

    siz_list = 0;

    echo('---- Initial state ------------');
    print(#"$list"); print(siz_list); # Empty list.

    insert(#"$list",siz_list,[ 0,128,0 ],0);
    insert(#"$list",siz_list,[ 64,0,0 ],0);
    insert(#"$list",siz_list,[ 0,0,255 ],2);

    echo('---- After three insertions ---');
    print(#"$list"); print(siz_list); # List with three elements.


    echo('--- After one removal ---------');
    print(#"$list"); print(siz_list); # List with two elements.
1 Like

No problem. Actually list and element manipulation were the first things I tried, with limited success, when I encountered G’MIC scripting (which was not that long ago; am still a relatively new user :slight_smile:). If I stare at your discussions long enough, I might learn something. Still struggling to follow the math and code but it is fun nevertheless. :blush:

PS All of you can make it up by looking into An Error Reduction Technique in Richardson-Lucy Deconvolution Method. :wink:

Actually I already had a look, not certain whether it applies generally because it appears directed towards a particular form of noise. I suspect some of the maths will be outside what I know just now anyway, so much to learn!