G'MIC exercises

I am aware of the parameters but have yet to give it a try. If you all could provide simple examples of each (command, stdout/display and diagram), that would be great.

Ok, I tried using this, but there’s no way to hide the dot from the preview portion of the screen without changing the output of it. What can I do about this? I used this on the Fibonacci GUI filter.

I feel like I’m missing something here… Why is this not smooth?

$ 512,512,1,1,x/50 pal autochrome3 {w#-2},{h#-2},1,3,I(#-1,i(#-2,x,y,0,0),0,0,2,2) k.

After zooming in:
image

What I’m trying to do is to create a smooth map where it is wrapped around with bicubic mode.

Looks periodic to me. What is it supposed to look like? You mean the start and end of the period should be a much smaller step in colour? There is a leap in green and a flip in red and blue.

The right (which is the problem image to solve) is supposed to look like the left though the left is using linear interpolation, and the right is using bicubic interpolation. So yes, there should be a smaller step in color and with bicubic interpolation.

I realized that cubic spline would solve this, however, I still don’t know how to code that in this context as I do not understand how that works. :confused:


@afre After looking at this page, I believe I have my solution - Cubic interpolation - Paulinternet.nl

rep_test_cubic:
512,1,1,1,"begin(
 const length=w-1;
 initial_array=[50,10,100,30];
 cubic_interpolation(pt,v)=(
  (-.5*pt[0]
  +1.5*pt[1]
  -1.5*pt[2]
  +.5*pt[3])*v^3
  +
  (pt[0]
  -2.5*pt[1]
  +2*pt[2]
  -.5*pt[3])*v^2
  +
  (-.5*pt[0]
  +.5*pt[2])*v
  +pt[1]
 );
);
pos=x/length;
cubic_interpolation(initial_array,pos);
"
512,256,1,1,"begin(const hh=h-1;);y<i(#-1,x,0,0,0);"

Never mind. I found it here - Reptorian G'MIC Filters - #612 by David_Tschumperle

Sorry about that. I bookmarked it.

I saw kth(), and vkth(). How do those even work?

  • kth(n,arg1,arg2,...,argN) returns the n^\text{th} highest argument from the argument list that is passed (with n starting from 1).
kth(3,10,52,38,25,3)
-> 25
  • If you pass vectors as an argument of kth, it’s like adding the list of scalar values that compose these vectors to the list of arguments. So, kth() always returns a scalar value:
kth(3,[10,52],[38,25],3)
-> 25
  • That’s why vkth() also exists: it works with vector-valued arguments and return a vector-valued result (where kth() has been applied to each vector component):
vkth(3,[10,52,8],[38,25,26],[-3,-8,-9])
-> [ 38,52,26 ]
1 Like

Question about the critical() function. Does it execute operation on multiple thread when the fill/eval starts with >? I think that’s how I am able to solve my test code in my g’mic thread.

EDIT: Nope, it doesn’t. Really wish there was a function that would execute a operation at multiple threads if fill/eval starts with >, and said function waits for everything to finish before continuing on to the next part of the code.

I got it. I solved it, the answer is in my g’mic thread.

I want to have labels within image that is order of sort of shapeaverage value ignoring 0 value. How would I do this? Like higher shapeaverage value has higher label value. 0 for lowest value, and 50 for highest value. In addition,disconnected areas being labeled the same if they have the same area.

Also, I want the same for minimum value.

What is wrong with using label_fg? :christmas_tree:

The problem with label_fg is that same areas away from coordinates 0,0 will be labeled differently. In addition, I want to isolate the stray black/white pixels.

See this picture to see what I mean:

image

Hence, why I need label based on the sorted order of value found with shapeaverage0 and all of them ignores 0 as part of label. Basically, the area with most value has the highest id, and the area with least value has the lowest id regardless of whether they’re connected.

Have a look into 'karo_label_sort" or “karo_label” custom functions. Maybe that is in your direction.

My brain checked out for Christmas. :stuck_out_tongue: What I meant is use label_fg or area_fg as a base for a custom command. Maybe @KaRo’s would be useful. I don’t feel like digging into my code snippets ATM…

To make things easier, @Reptorian, send us the code to make your image (with the ideal result). Then someone could experiment with it.

@KaRo : That’s not what I exactly want. I don’t want size. I want to label and sort the label based on the average value found within each region, and two areas of the same value has the same label. Areas with value of 0 are to be ignored.

Take a check at blend shapeaverage0.

@afre The command I’m working with is my own hitomezashi command. Copying from my G’MIC thread:

All you need to do is to assign same binary number on $1, and $2.

$ +rep_binary_hitomezashi 0110111001111,0110111001111

+rep_binary_hitomezashi:
skip "${3=}" #If there is no 3rd argument, then $3 is treated as null. So therefore, 2 arguments.

if narg($3) pass$3 1 # If there is a 3rd argument
else
 # Vowels as 1 is part of the rule. 
 # Whether number is even is also part of rule. 
 # Emoticons as 1 is part of rule. 
 # There's some few more arbitrary rule.
 (0,1,1,1,1,1,0,0,0,0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,1,1,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,0,1,0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0)
