G'MIC exercises

Sorry, I was editing the post as your were reading and also multitasking. Refer to post 551 for the outcome I would like; maybe output one column with coordinates and the other corresponding values. The input is a histogram where all other positions are 0. The output should also be a truncated set of columns. I only want to select the pixels that are within the subset defined by the conditional statement.

In the case of post 551, I expect to get something like this

 85 0.066667
 92 0.066667
104 0.066667
106 0.066667
108 0.133333
113 0.133333
114 0.066667
116 0.066667
117 0.066667
124 0.066667
125 0.066667
126 0.066667
128 0.066667

The second thought of 551 is whether we could get a text-based output in-console. I know it can be clumsy but for querying it could be helpful and saves me the stress from having to manage too many floating windows.

myprint :
  e[] {b}" = \n"
  v - eval. ">echo('   ',i)" v +
  e[] ""

And if you want to customize your input, specifically for your task, there shouldn’t be a problem:

both :

  # Create random normalized signal.
  64,1,1,1,'u<0.1' normalize_sum. nm. pdf

  # Extract locations of non-zero values.
  +extract. "i!=0",1

  # Print values.
  e[] "\n"{-2,b}" = \n"
  v - eval. ">X = i; echo('   ',X,' ',i[#0,X])" v +
  e[] ""

and then :

$ gmic both
[gmic]-0./ Start G'MIC interpreter.
[gmic]-0./both/ Input image at position 0, with values 'u<0.1' (1 image 64x1x1x1).
[gmic]-1./both/ Normalize image [0] with a unitary sum.
[gmic]-1./both/ Set name of image [0] to 'pdf'.
[gmic]-1./both/ Extract xyz-coordinates from image [0] verifying condition 'i!=0'.

pdf = 

   13 0.25
   29 0.25
   35 0.25
   63 0.25

[gmic]-2./ Display images [0,1] = 'pdf, [unnamed]_c1'.
[0] = 'pdf':
  size = (64,1,1,1) [256 b of floats].
  data = (0,0,0,0,0,0,0,0,0,0,0,0,(...),0,0,0,0,0,0,0,0,0,0,0,0.25).
  min = 0, max = 0.25, mean = 0.015625, std = 0.0609938, coords_min = (0,0,0,0), coords_max = (13,0,0,0).
[1] = '[unnamed]_c1':
  size = (1,4,1,1) [16 b of floats].
  data = (13;29;35;63).
  min = 13, max = 63, mean = 35, std = 20.8487, coords_min = (0,0,0,0), coords_max = (0,3,0,0).
[gmic]-2./ End G'MIC interpreter.

Thanks. Now that you spell it out, it is very simple to do. My habit of writing one-liners certainly doesn’t help. As for the gradient confusion, I see that I was copy-pasting the condition from your example instead of using my own.

One question is if I get the user input and they use the dot shortcut how would I change it to [index] output. Or more generally, if the user input was [index pattern], how would I simplify it to a more general form like [0,1,…]?

This is related to the question that I posed in post 492 and continued in post 518. I want to simplify the index and name outputs. The user can refer to the same images in any number of ways available, and the name could be the original or a copy, but I would like to output a simplified index and retain the name (whether it be the original or a copy).

That’s actually planned in 2.8.0_pre : Command pass will return a status containing the list of all image indices, so something like this will be possible:

e[^-1] "Do something on image$?, with argument images "${"-pass$2"}"."

Also, I’m planning to change a little bit how the verbosity is managed, so that there won’t be much v + and v - necessary in a command.
Work in progress… :slight_smile:

Now, I have a problem of my own.

isophotes 15
if w>h
    dx_a={.2*w}
    dx_b={w-$dx_a}
    dp={1/max($dx_a,$dx_b)}
else
    dy_a={.7*w}
    dy_b={h-$dy_a}
    dp={1/max($dy_a,$dy_b)}
fi

iter=1

