Photo Mosaic with G'Mic

I did just found the solution, to creating photo-mosaic, but the result are atrocious, but it works nevertheless.

#@cli rep_lbchstatfunc_to_pal: (eq. to rep_layers_by_channel_statistical_function_to_palette)
rep_lbchstatfunc_to_pal: rep_layers_by_channel_statistical_function_to_palette $*
#@cli rep_layers_by_channel_statistical_function_to_palette: variable
#@cli: Converts layers to palette using statistical function by channels per layers into 1x1 tile, then append them.
rep_layers_by_channel_statistical_function_to_palette: to_rgb rep_bchstatfunc $1 a x

#copy and paste below into code filter in g'mic, and copy and paste above to somewhere where you can remove it when not needed#
v=5
te={w<h?$v/w:$v/h}
to_a
at[0] "rep_bchstatfunc ia,0",{$te*w},{$te*h} r[^0] {$te*w},{$te*h},1,4,5 r[^0] {w#0},{h#0},1,4,0,2 +rep_lbchstatfunc_to_pal[^0] ia split_opacity[^{$!-1}] index[0] .,0,1 rm. l[^0-1] repeat {$!/2} +rep_bchstatfunc[{$>*2}] ia,0 done endl l[^1-{($!-1)-($!-2)/3}] repeat {$!-1} l[0,{$>+1}] f. "i#0==i#1?255:0" to_gray. endl done endl repeat {($!-2)/3+1} l[{1+($>*2)},{($!-1)-($!-2)/3+$>}] / 255 f.. "i#0*i#1" * 255 endl done rm[^0-{($!-1)-($!-2)/3}] repeat {($!-2)/2} a[{$>+2},{$>+3}] c done blend[^0-1] alpha rv[0,2] rm. split_opacity[0] blend[^0] multiply a c

Using code, you can change the value of v. Works with any layer greater than 3 as 2 are at least needed minimum for the mosaic.

Here’s the atrocious result -

That’s due to the indexing technique. I may need to find out just how to get a better indexing for the purpose of generating the mosaic. Either that or I may have to add blending using the original [0] image. Or both.

EDIT: One more example, but this time, more passable. Had to add more images for the mosaic result.

EDIT: I may have to keep in mind about expand_x, and expand_y for future filters.

1 Like

Not quite what the OP was looking for, but nevertheless interesting. Reminds me of those Lego grid bases. Or a map of grid based video games.

Exactly, however, I"ll admit that this is a start to a new filter unless someone makes a better version than my own. Also, I’ll share this result too -

1 Like

Now add an option, that every photo can only used 1 or n times.

That’s going to be hard given that it’s a bit hard to maintain the code.

I made a better algorithm to make the end image better. There’s two problem - A incredible annoying bug, and having to figure out shift due to nearest neighbor scaling issue. This approach uses indexing instead.

#@cli rep_lbchstatfunc_to_pal: (eq. to rep_layers_by_channel_statistical_function_to_palette)
rep_lbchstatfunc_to_pal: rep_layers_by_channel_statistical_function_to_palette $*
#@cli rep_layers_by_channel_statistical_function_to_palette: variable
#@cli: Converts layers to palette using statistical function by channels per layers into 1x1 tile, then append them.
rep_layers_by_channel_statistical_function_to_palette: to_rgb rep_bchstatfunc $1 a x

#copy and paste below into code filter in g'mic, and copy and paste above to somewhere where you can remove it when not needed#
v=25
isw={w>h?1:w/h}
ish={h>w?1:h/w}
vw={floor($v*$isw)}
vh={floor($v*$ish)}
nsw={ceil(w/$vw)}
nsh={ceil(h/$vh)}
to_a

l[0] +r[0] {$nsw},{$nsh},1,{s},5 endl
+rep_lbchstatfunc_to_pal[^0-1] ia
split_opacity[1]
index[1] .,.85,1
a[1,2] c
r[1] {w#0+($v-(w#0%$v))},{h#0+($v-(h#0%$v))},1,{s#1},1
shift[1] {w>h?0:0},{h>w?0:0}
f[0] "i#1"
rm[1]
r[^0,{$!-1}] {ceil($vw)},{ceil($vh)},1,4,5
r[^0,{$!-1}]  {w#0},{h#0},1,4,0,2
split_opacity[^{$!-1}]
l[0,{$!-1}] pal_l. r[^0] {w#0},{h#0},1,3,1 endl

ti={($!+1)/3}
repeat {($ti-1)} l[0,{$!-$ti+$>+1}] f. "i#0==i#1?255:0" to_gray. endl done
repeat {($ti-1)} l[{($>*2)+3},{$!-$ti+$>+1}] f.. "i#0==i#1?255:0" endl done
rm[^0-{$!-$ti}]
repeat {($!/2)-1} a[{$>+2},{$>+3}] c done
blend[^0-1] alpha rv[0,2] rm. split_opacity.. blend[^0] multiply a c

Some part of the image are shifted for some reason, and I don’t know how exactly do I fix that bug. There’s also the need to add shift because some areas have bigger side than the other areas. See what I mean by deleting everything after shift and checking for yourself.

That would also depend on how many input files you have for the mosaic.

EDIT: Finally, I figured out what’s wrong with the colors. So, irrelevant part of post is gone.

EDIT: It is uploaded to g’mic community. And here’s a sample image. It uses indexing, and no apply_tiles.

^Also works with transparency too.

1 Like

Ok, now I got a issue here. When developing the gui filter - I am not exactly sure how do I get the number of layer inputs to affect the dynamic options. It seems to treat $! as one every time.

u "{$1}_"{$!>=1?2:0}\
"{$2}_"{$!>=1?2:0}\
"{$3}"\
"{$4}"\
"{$5}"\
"{$6}"\
"{$7}"\
"{$8}"
text_outline {$!},2,22,23,2,1,255 # nb layers
text_outline {{$!}-1},2,42,23,2,1,255 # nb layers - 1

This is the first test that does not block my PC with your ‘Mosaic’ filter.
The result is funny on the picture of ‘Gmicky’
Under G’MIC-GIMP-QT the command line used is ’ rep_mosaic_gen 20,{{$!}-1} '.
Thumbnails are from www.uihere.com

rep_mosaic_test_01

1 Like

Photo-mosaic has been updated. I think I should add the option to have the end result resized to nearest divisible numbers by tile_width, and tile_height? Is there anything else other than that I should add (I can’t do automatic rotation to make the end result even better as a option)? Should I add the option to have users to use original picture color as a blending mode?

For your reference,

#@cli rep_mosaic_gen: 0>=tile_width,0>=tile_height,0>=dithering<=1,1>=interpolation<=6,autocrop-by-median_bool[0=Do not autocrop by median|1=Autocrop by median]
1 Like

Your parameter conditions and formatting need revision. See example:

With the bug on my aspect ratio, I gotta say that I give up on the mosaic project. I couldn’t find a fix despite it works mostly.

Now that the aspect crop bug is fixed. I’m on my way to fixing my cli formatting. All of them. A few info might go amiss though considering the large info I added.

Okay, now I think I got a working mosaic filter with dynamic options all working irrespective of software one is using (Paint.NET or Krita or GIMP). So, I believe this thread is solved. Mind you, sometimes autocrop has to be enabled for the filter to work, and that’s something I’d really like a explanation for. Other than that, it works 100%.

Congrats. For the OP, what is the GUI filter called now?

‘Picture Mosaic’

And as for the cli command

#@cli rep_mosaic_gen : _tile_width>=0,_tile_height>=0,_dithering<=1,1>=_interpolation<=6,_autocrop-by-median_bool={ 0=Do not autocrop by median | 1=Autocrop by median },_out_original_dimension={ 0=Do not output original dimension | 1= Output Original Dimension },use_folder={ 0=Do not use folder | 1=Use folder },folder_location="location_in_computer"
#@cli : Generates mosaic using multiple pictures using indexing methodology, and uses average to determine the mapping based on colors. Tile_Width and Tile_Height cannot be both zero!
#@cli : Default value: 'tile_height=0', 'interpolation=5', 'autocrop-by-median=0','out_original_dimension=1','use_folder=0','folder_location="N/A"'
#@cli : $ rep_mosaic_gen 10,10,.75,6,1,0 ,
1 Like

As I hinted in my penultimate post, 1>=_interpolation<=6 should be 1<=_interpolation<=6. You could also shorten your Boolean descriptions to make them easier to read; e.g., _median_autocrop={ 0 | 1 }.

Did you use this for files?

image

Noted via my github gmic community branch.

I used input_glob like in the PM. I didn’t really had any success with files when I tried before input_glob, but I’ll try again though. Files and folder does seem interesting. I’ll have to make that work.

The issue with input_glob is fixable. I found this alternative command.

v - files 3,"D:\Pictures\NFS3 Expansion Pack Pictures\file test" _N=/{narg(${})-1} arg2var _file,${} nb_files=${}
repeat $nb_files l[]
file=${_file{$>+1}} 
_file=$file
i $file
endl
done

Unlike input_glob, this’ll accept spaces. Problem is that when it gets to the gui filter. Putting $8 as the replacement is just not gonna work. I know I’m going to need to replace char, but I don’t know how to do that.