Dibujando la alfombra de Sierpinski con pixeles

Posted · Añadir comentario

self_portrait_sierpinski

Hagamos el ejercicio de intentar llevar la lógica del conjunto fractal de la alfombra de Sierpinski al nivel del pixel. Para hacerlo necesitaremos trabajar con imágenes cuyas dimensiones sean potencia de 3, de modo que podamos ir dividiendo sucesivamente el ancho y el alto de la imagen en tres partes iguales, hasta llegar a un fragmento de 1 x 1 pixel.

1, 3, 9, 27, 81, 243, 729 ...

Usemos una imagen de 729 x 729 pixeles para dibujar un Sierpinski de 6 niveles. ¿Cómo podemos saber que pixeles corresponden al cuadrado central de 243 x 243 cuando recorremos la matriz?

sierpinski_00

Lo primero que necesitaremos es conocer las coordenadas X e Y de cada pixel en función de su índice, para lo que utilizaremos el sistema de cálculo que propusimos en el artículo 01. También es importante recordar que multiplicaremos todas las medidas por 3 ya que, para cada pixel, en realidad hay tres valores almacenados en la matriz, R, G y B.

for (int i=0; i<totalPixels; i++) {

	int x = i % (width * 3);
	int y = (i - x) / (width * 3);

	// do something with x and y  …

}

Como el ancho de nuestra imagen es de 729 pixeles, los pixeles del extremo izquierdo empiezan en la coordenada X = 0 y los del extremo derecho acaban en la coordenada X = 728. Por lo tanto, si dividimos la coordenada X de cualquiera de los pixeles entre 243 siempre obtendremos un valor entre 0 y 2,996, que será inferior a 1 cuando se trate de pixeles de la zona anterior al cuadrado central, estará entre 1 y 2 cuando se trate de pixeles de la zona central y será igual o superior a 2 cuando se trate de pixeles de la zona posterior.

sierpinski_03

Si queremos obtener un número entero al dividir y evitar trabajar con decimales, podemos calcular el resto de la división entera y restarlo previamente, utilizando el operador módulo. Así obtendremos un valor igual a 0 para todos los pixeles de la zona anterior al cuadrado, igual a 1 para todos los pixeles del cuadrado central e igual a 2 para todos los pixeles de la zona posterior.

	int resto_x = x % (243 * 3);
	int zona_x  = (x - resto_x) / (243 * 3);

Realizando el mismo cálculo en el eje Y, podemos establecer que todos aquellos pixeles en los que obtengamos 1 y 1 como resultados, están situados en el cuadrado central de la imagen.

for (int i=0; i<totalPixels; i++) {

	int x = i % (width * 3);
	int y = (i - x) / (width * 3);

	int resto_x = x % (243 * 3);
	int resultado_x  = (x - resto_x) / (243 * 3);
	int resto_y = y % (243 * 3);
	int resultado_y  = (y - resto_y) / (243 * 3);

	if ((resultado_x == 1)&&(resultado_y == 1)) {
		// do something with pixels[i]  ...
	}

}

Una vez sabemos qué pixeles están en el cuadrado central del primer nivel, intentemos averiguar cuales de los pixeles que no están en dicho cuadrado, están en los cuadrados centrales de de las 8 áreas que quedan definidas a su alrededor. Cada una de estas nuevas zonas tiene un tamaño de 243 x 243 pixeles y, a su vez, sus cuadrados centrales miden 81 x 81 pixeles. ¿Como podemos averiguar las coordenadas X e Y de cada pixel dentro de este nuevo marco de referencia?

sierpinski_01

Reflexionemos un poco, ¡en realidad ya las conocemos! Los restos de la división entera, que calculamos con el operador módulo, nos indican dichas coordenadas ya que equivalen al número de pixeles que hemos recorrido desde que sobrepasamos la zona anterior a aquella en la que estamos.

sierpinski_04

Saber que pixeles están en los nuevos cuadrados centrales, en realidad, es un problema que ya hemos resuelto con una matriz de diferentes dimensiones. Solamente tenemos que aplicar la misma lógica que en el primer nivel, considerando que ahora tenemos una matriz de 243 x 243 con un cuadrado central de 81 x 81 pixeles.

	if ((resultado_x == 1)&&(resultado_y == 1)) {
		// do something with pixels[i]  ...
	} else {
		int x1 = resto_x;
		int y1 = resto_y;
		
		int resto_x1 = x1 % (81 * 3);
		int resultado_x1  = (x1 - resto_x1) / (81 * 3);
		int resto_y1 = y1 % (81 * 3);
		int resultado_y1  = (y1 - resto_y1) / (81 * 3);

		if ((resultado_x1 == 1)&&(resultado_y1 == 1)) {
			// do something with pixels[i]  ...
		}
	}

Aplicando el mismo sistema podemos proseguir sucesivamente con cuadrados cada vez más pequeños, de 27 x 27, de 9 x 9 y, finalmente de 3 x 3, el último nivel al que podemos llegar trabajando con pixeles.

sierpinski_02

En la siguiente aplicación encontrareis un ejemplo de como hemos combinado el concepto de áreas de activación, descrito en el articulo 00, con la alfombra de Sierpinski, para definir una retícula de zonas sensibles, activables y desactivables, con la que interactuar a través de una web cam.

https://github.com/alg-a/herm3TICa/tree/master/exploracion%20pruebas%20y%20juegos/SierpinskiGreyScale

 
 

Uso de cookies

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información.plugin cookies

ACEPTAR
Aviso de cookies