Reptorian G'MIC Filters

I recall LBP being the basis for some edge/detail/object detection methods.

Yes, and the basis of it can also be used to find vector of most similar color. I’m glad I stumbled upon it.

Also looks very like many other gradient convolutions, examples:

g xy,1 sign add
g xy,1 sign add +eq 0 mul. 2 sub

(0,-0.25,-0.25;0.25,0,-0.25;0.25,0.25,0) +convolve.. . mirror.. x convolve... .. rm.. atan2.. . rm.

Edit: some bonus extras, not as similar but still interesting:
g xy,1 sign g.. x,-1,0 g. y,-1,0 add
g xy,1 sign g.. x,-1,0 g. y,-1,0 neq 0 add
laplacian sign

People can make any method a basis for any application. The questions are: Is it the best use of the base algorithm and How much of a time sink is it? :wink: I know you and I do this for a hobby and to please others, but lately I am severing lacking the time to play. Hence, my absence from G’MIC code for the past year or so. Still, I like to engage simple G’MIC conversations. :stuck_out_tongue:

One of the thing I hope to do is to do more generic algorithm and things like pal,modf, and my combination/permutations commands to makes things a lot easier (The last one to do is permutation with n-set which has yet to be solved). I may even think about adding a new command which involves count-sorting that is utilized in Lavander Binary Map, but I only see very rare usage of it, so I won’t add it.

Right now, what’s keeping me from that is that I’m still in the process of improving my existing command and bug-fixing before 2023 start, and honestly, I’d doubt I’ll finish it, but I did what I can.

I have successfully optimized a filter

C:\Windows\System32>gmic sp flower args=50,50,50 tic +new_rep_hsx_poster_index[0] $args,10% toc tic rep_hsx_poster_index[0] $args,10% toc
[gmic]-0./ Start G'MIC interpreter.
[gmic]-1./ Input sample image 'flower' (1 image 640x600x1x3).
[gmic]-1./ Set local variable 'args=50,50,50'.
[gmic]-1./ Initialize timer.
[gmic]-2./ Elapsed time: 0.171 s.
[gmic]-2./ Initialize timer.
[gmic]-2./ Elapsed time: 98.399 s.
[gmic]-2./ Display images [0,1] = 'flower, flower_c1'.
[0] = 'flower':
  size = (640,600,1,3) [4500 Kio of float32].
  data = (11.9,18.7,11.9,13.6,11.9,10.2,10.2,10.2,10.2,10.2,10.2,10.2,(...),2.703,3.06,2.703,3.06,2.703,3.06,3.06,3.06,3.06,3.06,3.06,1.173).
  min = 0, max = 255, mean = 103.712, std = 84.8802, coords_min = (309,167,0,2), coords_max = (550,1,0,0).
[1] = 'flower_c1':
  size = (640,600,1,3) [4500 Kio of float32].
  data = (14.325,23.1061,14.325,14.325,14.325,9.26114,9.26114,9.26114,9.26114,9.26114,9.26114,9.26114,(...),2.23032,2.23032,2.23032,2.23032,2.23032,3.82341,2.23032,2.23032,3.82341,2.23032,2.23032,2.23032).
  min = 0.849646, max = 255, mean = 104.083, std = 85.1316, coords_min = (107,0,0,2), coords_max = (549,1,0,0).

New time: .171 s
Old time: 98.399 s

Results: ~575x faster

EDIT: I have pushed optimized version of HSx Posterize/Index.

Also, HSx Posterize/Index + Smooth[Median] looks nice.

In addition, I added a new feature to it which is called start_hue or Start Hue. This means you don’t have to stick with red and blue with low hue band.

Here’s a example:

1 Like

Can someone test this code for multiple images and different dimensions? I think it should work on 3.2, but I don’t think so.

#@gui Image Dimensions Factors:_none_, fx_find_factors_of_images_preview(1)*
#@gui:_=note("This tool is used to calculate factors of your image dimension. It is not used to change image.")
#@gui:_=separator()
#@gui:1.Image Index Position(%)=float(0,0,100)
#@gui:2.Image Index=text("0")
#@gui:3.Width Factors=_text("Width Factors will be calculated and inserted here")
#@gui:4.Height Factors=_text("Height Factors will be calculated and inserted here")
#@gui:5.Width and Height Factors=_text("Width and Height Factors will be calculated and inserted here")
#@gui:6.Factors Information=_text(1,"Every factors can be copied and pasted from this box")
#@gui:_=separator(),_=note("<small>Author: Reptorian. Latest Update: <i>2022/07/09</i>.</small>")
#@gui:7.Image Index Position(%)=float(0,0,100)
#@gui:8.Image Index=text("0")
fx_find_factors_of_images_preview:
skip "$*"
check "isint($2)&&isint($8)"

