Do you know these Mosaic images, where a big image is composed of thousands of tiny images? Even if you don’t recognize the big image, when you’re close, it will become perfectly clear when you take a step back and look at it from a distance.
Our brain is pretty smart, when it comes to reducing visual information and recognizing patterns. Well, if we wouldn’t be able to do that, we would probably be extinct…
So how do we compose that big image out of these little tiny images? By reading the brightness information from the big image (pixel by pixel) and give this brightness to our tiny images. As simple as that.
Have a look at the demo.
Another thing is the remarkable capacity of our brain to recognize faces. As a human being we are all trained to recognize faces easily, beginning from the very first moments of our lifes. We need very few information to actually identify a face and we do it pretty fast. Much faster and even more reliable than any computer will (ever?) do. I don’t wanna go into details here, there are some scientific papers at the bottom of the page, go and read them.
In technical terms: How many pixel of information do we need to identify someones face? It’s as little as about 30×30 pixel, 80+% of the population will identify a (known) face correctly.
Play around with the demo and check different sizes. Take a big step back to see, if you can recognize these folks (if you’re one the Triona guys). But when you’re too close, it seems all like a big mud.
From a programmers standpoint, this is a Javascript demo where everything will be printed on a canvas. I read the image information like that:
var canvasForImage = $("#canvasForImage")[0];
var ctx = canvasForImage.getContext("2d");
var img = $(".imgSelected")[0];
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
return ctx.getImageData(0, 0, imgWidth, imgHeight);
and I reprint this information onto the canvas in the middle of the screen:
for (var i = 0, n = 0, x = 0, posX = 0; posX < IMG_WIDTH; x += TILE_WIDTH, posX++) {
for (var y = 0, posY = 0; posY < IMG_HEIGHT; y += TILE_HEIGHT, i++, n += 4, posY++) {
var gray = parseFloat((imgData.data[n] + imgData.data[n + 1] + imgData.data[n + 2]) / 3.0);
var opacity = parseInt(gray);
var opStr = opacity.toString(16);
ctx.fillStyle = "#" + opStr + opStr + opStr;
if (usePortrait) {
ctx.globalAlpha = (255 - opacity) / 255.0;
ctx.drawImage(img, y, x, TILE_WIDTH, TILE_HEIGHT);
} else {
ctx.fillRect(y, x, TILE_WIDTH, TILE_HEIGHT);
}
}
}
Drawing is pretty fast on a canvas, so that allowed me to animate the whole stuff.
Have fun.