G'MIC exercises

There is actually a much more faster solution that’s simpler. It’s the map command. With map approach, this is the speed:

C:\Windows\System32>gmic sp dog tic new_rep_bitplane_shuffle 8,${rep_extract_permutation_order\ 8,23459} toc
[gmic]-0./ Start G'MIC interpreter.
[gmic]-1./ Input sample image 'dog' (1 image 1024x685x1x3).
[gmic]-1./ Initialize timer.
[gmic]-1./ Elapsed time: 0.002 s.
[gmic]-1./ Display image [0] = 'dog'.
[0] = 'dog':
  size = (1024,685,1,3) [8 Mio of float32].
  data = (208,216,208,216,208,216,216,208,208,216,216,208,(...),220,85,85,85,220,220,73,73,73,220,220,220).
  min = 1, max = 254, mean = 124.926, std = 70.271, coords_min = (405,181,0,1), coords_max = (496,88,0,2).
[gmic]-1./ End G'MIC interpreter.
1 Like

I think warp is related to map. I am not good at using either command…

Very interesting indeed!

Note that in the Fourier domain, the convolution J = I \star K is translated as FFT(J) = FFT(I)\;FFT(K), which means K = iFFT(FFT(J)/FFT(I)) (where / is the complex division operator).
So, I’ve tried this:

foo :
  sp lena  +laplacian

  khs=1  # Kernel half-size
  foreach { fft }
  eval. "cK = [ i(#2),i(#3) ]//[ i(#0),i(#1) ]; i(#0) = cK[0]; i(#1) = cK[1]"
  rm[-2,-1] ifft[-2,-1] rm.
  z. -$khs,-$khs,$khs,$khs,2

This works, except that it considers periodic boundary conditions, so there are a few errors in the estimated kernel because command laplacian uses neumann bc.
But I think that with some additional care, we could end up with something good enough.

(I’ve tried computing the laplacian with periodic bc, and the error on the estimated kernel is very low, like 1e-10).

Damn, I dismissed the Fourier method exactly because of the boundary. Sometimes you just have to try it anyway! I’ll see how it looks later, I have some ideas which need such a command…

Edit: hmm, not certain how to get a working Fourier method which allows a mask (to get best kernel fit just for specific places in an image).

As a first experiment with it, I just pushed gui filter “Upscale [Solver2x]” with associated cli command gcd_upscale_solver2x.

It first solves kernels at particular gradient orientations in a downscaled vs original comparison. Then it uses those kernels to convolve the upscaled image in the same places (basically anisotropic convolution). I suppose results will be quite similar to lanczos.
tigereye2x

Edit: if a masked Fourier kernel solver is possible I’ll use it, this is quite slow!

Is there something like multiply version of sum() or do I have to use a loop to do that? Like mul(3,3,5)=45.

Is it this one?

mul(A,B,_nb_colsB)

Not sure what to do with that if it is.

You could use sum() on log of the values, then exp? Multiplying larger sets can lead to overflow if you aren’t careful as well…

Example:
gmic eval "A=[3,3,5];exp(sum(log(A)))" e \${}

There’s a easier way. prod(). It took me a google search to find that prod() is the multiply equilavent of sum() in Python, and this applies to G’MIC too and exists in it too.

C:\Windows\System32>gmic echo {prod(3,3,5)}
[gmic]-0./ Start G'MIC interpreter.
[gmic]-0./ 45
[gmic]-0./ End G'MIC interpreter
1 Like

Sorry I’m to the party late. You may have already worked this out.

That is the matrix multiplier. See Vector Calculus.

Here’s a roundabout way of rotating the an x unit vector 45° degrees counterclockwise around the z unit axis, via 67° and –22° intermediary rotations. The ‘3’ argument is a hint to mul() that its
matrix arguments have three columns.

 gosgood@bertha ~ $ gmic a='{matA=rot([0,0,1],67°);matB=rot([0,0,1],-22°);mul(matA,matB,3)*[1,0,0];}' echo \$a
[gmic]-0./ Start G'MIC interpreter.
[gmic]-0./ Set local variable 'a=0.70710668702957791,0.70710687534350458,0'.
[gmic]-0./ 0.70710668702957791,0.70710687534350458,0
[gmic]-0./ End G'MIC interpreter.
1 Like

Question A - Is there a more efficient way of doing this? I believe there exists a solution which doesn’t involve creating new pixels.

# snip from rep_form_pixel

# Form ratio is the scale factor of shape_something. 1 means full size, 0 means empty size. .5 means half-scaled.
# tile_w is the width of shape_something tile
# tile_h is the  height of shape_something tile

