Page 2 of 2

Re: A Fun Experience with IM

Posted: 2010-10-13T19:39:52-07:00
by anthony
immortal26 wrote:In final result's it gives me ONE member at each point! Hooray!
I see.... you used a Autotrace to generate coordinate positions for the people.
then compose each person at the position indicated. Pretty nifty.

Re: A Fun Experience with IM

Posted: 2010-10-14T05:58:56-07:00
by immortal26
anthony wrote:
anthony wrote:Very good.

I gather you use a 'dot' font to draw the name, then distort that to fit the background image, and then replace each 'dot' with a small human figure, before it is overlaid on the background image.

Very tricky. and you obviously a lot of fun to create it.

What did you use for the 'dot replacement'

Looking close you can see some figures 'doubled up'. You may like to look at some type of morphology to convert any large dot to a single dot before converting 'dots to people'.
immortal26 wrote:Hi Anthony,

I think you posted in the wrong topic, but thats okay I'm sure somebody can move it... but.
I've been trying out this morphology option but I can't seem to get this dot font down to one pixel for each dot.
Here is the font, maybe you can give me some ideas?:

Thanks Man,
Actually I hadn't! But at the time I looked at your links I saw a picture of a stadium filled with a large crowd, but an empty field, but then the same picture with lots on 'little' people standing around so as to form letters of a name.

The links are now (original) ... lorida.png
With the result ... /final.jpg

I still like to know how you placed all those ant-like people!

As for the 'dot' font. After distorting, I would first so a threshold on the image to make it binary, then would use a Morphology Thinning transform to repeatedly remove 'edge' from the image until you get a single dot.

For example...

Code: Select all

convert -font Dot -pointsize 144  label:Anthony \
          -trim +repage -bordercolor white -border 5 -negate anthony_dots.gif
Use morphology Thinning to convert the dots to single points.

Code: Select all

convert anthony_dots.gif -threshold 80% \
          -morphology Thinning:-1 'LineEnds;Corners;Edges' anthony_pixels.gif 
Distort and enhance to single dots again

Code: Select all

convert anthony_pixels.gif  +distort Affine '0,0 0,0  0,1 .5,.2  1,0 1,-.2'\
            -threshold 10% -morphology  Thinning 'LineEnds;Corners;Edges'  anthony_final.gif 
Very very nice. I think you got the gist of it Anthony.
Yes autotrace is the final factor in getting the coordinates of each point to compose individual bitmaps at those points.
Depending on the programming language you are using is where you would gather those x,y coords... as you can see with mine in php.

