Anyone can read 1977 codes here?

Basically, what I’m looking for a command that cuts based on the frequency vs dimension ratio. $1 would be the parameter to find the lowest value that has a frequency higher than $1, and $2 would be the parameter to find the highest value that has a frequency higher than $2. Then, cut based on the found values. That’s something I requested on G’MIC 3.1 thread.

Like a band pass/stop? There is a bandpass command that you could use as a starting point.

bandpass:
    _min_freq[%],_max_freq[%]

  Apply bandpass filter to selected images.

  Default values: 'min_freq=0' and 'max_freq=20%'.

  Example:
    [#1] image.jpg bandpass 1%,3%

  Tutorial: https://gmic.eu/oldtutorial/_bandpass

That doesn’t give me the output I want. I want to cut instead. Let me see. I could try to do a custom command involving sorting, and then find the frequency of each value, and cut based on those.

The world doesn’t have enough graphics languages, so here’s a solution in “alfim”, a language I am developing. I call sercir() only once, so there is only one “circle”. It is based on code above by @mbs, but with smaller initial (xi,yi) and without wraparound.

function sercir ()
  variables
    WW = %[fx:w],
    HH = %[fx:h],
    xi = %[fx: 4 * rand() - 2],
    yi = %[fx: 4 * rand() - 2],
    xmin = -2,
    xmax = +2,
    ymin = -2,
    ymax = +2,
    xmult = %[fx: (%{WW}-1) / (%{xmax}-(%{xmin})) ],
    ymult = %[fx: (%{HH}-1) / (%{ymax}-(%{ymin})) ],
    rep = 1,
    col,
    row,
    x = %[fx: %{xi} ],
    y = %[fx: %{yi} ]
  endvariables

  -fill White

  while %[fx: %{rep} < 1000 ] do

    assign x = %[fx: %{x} - %{y}/2 ]
    assign y = %[fx: %{y} + %{x}/2 ]

    assign col = %[fx: (%{x}-(%{xmin})) * %{xmult} + 1 ]
    assign row = %[fx: (%{y}-(%{ymin})) * %{ymult} + 1 ]

    -draw "point %{col},%{row}"

    assign rep = %[fx: %{rep} + 1]
  endwhile

endfunction

-size 400x400 xc:Black
call sercir ()
+write x.png

x

3 Likes

Sounds like you’re talking about statistical relative frequency? A histogram ought to manage that…

What I understand here is what you name “frequency” is actually the “occurence”, right ?
(Frequency in image often refers to Fourier decomposition in image processing).

as @garagecoder suggests, computin the histogram is probably the key here.
But what do you want to do with the values below or above a certain occurence threshold. What value should be used to replace the old one ?

These become the values used for cut(). A partial work on this:

> gmic sp cat to_gray +pixelsort +,yx +area. 0,0 +label.. a[-3--1] c colormap. 0 sh. 2 pixelsort.. +,x,. rm.

The first channel is the value of image, the second channel is the occurence, and the third channel is the label value of the image. If the occurence is greater or equal to 5% starting from the left, then corresponding image pixel value becomes the cut value 1. If the occurence is greater or equal to 5% starting from the right, then the corresponding image pixel value becomes the cut value 2. So, with those found value, it is the cut values.

I have done something similar for tone re-mapping (the ranking and smoothing). The challenge is making it fast. E.g., colormap on large colourful images takes a while to process.

The speed issue is why I brought it up. I also think something like this could also apply to the math parser on a vector as well.

Beautiful name! If you replace “m” with “o” then you get my first name :slight_smile:

I’m interested. Could you tell us a bit more about it? Design and goals ?

It has similarities with IM syntax… Is it its own thing or using IM?

I guess that maybe, it is intended to be an extension to the IM syntax, that will be available for future versions of IM. That is really interesting.

1 Like

To avoid massive off-topicing, I have replied in a new thread, Alfim: Augmented Language For ImageMagick

1 Like

@afre I think this is the fastest I could make occurrence-based cutting.

Code to Try
rep_percentile_gray_cut:
m "generate_array_of_pixel_value_and_occurance: 
 unroll x
 sort

 1,1,1,2

 start_point:=im#-2-1

 eval.. \">begin(v=$start_point;p=-1;o=1;);
  if(i!=v,
   v=i;
   o=1;
   p++;
   da_push(#-1,[v,o]);
  ,
   o++;
   I[#-1,p]=[v,o];
   0;
  );
  end(
   resize(#-1,1,da_size(#-1)-1,1,2);
  );\"
  rm..
 "

init_lowval_freq_thres,init_highval_freq_thres={$1},{$2}

repeat $! l[$>]
 if s>1 +to_gray fi
 generate_array_of_pixel_value_and_occurance.

 sh. 1
 lowval_freq_thres:=$init_lowval_freq_thres*iM#-1
 highval_freq_thres:=$init_highval_freq_thres*iM#-1

 rm.

 eval "
  begin(
   const my=h#-1-1;
   const lv=$lowval_freq_thres;
   const hv=$highval_freq_thres;
   search_lv=search_hv=1;
   out_a=out_b=0;
   p=0;
  );
  
  repeat(h#-1,
  
   if(search_lv,
    if(i(#-1,0,p,0,1)>=lv,
     out_a=i(#-1,0,p,0,0);
     search_lv=0;
    );
   );
   
   if(search_hv,
    inv_p=my-p;
    if(i(#-1,0,inv_p,0,1)>=lv,
     out_b=i(#-1,0,inv_p,0,0);
     search_hv=0;
    );    
   );
   
   if(!search_lv&&!search_hv,break(););
   
   p++;
   
  );

  [out_a,out_b];"

  cut.. ${}
  rm.
endl done

Could you give me a sample command? All I am getting is a zero image.

$ sp +rep_percentile_gray_cut 5%,6%

The percentage is used to define threshold.

I neglected to add the % sign. This command may be confusing to users; e.g.,

gmic sp tiger rep_percentile_gray_cut 5%,6%
gmic sp tiger rep_percentile_gray_cut 5%,95%

yield the same result.

I finally got around to adding the Serendiptous Circle to G’MIC. Doesn’t work too well with large images from the GUI side of thing, but I’ll have to say oh well to that since there’s no full-size preview or a way to access the original image size.

It’s a little tricky to work with, but the main gist is that once you understand the common expression, you can make anything on the Serendiptous Circle article.

1 Like