Posted: October 23rd, 2009 | Author: John del Rosario | Filed under: Experiments, Programming and Development, Python | Tags: Experiments, photomosaic, Python | 2 Comments »
I haven’t posted in a long while, mostly because of school. I managed some free time the past few days and wrote a photographic mosaic generator in Python. Why not call it by its more popular name? Because it is trademarked and patented. But I don’t think I’ll get into any trouble by posting this, as this is merely for learning purposes, right?
This is a relatively simple solution. I didn’t use any complex algorithms like edge-detection, dithering or whatever (maybe I could add those later), just plain old RGB matching. I’ll try to explain the process as best and as simply as I can.
Creating the image pool
The first step is to create your image pool. The image pool is a directory of all the tiles that will be used in your mosaic, and every tile must be of the same size. The more tiles you have, the better results you get.
I used Irfanview to resize, crop, rotate and rename 1,983 photos for my image pool, plus a Python script I wrote to separate the portrait oriented photos from the landscape oriented ones.
Next, I wrote another Python script to create an SQLite database which stores all the data I need to create a photomosaic, instead of calculating each value every time I want to create a mosaic. It holds a reference to an image file, and 9 RGB values.
To calculate the RGB values of a tile, I didn’t just get the average color of the entire tile, instead I divided the tile into a 3×3 grid, then calculated the average RGB value of each cell in the grid (resulting in 9 values). I think this method is called “sub-sampling”. This helps in making more accurate matches. (Pardon the crappy images, I’m making these in Paint.NET)
Subdivided tile –> (Pseudo) Average colors
Generating the mosaic
Now that I have my image pool ready, I can start generating the photographic mosaic itself. I won’t go into the too much detail but basically I subdivide the source image with the size of my tiles. I then iterate over the subdivisions and further subdivide each cell into a 3×3 sub-grid to match against the tiles. I calculate and compare the RGB differences between every tile in my image pool, and get the best result (least difference). I then place the best tile into its proper position in the mosaic.
Subdivided cell –> Average colors of cell = Average colors of tile –> Best matching tile
I added an extra method that starts matching from the middle of the source image, going outward. This generates a mosaic where the best matches are in the center, and leftover tiles go to the edges, resulting in a better looking mosaic, especially for portraits.
Top-down matching vs. Inside-out matching
In the first one, by the time I got to the center, I ran out of good tiles to use. For the second one, the best tiles are used in the center.
Results
Try it out
This is just a bunch of Python scripts, so there is no executable to run.
Just type
>python photomosaic.py path\to\source.jpg path\to\output.jpg path\to\imagepool\dir [-options]
on the command line. Type --help to see possible options.
Of course, preparing the image pool is the most difficult part of creating a mosaic. You can use the create_image_pool.py script to do that for you. Just make sure all your tiles are of the same size, and it will automatically create an SQLite file inside your pool directory which the photomosaic generator can use.
>python create_image_pool.py path\to\imagepool\dir
If you don’t have 2,000 images lying around, you can go to this page. At the bottom of his post he has a link to .zip of photos of chemical elements. It’s already resized for you.
Right now, generating a 1,600 tiles mosaic from ~2,000 tiles takes about ~5 minutes on my slow-ish machine. My next goal would have to be speed and better matching algorithms.
Download photomosaic.zip
Posted: June 14th, 2009 | Author: John del Rosario | Filed under: Experiments, Python | Tags: Experiments, Python | 1 Comment »
I’ve always wanted to try out Python, and I’ve been meaning to make a Tetris clone for some time now ( my last attempt in Flash failed ). Since I didn’t have anything to do for the remainder of the summer, I decided to do both.
I wanted to post about this last week, during Tetris’ 25th anniversary, but it wasn’t done. This is my first Python app, so the code is filthy. I am quite proud of it though.
Unfortunately, I don’t know how to make an executable from a Python program, and the guys at the #python channel are less than helpful, so I’ll just put up a zip of all the files.
Python is fun and easy to learn, but I think I’ll stick with Flash. I will also be studying Django.
You need to have Python and Pygame installed to run it though, until I figure out how to make an executable.
Download the zip. Extract and run Main.py in ‘src/’ folder using Python.
Posted: April 15th, 2009 | Author: John del Rosario | Filed under: AS 3.0, Art and Design, Experiments, Flash | Tags: AIR, Apps, AS3, Experiments, Flex | No Comments »
I’ve updated my Color Mixer application. Right now it is as good as done. It’s not the best looking, but all the functionality is working fine. If there are any suggestions on how to improve it, I’d be glad to hear them.
I am still working on the AIR version. It’s taking a while figuring out how to skin components properly (the gradient sliders clearly show this). And it seems that taking a screenshot of the desktop is not possible on AIR, which is a shame because I was really looking forward for the feature to take any color on screen. Unless I find a workaround for this, I’m going to have to leave that feature out.
I hope someone finds this useful, as I know I do. Here it is.
On different note, this post was posted from Windows Live Writer. I’m liking it very much. I hope everything displays fine.
Posted: April 13th, 2009 | Author: John del Rosario | Filed under: AS 3.0, Programming and Development | Tags: AS3, Tutorials | 3 Comments »
In my previous post, I needed to do a lot of conversion between different representations of color. I think a post on how to convert color would be useful.
private function RGBToHex(r:uint, g:uint, b:uint):uint{
var hex:uint = (r << 16 | g << 8 | b);
return hex;
}
private function HexToRGB(hex:uint):Array{
var rgb:Array = [];
var r:uint = hex >> 16 & 0xFF;
var g:uint = hex >> 8 & 0xFF;
var b:uint = hex & 0xFF;
rgb.push(r, g, b);
return rgb;
}
private function RGBtoHSV(r:uint, g:uint, b:uint):Array{
var max:uint = Math.max(r, g, b);
var min:uint = Math.min(r, g, b);
var hue:Number = 0;
var saturation:Number = 0;
var value:Number = 0;
var hsv:Array = [];
//get Hue
if(max == min){
hue = 0;
}else if(max == r){
hue = (60 * (g-b) / (max-min) + 360) % 360;
}else if(max == g){
hue = (60 * (b-r) / (max-min) + 120);
}else if(max == b){
hue = (60 * (r-g) / (max-min) + 240);
}
//get Value
value = max;
//get Saturation
if(max == 0){
saturation = 0;
}else{
saturation = (max - min) / max;
}
hsv = [Math.round(hue), Math.round(saturation * 100), Math.round(value / 255 * 100)];
return hsv;
}
private function HSVtoRGB(h:Number, s:Number, v:Number):Array{
var r:Number = 0;
var g:Number = 0;
var b:Number = 0;
var rgb:Array = [];
var tempS:Number = s / 100;
var tempV:Number = v / 100;
var hi:int = Math.floor(h/60) % 6;
var f:Number = h/60 - Math.floor(h/60);
var p:Number = (tempV * (1 - tempS));
var q:Number = (tempV * (1 - f * tempS));
var t:Number = (tempV * (1 - (1 - f) * tempS));
switch(hi){
case 0: r = tempV; g = t; b = p; break;
case 1: r = q; g = tempV; b = p; break;
case 2: r = p; g = tempV; b = t; break;
case 3: r = p; g = q; b = tempV; break;
case 4: r = t; g = p; b = tempV; break;
case 5: r = tempV; g = p; b = q; break;
}
rgb = [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
return rgb;
}
The code above requires and returns:
- RGB values between 0 to 255
- Hexadecimal in RRGGBB format
- Hue values between 0 to 360
- Saturation and Value between 0 to 100
Notice that the “middleman” is RGB.
And, just in case you only have the Hexadecimal string to work with, here is the code to convert that string into a usable decimal value.
private function HexToDeci(hex:String):uint{
var deci:uint = 0;
var power:uint = hex.length - 1;
for(var i:uint = 0; i < hex.length; i++){
var char:String = hex.charAt(i);
if(parseInt(char) >= 0 && parseInt(char) <= 9){
deci += parseInt(char) * Math.pow(16, power);
}else{
switch(char){
case "A": case "a": deci += 10 * Math.pow(16, power); break;
case "B": case "b": deci += 11 * Math.pow(16, power); break;
case "C": case "c": deci += 12 * Math.pow(16, power); break;
case "D": case "d": deci += 13 * Math.pow(16, power); break;
case "E": case "e": deci += 14 * Math.pow(16, power); break;
case "F": case "f": deci += 15 * Math.pow(16, power); break;
}
}
power --;
}
return deci;
}
EDIT: I’ve just gathered that there is a much much simpler way to convert a Hexadecimal string into a usable number. I feel kind of stupid right now.
private function HexToDeci(hex:String):uint{
if (hex.substr(0, 2) != "0x") {
hex = "0x" + hex;
}
return new uint(hex);
}
Posted: April 9th, 2009 | Author: John del Rosario | Filed under: Experiments | Tags: AIR, App, Experiments, Flex | 3 Comments »

I’ve always found the color mixer found in the very nice Color Schemer Studio to be very useful. I’ve only used the trial, and it’s been hard living without it. So, I decided to create my own app. I’ve only made the color mixing part of the program, as it is the only feature I ever use, and anything more would only complicate things too much (this is my first Flex app).
Right now, you can choose a color from the color picker, enter a Hex value, RGB values, and HSV values. Changing one will affect the others, real-time. There’s also a button to copy the Hex value into your clipboard, for convenience.
It’s still not finished though. I’m planning on adding an eyedrop tool to pick colors from the desktop. I still need to figure out how to do that, probably only possible through AIR. And I’m having trouble customizing the sliders to have a gradient background, like in the Color Schemer Studio program, to better visualize what color you are going to get when moving the sliders. I also plan on publishing this as AIR app, to make it even more convenient. And once I get the hang of Flex, I’ll make it pretty, like all the other Flex apps out there.
Enough babbling, here is the application itself. If you have any suggestions or discover any bugs, please comment. Note though, that this is very unfinished. Right now all it has is core functionality. I haven’t even thought about the interface yet. Need to read up on customizing components first.
UPDATE: I’ve updated the app. It’s pretty much done at this point, as I am satisfied with it. But if anyone has any suggestions, I am still open. Links updated.
Posted: April 4th, 2009 | Author: John del Rosario | Filed under: AS 3.0, Experiments | Tags: Experiments | No Comments »
I’ve put on hold reading “Making Things Move”, as the remaining chapters were too much for my brain to handle. I decided to try out some cool webcam experiments. Augmented Reality is obviously out of my reach right now (but definitely in my sights), I decided to try out motion tracking.
It is very twitchy and erratic, and it’s not very accurate neither, but it works.
Most of the concepts are explained in detail here and there.
My next step would be to track something of a specific color (a marker). Shouldn’t be too hard – I hope.
CLICK TO OPEN MOVIE. Press SPACE to toggle between display modes.
Posted: March 29th, 2009 | Author: John del Rosario | Filed under: Random | Tags: Real Life | No Comments »
Hadn’t posted in a long while. I was swamped with school work – projects, exams, and more projects. But now it is all over, and I can finally take a breather.
Although, it will be a short breather; I have to go to summer class to catch up with missed classes. *sigh* Oh well, at least it’s better than just staying at home.
So, for this summer, I have a few things in mind that I plan to accomplish, in no particular order:
- finish summer classes, obviously
- finish reading “Making Things Move”
- hopefully have some semblance of a website
- learn how to drive
- have fun
There might be a few more other things, but those are the ones on the top of my head right now. They all seem attainable in the limited time I have between classes.
I’ll be back with more Flash stuff, but maybe no more random experiments this time. I’m going back to basics reading the “Making Things Move” book (awesome read).