I load the svg in using simple_xml_load.
Then foreach path that it finds (I skip the first one because it's the black background).
Then I run another foreach loop in the second path (since it's 2 colors) and:
explode the d= in the svg using "space" as the delimiter so I would be left with an array like:
[0] => M567 [1] => 17L82 [2] => 18L83 [3] => 17M627
I'm not worried about the lines "L's", just the M's
So I take each element in the array and parse it looking for that M and what's behind it... so the first one would be 567.
Now it skips the next two because I don't want the lines and sees 17M627... I want the 17 and the 627 (using php I did this)
so the first one was 567 which is "x" ... next is the numbers in front of the next element with an "M" being 17 which would be "y"
So first coord's is x=567 y=17 ... and as you can see above I wanted the 627 after the M as well for the next "x" coord.
And I just let the foreach and that code run at the same time adding the bitmap at that position.

Re: A Fun Experience with IM

Posted: 2010-10-14T06:24:42-07:00
by immortal26
On a second note, I also took that dots font and removed quite a few of the dots so that it doesn't get to congested.
Especially on an extreme distort where they would be very close on overlaying each other.
I am thinking of creating a few more with more or less for different angles... good thing you just have to change the font being used and the rest takes care of it :)

Re: A Fun Experience with IM

Posted: 2010-10-14T19:49:46-07:00
by anthony
You can use the 'txt:' image output to get the coordinates of the single white dots in the distorted result. for example

Code: Select all

   convert anthony_final.gif txt:- | sed -n '/white/s/:.*//p'
the sed does two things. look for 'white' pixels in the output, and remove all the other stuff but the coordinates. Of course the API can do this too.

The order is also from top to bottom (back to front) so composing multiple figures will also work properly.

IM examples do have a section on this...
Drawing Symbols
I list three methods, but of course you want to compose images of people, so this may not be very useful to you.

Re: A Fun Experience with IM

Posted: 2010-10-15T06:06:34-07:00
by immortal26
Ah, yes that does work well. It added 1 second extra to the total rendering time instead of using autotrace and php... which I would think the method you mentioned above would be faster since it's one command and I wouldn't parsing through a huge chunk of svg to find coords. Other than that, I think this has become a great example of ImageMagick... and especially how fast it is.
First this was tried using photoshop scripting, but it took on average 30+ seconds to render one image... that was way to slow.
ImageMagick on the other hand, 5-6 seconds per image, which is perfect. There maybe some other things that can drop it even lower but I'm fine with those times at the moment.

Re: A Fun Experience with IM

Posted: 2010-10-15T06:59:09-07:00
by anthony
The slowness may be in the parsing of the image into a text file. It is one line per pixel, including ALL the black background pixels. A faster way may be to somehow get IM to only report the actual white pixels.

Hmmm... One method comes to mind is to use -fx with its 'debug()' function, but FX is itself slow, so I am not certain if it would be any faster, even with the reduced output.

Can you post a link to the 'person' image. I'd like to see if I can convert that small image into a convolution kernel for each color channel. If that works you may be able to directly convert the 'dots' into multi-colored 'people' :-)

It would be worth a try, and may lead to a new technique for IM users.

ASIDE: I see you have turned off directory reading on your site (tried to see if I could find one 'person' image on my own). 8)
It is amazing the number of people who don't think about that type of thing :-)
On the other hand I purposfully turn on directory reading for some areas, and even use a enhance directory listing with headers and file 'descriptions' for some of the files. For example

Re: A Fun Experience with IM

Posted: 2010-10-15T08:24:00-07:00
by immortal26
Yeah, everything is back up and directory listing is enabled again.
Had a runaway script going on and had couldn't figure out where it was coming from so just turned off all permissions until we figured it out, but all is good now.
For one of the members (which on average there are 3-4, and use rand(1,4) just for more realism) here is a directory for 4 of them. ... na/bitmap/

The tif version's come out better than the png's. The png's look washed out when printed.
But yeah go for it!

Re: A Fun Experience with IM

Posted: 2010-10-16T04:09:02-07:00
by anthony
I managed to do it. But any overlap looks horrible as the two images 'add' and become over bright.

I created a script called image2kernels

For example given a point pixel....

Code: Select all

convert -size 100x100 xc:black  -fill white -draw 'point 30,40 point 70,70'  pixel.png

And a download of one of your 'little figures'.

Code: Select all


Now use that script to create kernel data for each channel of the bm1.png

Code: Select all

image2kernel bm1.png kernel.dat
The above actually creates the files kernel_R.dat etc. One for every channel RGBA.
It does not specify a 'origin' point in the kernel data, so IM will default to the center
of the kernel (point of expansion).

Now convolve...

Code: Select all

convert pixel.png -alpha off \
        \( -clone 0 -morphology Convolve "`cat kernel_R.dat`" \) \
        \( -clone 0 -morphology Convolve "`cat kernel_G.dat`" \) \
        \( -clone 0 -morphology Convolve "`cat kernel_B.dat`" \) \
        \( -clone 0 -morphology Convolve "`cat kernel_A.dat`" -negate \) \
        -delete 0 -channel RGBA -combine pixel_to_bm1.png

And the pixel (and every other single pixel) has been replaced by the bm1.png image.

