Page 1 of 2

Converting an image into blocks of colour as a lego pattern

Posted: 2011-02-18T08:37:40-07:00
by mrship
I'm interested in taking a photo image and reducing it into blocks of colour so that it can then be reproduced using lego bricks. I've played with several options in IM 6.6.7-1 on OS X and haven't been able to create a crisp, sharp image. In reading the docs, often the requirement for a resize or colour reduction is to produce nice anti-aliased lines, whereas I actually _want_ the jaggies as lego bricks are a very coarse brush!

I've tried various techniques, with the best results coming from Fred Weinhaus' stained glass scripts (which are great BTW, I learned a lot!) with square blocks after I've reduced the number of colours in the image as well as reduced the overall size with -sample. I've also had some limited success with +dither to reduce the photo to broad areas of colour first and/or Fred's cartoon script.

However, the problems that I'm continually seeing are:

1. Often areas of the image have small areas of "rogue" pixels left after the colour reduction that don't get removed with -despeckle, or are softened too much if I try.
2. The lines in the images between different areas of colour are still very dithered/feathered and I'm not sure how to get coarser, straighter, more 'jaggie' lines to match the edges of the lego bricks.

Ultimately, I'm hoping to produce a basic pattern that can be followed by a child (mine are aged 8 and 6) to put the bricks together into a picture comparable to the initial photo.

Any help/pointers would be appreciated...thanks.

Re: Converting an image into blocks of colour as a lego patt

Posted: 2011-02-18T11:05:57-07:00
by fmw42
not sure what you really want. perhaps an example if possible. have you looked at my pixelize script and tried a larger block size? http://www.fmwconcepts.com/imagemagick/ ... /index.php

Re: Converting an image into blocks of colour as a lego patt

Posted: 2011-02-20T04:54:33-07:00
by mrship
I'll try and put together a couple of image examples, but as another way to describe what I'm trying to do, imagine that you overlay a grid on top of an image and then fill the squares of the grid in with the most dominant colour of the image beneath within each section of the grid. That way, you end up with lines between the colours in the images that are very "blocky" by nature and perfect for lego bricks!

That's the manual method that I've used in the past to create the pattern template, but its very laborious! Does that make any more sense?

Re: Converting an image into blocks of colour as a lego patt

Posted: 2011-02-20T07:11:22-07:00
by Bonzo
This is the sort of effect from Freds script - I reduced the amount of colours to 25 before pixelating. Some default colours would probably be good as well?

Image

Re: Converting an image into blocks of colour as a lego patt

Posted: 2011-02-20T15:31:55-07:00
by fmw42
You can use -map or -remap with a special color image that contains only the colors you want. see http://www.imagemagick.org/Usage/quantize/#map

Re: Converting an image into blocks of colour as a lego patt

Posted: 2011-02-20T16:21:00-07:00
by anthony
Actually as lego bricks are limited to primary and secondary colors doing blocks then thresholding with -channel RGB will probably do the job. But for things other than lego, like cross-stitch or mini-stic or glass beads, even carpet looping, then you can have a much wider range of colors.

One aspect you may like to consider when you get a lot more colors involved is also mark the various colors with some type of symbol, so you make less mistakes when following some chart.

What I would to is take the blocky color map, create a clut table to replace each color with some greyscale value, an dthen use Dithering with Symbol Patterns to create symbols you can overlap on the color pattern. That will make it clear that this square is a 'olive green' rather than a 'yellow green'.
;-)

PPS: this is one of the common cases were using a 'correct nearest color mapping' needs to be used, rather than 'near enough', as currently being discussed in the Bugs Forum.... viewtopic.php?f=3&t=18125

Re: Converting an image into blocks of colour as a lego patt

Posted: 2011-02-21T04:06:31-07:00
by mrship
Thanks for the suggestions. It mostly makes sense so far :)

However, looking at the pixelated image of the tractor, that displays the problem that I'm trying to describe where, for example, the edges of the tractor wheels are anti-aliased with a "transition" colour between the black of the tyre and the red of the tractor body. For what I'd do manually, there should be a much more pronounced straight (and stepped) edge going from black to red without the grey/red pixel in between. Given that these patterns are designed to be easy to put together for kids, the more colours involved the more complex it gets.

So, I need to remove the anti-aliasing, perhaps with some form of edge detection, or else apply some sharpening to the image first, or afterwards? I'll have a further play and see what I can produce, but any other tips on reduce the anti-aliasing would be appreciated.

Re: Converting an image into blocks of colour as a lego patt

Posted: 2011-02-21T10:18:49-07:00
by Bonzo
The more colour bricks you have the worse the output seems; I think there needs to be some user input at the start to limit the amount of colours etc.

Anyway another output.

The colour map used:
Image

The result:
Image

I wonder if having the colours "brighter/saturated" at the start would help?

Re: Converting an image into blocks of colour as a lego patt