fi

('"$1"') # Get array of unicode value of input 1
('"$2"') # Get array of unicode value of input 2

f[-2,-1] i(#-3,i) # Convert unicode image/array to binary with rules.

{w#-1},1,1,1,>begin(v=0;);v=x?(j(#-1,-1)+v)%2:0; rm.. # Process first column. Creates auxilatory surface and then remove reference surface.

{w#-2},{w#-1},1,1 # Create a 2D surface to write on

eval.. "
 v=i(#-1,0,x)=i;
 row=x+1;
 repeat(w#-3-1,p,
  v=i(#-1,p+1,x)=sum(v,i(#-3,p,0),row,1)%2;
 );" #Generate value from spreadsheet rule.

rm[-4--2] # Keep only the Hitomezashi Pattern

I may find a solution here. My solution is to use label image to extract the info I want into a vector of size max number found with array. After that, I still have to figure out how to work with new vector and label image.

@afre @KaRo I have solved it.

image

image

image

The gradient there might not be obvious, but it’s based on the minimum length to coordinate 0,0. Stray single pixels get random color from a different palette.

This is where I got the gradient idea: https://github.com/josephsalmon/Tweets

Ok, I’m stuck with something. I have 7 arguments after the 9th arguments. My problem comes when the user insert empty arguments.

Here’s what I have:

arg9,stray_red,stray_green,stray_blue,border_size,border_r,border_g,border_b,frames

These arguments applies when I insert two image_args in arg5,and arg6. Nowhere else do they apply. For me to be able to work with this, I need to be able to have the option of generating selection of arguments based on mathematical expression. I thought creating a vector of arguments would work and extracting them, but vectors don’t accept empty arguments.

In addition, they don’t have to be restricted to 3 channels, but rather the number of arguments depends on number of channels for last image. So, in case of 5 channels, it would look like this:

arg9,stray_c,stray_m,stray_y,stray_k,stray_a,border_size,border_c,border_m,border_y,border_k,border_a,frames

Something like $=p, but with the option of using it akin to vector of arguments or something to extract group of stray arguments, and border arguments.

If this test command could work, then the above problem would be solved:

C:\Windows\System32>gmic rep_test 10,20,30,40
[gmic]-0./ Start G'MIC interpreter.
[gmic] *** Error in ./rep_test/*substitute/ *** Unknown command or filename '2-4'; did you mean '-'?
rep_test:
pal 45
$=p
echo ${"2-"{1+s#-1}""}

Have you tried string manipulation or if else statements?

I have not tried string manipulation, but that seem to be the only recourse. With ‘$=argpos’ and repeat, and appending string, this can be solved. Very ugly solution I must say.

One more for the heap; variance-weighted bilinear interpolation. That’s just a name I gave it - I don’t know the “official” name, assuming there is one. It has the property of making large edges clearer.

The idea is very simple: bilinear interp can be seen as a weighted sum of four pixel values, so we can easily add an extra weighting to that. The weighting is the reciprocal of variance of a 2x2 patch centred at each of the four pixels. The whole process effectively uses a 4x4 pixel input area for the output of one pixel.

This works best if the variance is averaged across all channels. The variance values can be computed quickly in advance with a box filter, but there’s no reason they can’t be done as part of the main loop either.

Here is an early reference version if anyone wants to experiment. I’d be very happy if the speed can be improved :slight_smile:

# Resize with variance-weighted bilinear scaling.
# format: gcd_resize_vwbl width,height
gcd_resize_vwbl : check "isnum(${1=0}) && $1>=1 && ${2=$1} && $2>=1"
  repeat $! l[$>]
    [0]x2 sqr.. boxfilter[-2,-1] 2 sqr. sub[-2,-1] max. 0 # 2x2 variance
    r. 100%,100%,100%,1,2 add. 1e-6 pow. -1 # average channels and invert
    $1,$2,1,{0,s} # The target resized image
    f. "begin(
        const interpolation=0;
        const boundary=1;
        const wr = (w#0-1) / max(w-1,1); # scaling ratios (small/large)
        const hr = (h#0-1) / max(h-1,1);
        px(x,y) = i(#0,x,y);     # point from source image
        vx(x,y) = i(#1,x,y,z,0); # point from variance image
      );

      X = x * wr;    # scaled coords
      Y = y * hr;

      xA = floor(X); # integer source coords
      xB = ceil(X);
      yA = floor(Y);
      yB = ceil(Y);

      lx = X-xA;     # usual ratios for lerp
      rx = 1-lx;
      ly = Y-yA;
      ry = 1-ly;

      w11 = rx * ry * vx(xA,yA); # variance adjusted weights for interp
      w12 = rx * ly * vx(xA,yB);
      w21 = lx * ry * vx(xB,yA);
      w22 = lx * ly * vx(xB,yB);
      S = w11 + w12 + w21 + w22;

      # final bilinear weighted sum
      (w11*px(xA,yA) + w12*px(xA,yB) + w21*px(xB,yA) + w22*px(xB,yB)) / S;
    " k.
  endl done

And an example of output - bicubic at the bottom for comparison:

3 Likes