Códigos Cadena
Una
manera para encontrar los contornos, es utilizar el algoritmo de códigos de
cadena. Los códigos de cadena tienen como objetivo representar un contorno por medio de una
sucesión conexa de segmentos de longitud y dirección especificadas. La conexión
de los segmentos se lleva a cabo en entornos de 4 vecinos o de 8 vecinos.
Cuando se usa un entorno de 4 vecinos tendremos cuatro orientaciones para los
segmentos, como se muestra en la siguiente figura, y utilizaremos los números 0,1,2 y 3 para especificar la orientación
de los segmentos. Si se usa un entorno de 8 vecinos tendremos 8 orientaciones posibles (ver siguiente figura).
El código de cadena genera una secuencia de números
que representan las orientaciones de los segmentos conectados consecutivamente,
partiendo de un punto del contorno y siguiendo el sentido de las agujas del
reloj. Por ejemplo, la cadena 0033333323221211101101 representa el
contorno del objeto de la figura posterior cuando empezamos por el píxel superior izquierdo del contorno. Aunque depende
del punto de partida, ello no supone un problema pues se puede considerar el
código como una lista circular en el caso de contornos cerrados.
En nuestro programa se intercambian la orientación para el contorno 4
en la siguiente manera:
/**
* 2
* 1_3
* 0
*/
private Punto getProxVec4(int x, int y){
int startDirection = (directCuat+3) % 4;
int i = 0;
Punto d = null;
while(i < 3){
d = getPuntoVecino4(x, y, startDirection);
if(d != null){
directCuat = startDirection;
break;
}
startDirection = mod ((startDirection +1), 4);
i++;
}
return d;
}
Recibe como argumentos la posición del pixel y regresa una variable de tipo Punto, que hace referencia a una posición en la imagen. El método encargado de encontrar el punto vecino de acuerdo a la dirección que se le proporciona se muestra a continuación:
private Punto getPuntoVecino4(int x, int y, int dir) {
switch(dir) {
case 0:
return(enLimite(x+1,y)&&esPixel(x+1,y))?
new Punto(x+1,y):null;
case 1:
return(enLimite(x,y-1)&&esPixel(x,y-1))?
new Punto(x,y-1):null;
case 2:
return(enLimite(x-1,y)&&esPixel(x-1,y))?
new Punto(x-1,y):null;
case 3:
return(enLimite(x,y+1)&&esPixel(x,y+1))?
new Punto(x,y+1):null;
default:
return null;
}
}
El método enLimite, se encarga de verificar que solamente abarque los puntos dentro de la imagen, mientras que el método esPixel, verifica que el elemento de la matriz corresponda a valores permitidos. Se muestran a continuación los dos métodos:
private boolean enLimite(int x, int y){
if((x >= 0 && x < height) && (y >= 0 && y < width)) {
return true;
} else {
return false;
}
}
private boolean esPixel(int x, int y){
if(imagen[x][y] > 0) {
return true;
} else {
return false;
}
}
En caso de que la dirección corresponda a un valor
correcto (dentro de la matriz o sea un pixel) regresará una variable de tipo
Punto, con la posición en la cual corresponde al borde.
La trayectoria del contorno es obtenida con el
método inicio4.
Este método empieza con el primer pixel de la imagen, el cual se obtiene
barriendo la imagen desde la primera línea de izquierda a derecha; y regresa
una lista de valores de tipo Punto que representa la posición del contorno de
la imagen.
public List<Punto> inicio4(int x, int y) {
List<Punto> ruta = new ArrayList<Punto>();
Punto firstCell = new Punto(x, y);
Punto d1 = firstCell;
ruta.add(new Punto(x,y)); //Add cell1
Punto secondCell = getProxVec4(x, y);
Punto d2 = secondCell;
do{
x = (int) d2.getX();
y = (int) d2.getY();
d1 = d2;
d2 = getProxVec4(x, y);
ruta.add(new Punto(x,y));
}while(!d1.equals(firstCell)&&
!d2.equals(secondCell)&&d2!=null);
}while(!d1.equals(firstCell)&&
!d2.equals(secondCell)&&d2!=null);
ruta.remove(0);
return ruta;
}
En la siguiente figura se muestra un resultado de la aplicación del algoritmo de códigos de cadena.
De manera análoga funcionan los métodos para calcular el contorno 8, el
cual fue también modificado de la siguiente forma:
/**
* 345
* 2_6
* 107
*/
Si te fue útil esta información, recuerda ponerme como referencia para tus trabajos o proyectos.
Referencias
·
Burger
Wilhelm and Burge Mark, Digital Image Processing, Primera Edición, Editorial
Springer, 2008.
excelente articulos sobre los codigos de cadena, me gustaria saber más sobre el codigo de 8N, tienes algun dato de contacto?
ResponderEliminar