Posted: 2011-02-21T19:42:33-07:00
by anthony
Perhaps a slightly different ordering of steps.


Before pixelating the image recolor it using your 'primary' lego colors. Then instead of making each square a 'average' of the colors, set them to the predominate color within each square.

Unfortunately selecting the predominate color in each square is not a operation that is directly provided.

We need a new convolution/morphology operator...
That is make each pixel the 'predominate color' of the specified neighbourhood.
When you have that a down/up sample pixalization will convert that to 'squares'.

That however is tricky, though about on the same processing level as the existing '-median' operator (select the 'middle' pixel of the grey level intensity found) That operator already has to create a 'list' of all pixels found, it would just need to save a list of colors with counts to work out the 'dominate color'.

Re: Converting an image into blocks of colour as a lego patt

Posted: 2011-02-21T20:13:08-07:00
by fmw42
mrship wrote:Thanks for the suggestions. It mostly makes sense so far :)

However, looking at the pixelated image of the tractor, that displays the problem that I'm trying to describe where, for example, the edges of the tractor wheels are anti-aliased with a "transition" colour between the black of the tyre and the red of the tractor body. For what I'd do manually, there should be a much more pronounced straight (and stepped) edge going from black to red without the grey/red pixel in between. Given that these patterns are designed to be easy to put together for kids, the more colours involved the more complex it gets.

So, I need to remove the anti-aliasing, perhaps with some form of edge detection, or else apply some sharpening to the image first, or afterwards? I'll have a further play and see what I can produce, but any other tips on reduce the anti-aliasing would be appreciated.

My script simply does the following:


# get parameters
w=`convert $infile -format "%[fx:w]" info:`
h=`convert $infile -format "%[fx:h]" info:`
minify=`convert xc: -format "%[fx:100/$size]" info:`

# process image
convert $infile -resize $minify% -scale ${w}x${h}! $outfile


Try replacing -resize with -scale or possibly better with -sample. Or post a link to your original tractor image so I can test this.

Fred

Re: Converting an image into blocks of colour as a lego patt

Posted: 2011-02-22T07:06:25-07:00
by mrship
fmw42 wrote:Or post a link to your original tractor image so I can test this.
Bonzo - could you please oblige. I have test images that I could post, but it makes sense to continue working with your tractor if we can.
fmw42 wrote:Try replacing -resize with -scale or possibly better with -sample
I didn't have immediate success with this, but I'm going to try some more...
anthony wrote:We need a new convolution/morphology operator...
That is make each pixel the 'predominate color' of the specified neighbourhood.
When you have that a down/up sample pixalization will convert that to 'squares'.
That sounds exactly what I'm looking for - shame it doesn't exist! (yet? :) )

Re: Converting an image into blocks of colour as a lego patt

Posted: 2011-02-22T11:28:32-07:00
by fmw42
You can do the max in a 3x3 neighborhood with my statsfilt script. So I did it twice so as to get effectively a 9x9 neighborhood, then did pixelize with -resize replaced with -sample and -s 9. Here is the result. Following that just pixelize with -s 9 on the image without the statsfilt max.


statsfilt -s 3 tractor_sm.png tractor_sm_max.png
statsfilt -s 3 tractor_sm_max.png tractor_sm_max2.png
Image

pixelize1 -s 9 tractor_sm_max2.png tractor_sm_max2_pixelize9.png
Image


pixelize1 -s 9 tractor_sm.png tractor_sm_pixelize9.png
Image


PS. I believe that the max operation is already available in -morphology dilate on a colored image

convert tractor_sm.png -morphology dilate square:4 tractor_sm_dilate4.png
Image


pixelize1 -s 8 tractor_sm_dilate4.png tractor_sm_dilate4_pixelize8.png
Image

Re: Converting an image into blocks of colour as a lego patt

Posted: 2011-02-22T16:54:47-07:00
by NicolasRobidoux
Have you thought of median filtering based on an area about the size of the blocks, then downsampling with nearest neighbour? (You could also repeatedly median filter over a small area + downsample by half + median filer + downsample + ...? Then, you re-enlarge to the original size with nearest neighbour.

(I've not tried it: It's just an idea.)

Re: Converting an image into blocks of colour as a lego patt

Posted: 2011-02-22T18:45:07-07:00
by anthony
Its is not a 'max' value that is wanted. But the most common color.

Try using a +dither -map colormap replacement first, then in each square select the most common color.

Re: Converting an image into blocks of colour as a lego patt

Posted: 2011-02-22T19:56:52-07:00
by fmw42
anthony wrote:Its is not a 'max' value that is wanted. But the most common color.

Try using a +dither -map colormap replacement first, then in each square select the most common color.
Yes, you are right most frequent is not max. I don't know what I was thinking. IM could use some statistical filters such mode, most frequent, k-nearest neighbors average, etc. But I know you don't have time and it is low on the priority list.