do
    rx={(1-($iter*$dp))*w#0}
    rx={$rx<1?1:$rx}
    ry={(1-($iter*$dp))*h#0}
    ry={$ry<1?1:$ry}
    +r. $rx,$ry,100%,100%,2
    iter+=1
while w!=1&&h!=1
cut 0,255
r[^0] {w#0},{h#0},100%,100%,0,0,.2,.7
rv blend alpha

The problem here is pretty clear. I don’t want the result to be black. What can I do to remedy this issue?

EDIT:

I have partly remedied the issue with adding

sh 0,{s-2}
sh.. {s}
{w},{h},1,1,i#-1?0:1
inpaint_pde[1] [-1]
k[0]

EDIT:
I figured it out by using +r[0] $rx,$ry,100%,100%,5 instead.

EDIT:
One final issue - Getting it to look smooth.

#r 1280,780,100%,100%,0,0,.5,.5#
isophotes 15
sh 0,{s-2}
sh.. {s}
max_alpha={iM-1}
{w},{h},1,1,i#-1?0:1
inpaint_pde[1] [-1]
k[0]
if w>h
    dx_a={.125*w}
    dx_b={w-$dx_a}
    dp={1/max($dx_a,$dx_b)}
else
    dy_a={.5*w}
    dy_b={h-$dy_a}
    dp={1/max($dy_a,$dy_b)}
fi

iter=1

do
    rx={round((1-($iter*$dp))*w#0)}
    rx={$rx<1?1:$rx}
    ry={round((1-($iter*$dp))*h#0)}
    ry={$ry<1?1:$ry}
    +r[0] $rx,$ry,100%,100%,5
    iter+=1
while w!=1&&h!=1
r[^0] {w#0},{h#0},100%,100%,0,0,.125,.5
rv blend alpha

image

I could do subsampling, but then it would take me a longer time to render.

Command pass has now a new ‘mode’ that just returns the list of indices of selected images from the parent context.
From now (after recompiling of course), it is possible to write something as:

foo : 
  e[^-1] "Do something with images ["${"pass$1 3"}"]." 

Thanks David. I have been busy lately but I will definitely battle test and provide feedback for any of your changes. Usually do. :slight_smile:

I think I have decided to try to inverse transform the perspective effect, then transform to perspective. In between transform, streak at 90 angle. That’s a challenge of a filter.

I’ve posted new binary packages of the today’s pre-release, if it may help.

Actually, never mind. I realized that the 0 areas impossible to do with the fill transform that I was doing. I would need some math expert to help me on that. Picture 4 triangle, and the point are where all the triangle meet. Those are the if side. If one of them is 0, that means reversing the transform is impossible, and if they’re of different side, I’m going to end with bad interpolation.

Now that the earlier problem was solved [See earlier thread to see that I have solved the transformation problem] -
I’m having trouble making something work.

rep_test_val:
rm
repeat $#-3
    val={4+$>}
    orientation=${i=$val}
    1,1,1,1,$orientation
done
a x

See what I’m doing there? The output should be only numbers within argument 4 and above. I know I could do ($4–1), but however, I need to make the above work for a command I am working on. A snip of the command I’m working on is here.

        val={4+$>}
        orientation=${i=$val}
        if $orientation
            width={min($length_1,$length_2)}
            height={max($length_1,$length_2)}
        else
            width={max($length_1,$length_2)}
            height={min($length_1,$length_2)}
        fi

The closest I got to it was this which gives me error that includes $4 in it when there is 4 argument.

rep_test_val:
repeat $#-3
    val={4+$>}
    orientation="$"$val
    1,1,1,1,$orientation
done

The answer wasn’t easy to find, but here it is.

rep_test_val:
repeat $#-3
    $=val
    1,1,1,1,${val{$>+4}}
done

EDIT:
Now, what I would like to do is to be able to access original ratio of image within command, just before the commands.

#@cli rep_ratio_orientation:
rep_ratio_orientation:
ti=$!
u {"
if(w#0>h#0,ro=[0],ro=[1]);
for (k = 0, k<"$ti", ++k,
    if (w#k>h#k,tr=[0],tr=[1]);
    ro=[ro,tr];
);
(ro)"}

The above is my shoddy attempt at doing it. The reason why is that I would like to be able to do this with my rectangular polar transformation cli filter.

or={$-rep_ratio_orientation} rep_polrectrans 0,0,1,$or

The above command should work. I believe that this would be very useful for future filter. @David_Tschumperle

EDIT: Better attempt at $rep_ratio_orientation

Curious what the application of this would be.

@David_Tschumperle

@afre and I were having a PM conversation pertaining to getting pass to work in context of fill function. Right now, I would like to edit my modf command to allow for 2 different set of arguments, and eliminate the need for the 4th argument. The 2 arguments for $3 should be either images or number. He suggested to use pass, but I didn’t get it to work correctly, and he mentioned he didn’t get it to work in form of *[0] [1].

#@cli modf:
#@cli : (eq. to '_modular_formula').
#@cli : $ modf 3,255,{128/255},0 ,
modf : _modular_formula $*
#@cli _modular_formula : 0<=operation<=5,chan_v>0, 0<value[%]<=1,two_layers={0=Do not use layer as blending mode | two_layers=Use Layers as blending mode}
#@cli : Default value : 'two_layers=0'
_modular_formula :
skip ${4=0}
if {$1==0} f "eps=10^-8;img=i#0;vp=$4==1?i#1/$2:$3;mv=($2*vp)+eps;f=img-mv*floor(img/mv);f>$2*vp?$2*vp:f"
elif {$1==1} f "eps=10^-8;img=i#0;vp=$4==1?i#1/$2:$3;mv=($2*vp)+eps;nf=img-mv*floor(img/mv);minm=$2*vp;e=ceil((i#0/minm))%2>0?$2:0;cinv=i#0>0?e:$2;cinv>0?nf:mv-nf"
elif {$1==2} f "eps=10^-8;img=i#0;vp=$4==1?i#1/$2:$3;ivp=1/vp;simg=ivp*img;maxm=$2+eps;f=simg-maxm*floor(simg/maxm)"
elif {$1==3} f "eps=10^-8;img=i#0;vp=$4==1?i#1/$2:$3;ivp=1/vp;simg=ivp*img;maxm=$2+eps;f=simg-maxm*floor(simg/maxm);minm=$2*vp;e=ceil((i#0/minm))%2>0?$2:0;cinv=i#0>0?e:$2;cinv>0?f:$2-f"
elif {$1==4} f "eps=10^-8;img=i#0;vp=$4==1?i#1/$2:$3;vpi=vp*$2;fimg=img+vpi;maxm=$2+eps;fimg-maxm*floor(fimg/maxm)"
elif {$1==5} f "eps=10^-8;img=i#0;vp=$4==1?i#1/$2:$3;vpi=vp*$2;fimg=img+vpi;maxm=$2+eps;f=fimg-maxm*floor(fimg/maxm);cinv=fimg>maxm?$2:0;cinv>0?maxm-f:f" fi

This works in cases of two layers, but however I would have to assign 4 arguments and only be restricted into one layer. This is due to the fill function.

How would I modify it, so that modf[-1] 3,255,[-3] becomes valid and thus only 3 arguments would be needed while the 3rd argument can also take a number?

I know how it works, just not in your case ATM. I am not in that headspace, sorry. I am sure David or the others can help. :slight_smile:

Oh… you mean, either an image or a value? We’ve already discussed this somewhere.

Yes, as an image or value. If it has been discussed somewhere, I would like to know where.

On your thread. Ha ha.

Wrap with

if ${is_image_arg\ $3} pass$3 0 ... else ... fi
2 Likes

How exactly do I return coordinates for all non-alpha values within a radius within x,y,z coordinates? The first 3 coordinates would be the 0,0,0 relative point.

For codes on found in my thread:

#@cli rep_n0_alp_coords: eq. to 'rep_nonzero_alpha_count'. : (+)
rep_n0_alp_coords: rep_nonzero_alpha_coordinates
#@cli rep_nonzero_alpha_coordinates:
#@cli : Return the number of non-zero alpha of selected images.
#@cli : (eq. to 'rep_n0_alp_coords').
rep_nonzero_alpha_coordinates:
imgs={$!}
tna=${-rep_n0_alp_c}
tna={"sum("$tna")"}
tna*=3
u {"coordinates=vector"$tna"(0);mult=0;
for(img=0,img<"$imgs",img++,
    last_channel=s#img-1;
    for(pz=0,pz<d#img,pz++,
        for(py=0,py<h#img,py++,
            for(px=0,px<w#img,px++,
                if(i(#img,px,py,pz,last_channel)!=0,coordinates[mult*3]=px;coordinates[mult*3+1]=py;coordinates[mult*3+2];mult++;);
            );
        );
    );
);
(coordinates)
"}
#@cli rep_n0_alp_c: eq. to 'rep_nonzero_alpha_count'. : (+)
rep_n0_alp_c: rep_nonzero_alpha_count
#@cli rep_nonzero_alpha_count:
#@cli : Return the number of non-zero alpha of selected images.
#@cli : (eq. to 'rep_n0_alp_c').
rep_nonzero_alpha_count:
imgs={$!}
u {"num_alpha=vector"$imgs"(0);
for(img=0,img<"$imgs",img++,
    alpha_count=0;
    last_channel=s#img-1;
    for(pz=0,pz<d#img,pz++,
        for(px=0,px<w#img,px++,
            for(py=0,py<h#img,py++,
                if(i(#img,px,py,pz,last_channel)!=0,alpha_count++;);
            );
        );
    );
    num_alpha[img]=alpha_count;
);
(num_alpha)
"}

And this is an ongoing solution to solve this thread - Anything to autoconnect points within G'MIC?

That is loopy. I don’t think you need that many. Many functions already loop themselves, just as fill does.

Could you also explain your question using an actual example? Keep it dead simple. I am not quite sure what you want to do.