resize. {w#-1*(1/$form_ratio)},{h#-1*(1/$form_ratio)},1,1,0,0,.5,.5
resize. $tile_w,$tile_h,1,1,0,0,.5,.5

On this, I think this is the answer:

if $fit_tile
 resize2din. {round([$tile_w,$tile_h]*$form_ratio)},$interpolation
else
 resize. {round([$tile_w,$tile_h]*$form_ratio)},100%,100%,$interpolation
fi

resize. $tile_w,$tile_h,100%,100%,0,0,.5,.5

Question B - To fix the issue with many subcommands under pal, do I just go into using merge command for so many subcommands and remove the additional commands? I have not tried this yet, but can there be a loss of performance here? The last resort is to well develop a hash map and code in hashmap, and I certainly don’t want to do that.

I haven’t used gmic in a while. Is round necessary? Will resize throw an error if you input decimals or will it automagically round for you?

Subcommands help with readability. However, if you want performance, you may have gains if you made single purpose commands per thing you want to do. Also, if you subcommand everything, there comes a point where it becomes harder/longer to parse for humans/computers.

I only used round to ensure closest matching dimensions.

Performance is what I want for pal command. That’s the only command which has over 500 subcommands. Half of which is for creating palette, and other is used for naming palettes with long names.

How do I get the spectrum in which a image contains the string $ref_pal_pos?

There are images which contains one of the following names: gray_pal,rgb_pal,yuv_pal.

  repeat $num_of_target_imgs {
   s1:=s#$>
   ref_pal_pos={$>,n}
   ref_pal_pos=${arg\ {find('grargbyuv',('$ref_pal_pos')[0,3],0,3)/3}+1,gray_pal,rgb_pal,yuv_pal}
   
   s2={s#$$ref_pal_pos}
   echo $s2
  }

EDIT:
Ah yes, my solution is to simply type in $ next to those name, and I get the index of images which contains the name of string $ref_pal_pos. After 2 hours just solving this…

Here is what I came up with:

  image_indexes=$gray_pal,$rgb_pal,$yuv_pal
   
  repeat $num_of_target_imgs {
   s1:=s#$>
   ref_pal_pos={$>,n}
   ref_pal_pos=${arg\ {find('grargbyuv',('$ref_pal_pos')[0,3],0,3)/3}+1,$image_indexes}
   echo $ref_pal_pos
  }

How exactly do I get this to work?

image_a=${arg\ $mode,1~,1~\,1~,,0~\,1~}

Note the escape symbol in there. I need image_a to be 1~,1~ when arg1 is chosen.

Also, I note that this works:

mirror_a,mirror_b,mirror_c=${arg\ $mirror_mode,x\,y\,x,y\,x\,y}

This doesn’t work:

image_b=${arg\ $mode,"1~,1~","0~,1~","1~",}

Neither this:

image_b=${"arg0 $1,1~\,1~,0~\,1~,1~,"}

Even backslashes don’t work.

Perhaps escape the quotes?
image_b=${arg\ $1,\"1~,1~\",\"0~,1~\",\"1~,\"}

1 Like

That does work, however, I seem to get a error when using it as an argument.

$ sp cat new_rep_symmetrize_xy 1
[gmic]-0./ Start G'MIC interpreter.
[gmic]-1./ Input sample image 'cat' (1 image 600x550x1x3).
[gmic] *** Error in ./new_rep_symmetrize_xy/*foreach/ (file 'C:\Users\User\AppData\Roaming\user.gmic', line #26) *** Command 'image': Invalid argument '[-2],1~,1~'.
[gmic] Command 'image' has the following description:

Script:

new_rep_symmetrize_xy:
mirror_mode,mode={v=$1;[(!!(v%4))+1,(v%4)+1]}

crop_a_0,crop_a_1,crop_a_2,crop_a_3=${arg\ $mode,0\,0\,2\,2,1\,0\,1\,2,0\,1\,2\,1,1\,1\,1\,1}
resize_end={([0,0,1,0,0,1,1,1])[($mode-1)*2,2]}
mirror_a,mirror_b,mirror_c=${arg\ $mirror_mode,x\,y\,x,y\,x\,y}
image_a=${arg\ $mode,1~,\"1~,1~\",,\"0~,1~\"}
image_b=${arg\ $mode,\"1~,1~\",\"0~,1~\",1~,}
image_c=${arg\ $mode,\"0~,1~\",,\"1~,1~\",1~}


foreach {
 +crop $crop_a_0,$crop_a_1,{w-$crop_a_2},{h-$crop_a_3}
 +resize[-2] {w#-2+w#-1},{h#-2+h#-1},100%,100%,0,0,$resize_end
 
 mirror[-2] $mirror_a
 image[-1] [-2],$image_a
 
 mirror[-2] $mirror_b
 image[-1] [-2],$image_b
 
 mirror[-2] $mirror_c
 image[-1] [-2],$image_c
}

Move closing quotes from image_b and image_c to the right?

What do you move it to the right? Error shows up at $image_a.

Did you mean to put double commas like that?

Sorry, I forgot that one. Are you trying to quote around the ~? If so, then for image_a, you should start quoting earlier and for the latter two, quote later. I am not thinking too much about it since I have been under the weather, but that is what “doesn’t belong” just looking at your code.