act_mult_imgs_mode:=$!>1

index=$2

if narg($_persistent)
 
 if $act_mult_imgs_mode
  if $1!=$-2
   index={round(($!-1)*$1%)}
  fi
  
  $_persistent
  
  width_start_point:=i(#$width_factors_start_indexes,$index)
  width_end_point:=$width_start_point+i(#$number_of_width_factors,$index)

  height_start_point:=i(#$height_factors_start_indexes,$index)
  height_end_point:=$height_start_point+i(#$number_of_height_factors,$index)

  width_and_height_start_point:=i(#$width_and_height_factors_start_indexes,$index)
  width_and_height_end_point:=$width_and_height_start_point+i(#$number_of_width_and_height_factors,$index)
   
  width_factors:=crop(#$width_factors_img,$width_start_point,$width_end_point)
  height_factors:=crop(#$height_factors_img,$height_start_point,$height_end_point)
  width_height_factors:=crop(#$width_and_height_factors_img,$width_and_height_start_point,$width_and_height_end_point)
  
  text_box={t}
  
  remove[-9--1]
 else
  $_persistent
  
  width_factors={crop(#-4)}
  height_factors={crop(#-3)}
  width_height_factors={crop(#-2)}
  text_box={t}
  remove[-4--1]
 fi
else
 text_box=""
 
 foreach {
  if $act_mult_imgs_mode
   if $> text_box.=\n\n fi
  
   text_box.="Image "{`35`}$>\n
   text_box.=-----------------------\n
  fi
  
  w,h={[w,h]}

  width_factors=${rep_find_factors_of\ $w}
  height_factors=${rep_find_factors_of\ $h}
  width_height_factors=${rep_find_factors_of\ $w,$h}
  
  if $act_mult_imgs_mode
   ($width_factors) => width_factors_img
   ($height_factors) => height_factors_img
   ($width_height_factors) => width_and_height_factors_img
  fi
  
  text_box.="Image Width: "$w\n
  text_box.="Image Height: "$h\n
  text_box.="Image Dimensions: "$w{`120`}$h\n\n
  text_box.="Factors of Width: "$width_factors\n
  text_box.="Factors of Height: "$height_factors\n
  text_box.="Factors of Width and Height: "$width_height_factors
 }
 
 if $act_mult_imgs_mode
  
  local[width_factors_img] {
   $!,1,1,1,w#x => number_of_width_factors
   {w},1,1,1,>begin(v=0;);p=v;v+=i(#-1);p; => width_factors_start_indexes
   append[^-2--1] x
  }
  
  local[height_factors_img] {
   $!,1,1,1,w#x => number_of_height_factors
   {w},1,1,1,>begin(v=0;);p=v;v+=i(#-1);p; => height_factors_start_indexes
   append[^-2--1] x
  }
  
  local[width_and_height_factors_img] {
   $!,1,1,1,w#x => number_of_width_and_height_factors
   {w},1,1,1,>begin(v=0;);p=v;v+=i(#-1);p; => width_and_height_factors_start_indexes
   append[^-2--1] x
  }
 fi
 
 ('$text_box')
 
 text_box={t}
 
 if $act_mult_imgs_mode
  store[width_factors_img,\
        height_factors_img,\
        width_and_height_factors_img,\
        number_of_width_factors,\
        number_of_height_factors,\
        number_of_width_and_height_factors,\
        width_factors_start_indexes,\
        height_factors_start_indexes,\
        width_and_height_factors_start_indexes,\
        -1] _persistent
 else
  ($width_factors)
  ($height_factors)
  ($width_height_factors)
  move[-4] {$!}
  store[-4--1] _persistent
 fi
 
fi

u "{$1}"\
"{"$index"}"\
"{"$width_factors"}"\
"{"$height_factors"}"\
"{"$width_height_factors"}"\
"{"$text_box"}"\
"{$1}"\
"{"$index"}"

Well it seems to work for me, even inside preview. I wonder if you could include aspect ratio as well (e.g. 16:9)?

That’s out of scope, however, that can be done with gcd() and max(w,h)/min(w,h). I’ll add it to Detailed Information GUI “filter” (It doesn’t do anything on apply).

1 Like

@David_Tschumperle A question. I noticed that _persistent seem to stay when I switch active layer input. Shouldn’t it be cleared when switching input layers so that the expected input for a filter be applied? If you look at the Image Dimensions Factors GUI tool with the latest gmic-community code and switch input layers, the resulting numbers seem off, but it wouldn’t seem off if _persistent is cleared upon a switch and that is evidenced by simply applying refresh filter.


I found this on stdlib:

 '#@gui Command name : command, preview_command (zoom_factor)[*|+] [: default_input_mode]

I’ll figure out on where to put this default_input_mode thing, and make some play.

1 Like

@garagecoder I added rep_nearest_ratio which calculates the nearest ratio or the exact ratio of image. I’ll add it to Detailed Information soon. It’s a easy command. To see how it works:

D:\Programs\G'MIC\gmic-community>gmic rep_nearest_ratio 322,862,19 echo ${}
[gmic]-0./ Start G'MIC interpreter.
7,19
[gmic]-0./ End G'MIC interpreter.
D:\Programs\G'MIC\gmic-community>gmic rep_nearest_ratio 500,200,19 echo ${}
[gmic]-0./ Start G'MIC interpreter.
5,2
[gmic]-0./ End G'MIC interpreter.
1 Like

Reminds me of a command I sometimes use (I’m sure there are better ways):

gcd_rational_approx : skip ${1=1.6},${2=999}
  best=1 curr=1 lim:=1
  repeat $2 {
    curr+=1 diff:=$curr/$1-floor($curr/$1)
    if $diff<$lim best=$curr lim=$diff fi
  } e $best/{floor($best/$1)}
> gmic gcd_rational_approx {pi}
[gmic]-0./ Start G'MIC interpreter.
355/113
[gmic]-0./ End G'MIC interpreter.
2 Likes

Yes, there’s the fast farey method found here - best-rational-approximation/ad_rat_by_fast_farey.py at master · alidasdan/best-rational-approximation · GitHub .

I wish I understood that code. It reminds me of why I have plans to make variable names better on my code, and am growing in the habits of making longer variable names.

Interesting - I have some doubts that would lead to heavy gains in practice actually. Agreed about variable naming of course, depends whether we expect anyone else to maintain it though…

Or just to be sociable. If one wants to converse in code `tis best to be transparently clear throughout. Say it three times: though variable name hinting, the code itself and telling comments.

If one just intends to be a hermit, name variables tersely to save keystrokes. Years on — or even months! — if once-clear code is now incomprehensible, there is but one person to blame and one to suffer.

In most places definitely - especially when working in teams. We sort of covered this before in another thread. Perhaps we should revive that or make another rather than in here, but in short: looking at the existing contributed code, I think variable naming is the least of our worries.

1 Like

I kind of agree with @garagecoder.
There is a current trend that code must be readable (and well documented!) to be worthy of consideration. And this simplistic idea has made its way in the software development world.
Although this is indeed a desirable property in many cases (team development and so on…), the readability of a code is ultimately only a very minor aspect of the “value” of a program.

For example, if I want to do something quick, only for me, knowing that I won’t go back to it in 2 years or even 2 weeks, and I use a clever way of solving my problem. That’s not bad code, even if the variables I use are named a, b and c.
That would be clearly better than having a very well documented code with fancy variable names that takes forever to solve the same problem, because the algorithm used there just sucks.

Evaluating the quality of a code under the only aspect of its readability is in my opinion a serious mistake.

Would it mean that all programs participating in code obfuscation contests would be considered “bad”? This is exactly the contrary : those are treasures of ingenuity and creativity that only a few talented programmers are able to achieve.

Don’t get me wrong : I don’t say code readability is a bad practice.
It’s just not the only measure to consider chen evaluating the quality of a code.

I think that developers too much focused on the readability of the code should do a small internship of 2 or 3 months doing assembly programming, it would open their mind :slight_smile:

1 Like

(Sorry @Reptorian adding more noise)

@grosgood I just have to say that one place where code clarity is very much appreciated (and indeed required) is of course your tutorials!

Not everything must be in extremes; g’mic code is capable of being readable, when we need it to be. I do try and keep some sort of balance in general.

So as not to further hijack @Reptorian’s thread, I’ve placed my thoughts over at Tutorial Fragments.

1 Like