Of course ALL white pixels will be expanded to that image, BUT as I mentioned, any overlap will be added and then become over bright :-(

So it works, but not well.

I have added the above code to the script "convolve_image"
which will call the "image2kernel" script and do the convolve. so the above is equivelent to

Code: Select all

  convolve_image    pixel.png    bm1.png   pixel_to_bm1.png
It was worth a shot. :-)

Re: A Fun Experience with IM

Posted: 2010-10-16T22:55:11-07:00
by immortal26
Did you try using the tif version's instead of the png's of the band members? No compression... might help, or another shot.
Also these band members are in PSD smart objects... saved as tif's/png's for what we are doing... so if there is anything I can do when saving it let me know.

Re: A Fun Experience with IM

Posted: 2010-10-17T15:50:21-07:00
by anthony
TIFF would not matter for this, as essentually the conversion from an image into a kernel format is converting all the color values into floating point numbers suitable for convolution. This is a step I would like to build into IM. Of course when Fast Fourier Transform convolution operators become available (if we can find someone with the time to program them in), then convolving with images of any size would be a breeze.

However the 'addative' aspect overlapping images is an inherient part of the convolution process. It is not something that can be simply solved.

As I mentioned it was worth a try, allowing for full image processing rather than one by one composition, but looks liek you are better off using layered multiple images with composition.

Note: you can improve some memory performance by only reading in the composition image(s) once and using clone to generate other copies. This will not copy the overlay image data which reamins unchanged from compose to compose.

Re: A Fun Experience with IM

Posted: 2010-10-18T05:38:28-07:00
by immortal26
Note: you can improve some memory performance by only reading in the composition image(s) once and using clone to generate other copies. This will not copy the overlay image data which reamins unchanged from compose to compose.
Even when using random bandmembers? (rand(1,4))

Re: A Fun Experience with IM

Posted: 2010-10-19T05:19:54-07:00
by anthony
even then...

Code: Select all

  convert   image.png \
    \( bm1.png -repage +10+10 \) \
    \( bm2.png -repage +20+10 \) \
    \( bm3.png -repage +30+10 \) \
    \( bm4.png -repage +40+10 \) \
    \( -clone 1 -repage +10+20 \) \
    \( -clone 2 -repage +20+20 \) \
    \( -clone 3 -repage +30+20 \) \
    \( -clone 4 -repage +40+20 \) \
    \( -clone 1 -repage +10+30 \) \
    \( -clone 2 -repage +20+30 \) \
    \( -clone 3 -repage +30+30 \) \
    \( -clone 4 -repage +40+30 \) \
   -flatten  result.png
The above may seem long but only the data of 5 images are actually 'in memory'. all the later 12 'clones' are just references of the images meta-data only (such as its vitural canvas (page) position.

The image data, is not duplicated until it is actually modified and only the first image is modified to generate the result. As ushc the above at peak memory usage only contains the first image twice (original and finale result), and one copy of the image data for each of the 4"'band members", being composited over and over.

It is actually very efficient! Of course if you like to use a more direct loop, a shell command may not be the right API, Perl Magick can use the perl looping without needing to 'unroll' the loop as the above does.

This is something that I hope to address in IM v7 by allowing the API to read and process options give via a file or file stream (pipeline) so that the command can be run in sort of shell controlled IM. If I can get a good block of time, to do this. Such a method would be especially useful for PHP too!

Re: A Fun Experience with IM

Posted: 2010-10-20T07:54:28-07:00
by immortal26
That actually took off about a half a second in rendering time.

Re: A Fun Experience with IM

Posted: 2010-10-21T21:15:45-07:00
by anthony
-flatten basically works by creating a blank image (using background color) the final size, then compositing each image (including the first base iamge) onto that canvas, one at a time.

An API can do this as a looped composition, and specify the placement of the sub-image at taht time.
It is also not limited to just one image sequence. So if you want to get fancier than this, and save on shell and the command line parsing, an dallow looping while reaching the positions from another image, than an API interface may be a better idea. And I do not mean PHP using command calls. I mean imagick for PHP or PerlMagick, or Imagemagick using Ruby on Rails.