viernes, 5 de diciembre de 2008

Bienvenidos al Blog de Computacion Grafica

Todos sean bienvenidos al blog de Computación Gráfica y Visual, hecho por los alumnos de Ing. de Sistemas de la Universidad Privada del Norte Trujillo ~ Perú :

Renzo Lizárraga Geldres

Eduardo Díaz Roncal

Darwin Aguilar Julca

Esperemos encuentren toda la información que necesiten aquí.



PROCESAMIENTO DE IMÁGENES

En la parte visual, tenemos lo que es procesamiento de imágenes, son un conjunto de algoritmos que tienen como fin modificar, ya sea para bien o para mal, una imagen dada.

Pueden darse 3 tipos de procesamientos:
• Por puntos : se va procesando la imagen píxel por píxel.
• Local : se procesa por regiones, llamadas operaciones de vecindad ya que se utiliza un píxel y sus valores cercanos.
• Global : como su mismo nombre lo dice, el procesamiento de imágenes es global, es decir la imagen completa.

Se implementaron varios algoritmos de procesamiento de imágenes, entre ellos :

1. Diversos Filtros ( Gaussiano, promedio, realce, etc) : tienen como fin acentuar o disminuir una determinada característica de la imagen a procesar. Se usa la convolusión para esto, consiste en multiplicar la matriz de píxeles de la imagen por una máscara dada, para los cambios que se requieran.
2. Umbrales : el nivel de transición de grises se da por un valor dado que dividirá al mismo.
3. Inversa o negación : para simplemente cambiar los bits de blanco a negro y de negro a blanco, volviendo a la imagen negativa.
4. Binarización : tiene como objetivo principal diferenciar el objeto,persona,etc de la imagen del fondo de esta.


Veremos aquí los más importanes.

3.1 Negación :
Siendo img la imagen :

I=imread(img);
I=double(I);
[f,c]=size(I);
NI=255-I;
imshow(uint8(I))
pause;
imshow (uint8(NI));

Simplemente obtenemos el complemento a 255 de cada uno de los píxeles.

3.2 Binarización:

I=imread(imagen);
I=double(I);
[n,m]=size(I);

for i=1:n
for j=1:m
if I(i,j) IN(i,j)=0;
else
IN(i,j)=255;
end
end
end

imshow(uint8(I))
pause;
imshow(uint8(IN))

Se especifica un parámetro, desde el cual los valores menores a él se harán negros y los otros blancos.

3.3 Valor Umbral:

%leyendo imagen
I=imread(imagen);

I=double(I); %convirtiendo enteros a dobles
[n,m]=size(I); %calcular el tamaño

for i=1:n %para el eje Y es decir filas
for j=1:m %para el eje X es decir columnas
if (I(i,j)<=param)
IN(i,j)=255;
else
IN(i,j)=0;
end

end

end
imshow(uint8(I))
pause;
imshow(uint8(IN))

Da tonos de grises a partir de un valor ingresado como parámetro.

3.4 Umbral Intervalo:

%leyendo imagen
I=imread(imagen);

I=double(I); %convirtiendo enteros a dobles
IO=I;
[n,m]=size(I); %calcular el tamaño

for i=1:n %para el eje Y es decir filas
for j=1:m %para el eje X es decir columnas
%u1=50 u2=190
if (I(i,j)<=param1 | I(i,j)>=param2)
I(i,j)=255;
else
if(param1 IN(i,j)=I(i,j);
end
end

end

end
imshow(uint8(IO))
pause;
imshow(uint8(IN))

Es el mismo que el anterior, pero esta vez dado por un intervalo de 2 valores, al modificarse estos se obtendrán resultados muy diferentes.

3.5 Filtro Gaussiano

img=imread(imagen);
img=double(img);
[m,n]=size(img);
p=0;
mascara=[1,2,1 ; 2,4,2 ; 1,2,1];
for i=2:m-1
for j=2:n-1
for h=1:3
for k=1:3
p = p + img(i+h-2,j+k-2)* mascara(h,k);
end
end
img2(i,j) = p/16;
p=0;
end
end
imshow(uint8(img))
pause;
imshow(uint8(img2))

Aquí empezamos ya a usar operaciones d vecindad o locales, en este caso usamos una máscara y la comparamos con puntos específicos de la imagen.

Al cambiar la máscara se obtienen varios resultados, como por ejemplo :

3.6 Filtro Mediana:
img=imread(imagen);
img=double(img);
[m,n]=size(img);
p=0;
for i=2:m-1
for j=2:n-1
g=0;
for h=1:3
for k=1:3
g=g+1;
v(g)=img(i+h-2,j+k-2);%guardo los valores en un arreglo
end
end

%ordeno el arreglo "v"
for vi=1:9
for vj=1:9
if v(vi) > v(vj)
temp=v(vi);
v(vi)=v(vj);
v(vj)=temp;
end

end
end
img2(i,j) = v(5);%el pixel tendra el valor de la mediana
end
end
imshow(uint8(img))
pause;
imshow(uint8(img2))

3.7 Filtro Promedio:
img=imread(imagen);
img=double(img);
[m,n]=size(img);
p=0;
mascara=[1,1,1 ; 1,1,1 ; 1,1,1];
for i=2:m-1
for j=2:n-1
for h=1:3
for k=1:3
p = p + img(i+h-2,j+k-2)* mascara(h,k);
end
end
img2(i,j) = p/9;
p=0;
end
end
imshow(uint8(img))
pause;
imshow(uint8(img2))


3.8 Filtro Promedio Rango:

img=imread(imagen);
img=double(img);
[m,n]=size(img);
p=0;
mascara=[1,1,1 ; 1,1,1 ; 1,1,1];
for i=2:m-1
for j=2:n-1

for h=1:3

for k=1:3

if img(i+h-2,j+k-2) > 60 & img(i+h-2,j+k-2) < 250
p = p + img(i+h-2,j+k-2) * mascara(h,k);

end
end
end
img2(i,j) = p/9;
p=0;
end
end

imshow(uint8(img))
pause;
imshow(uint8(img2))


3.9 Filtro Realce:

img=imread(imagen);
img=double(img);
[m,n]=size(img);
p=0;
mascara=[-1/8,-1/8,-1/8 ; -1/8,1,-1/8 ; -1/8,-1/8,-1/8];
for i=2:m-1
for j=2:n-1
for h=1:3
for k=1:3
p = p + img(i+h-2,j+k-2)* mascara(h,k);
end
end
img2(i,j) = p;
p=0;
end
end
imshow(uint8(img))
pause;
imshow(uint8(img2))


3.10 Extensión:

img=imread(imagen);
img=double(img);
[m,n]=size(img);
for i=1:m
for j=1:n
img2(i,j)=(img(i,j)-u1)*255/(u2-u1);

end
end
imshow(uint8(img))
pause;
imshow(uint8(img2))


3.11 Histograma:

img=imread(imagen);
img=double(img);
[m,n]=size(img);
histograma=zeros(1,256);
for i=1:m
for j=1:n
histograma(img(i,j)+1)= histograma(img(i,j)+1) + 1;
end
end
plot(histograma);

Muestra el nivel de color o de gris de cada pixel de la imagen en un gráfico de barras o de ondas. Al ampliarlo se puede modificar el contraste:

img=imread(handles.direccion);
a=str2double(get(handles.txtExpHistA,'string'));
b=str2double(get(handles.txtExpHistB,'string'));
img=double(img);
[m,n]=size(img);
for i=1:m
for j=1:n
img(i,j)=(img(i,j)*(b-a)/255)+a;

end
end
axes(handles.Procesada);
image(uint8(img))


También se pueden hacer operaciones con 2 imágenes como sumar y restar:

3.12 Suma :

imagen1=imread(ima);
imagen2=imread(ima2);
imagen1=double(imagen1);
imagen2=double(imagen2);
[X,Y,Z]=size(imagen1);
for i=1:X
for j=1:Y
for k=1:Z
imagen3(i,j,k) = ((imagen1(i,j,k) + imagen2(i,j,k))/2);
end
end
end

imshow(uint8(imagen1));
pause;
imshow(uint8(imagen2));
pause;
imshow(uint8(imagen3));

3.13 Resta :

imagen1=imread(ima);
imagen2=imread(ima2);
imagen1=double(imagen1);
imagen2=double(imagen2);
[X,Y]=size(imagen1);
for i=1:X
for j=1:Y
imagen3(i,j)=(imagen1(i,j)-imagen2(i,j))*2;
end
end
imshow(uint8(imagen1));
pause;
imshow(uint8(imagen2));
pause;
imshow(uint8(imagen3));

Algoritmos Open GL para generación de gráficas.

Como todos saben Open GL es una herramienta que nos facilita mucho la generación de gráficos por computadora. Aqui aplicamos conocimientos matemáticos, usando Open GL para generar rectas, corcunferencias, elipses, etc.

1.1 DDA:

El Algoritmo DDA es un algoritmo de línea de conversión de rastreo que se basa en el cálculo ya sea en el incremento de X o en el incremento de Y. La finalidad de este algoritmo es determinar los valores enteros correspondientes más próximos a la trayectoria de la línea para la otra coordenada.


Código:

void DDA(int x0,int y0,int xFin,int yFin)

{

int dx = xFin - x0, dy = yFin - y0, steps, k;

float xIncremento, yIncremento;

float x = x0, y = y0;

if (fabs (dx) > fabs (dy))

steps = fabs (dx); /* |m|<1>

else

steps = fabs (dy); /* |m|>=1 */

xIncremento=float(dx)/float (steps);

yIncrement = float (dy) / float (steps);

setPixel (round (x), round (y));

for (k = 0; k <>

{

x += xIncremento;

y += yIncremento;

setPixel (round (x), round (y));

}

}


1.2 BRESENHAM:


El algoritmo de Bresenham sirve para trazar una línea entre dos puntos.



Código:


void Bres(int x0,int y0,int xFin,int yFin)

{

int dx = fabs(xFin - x0),

dy = fabs(yFin - y0);

int p = 2 * dy - dx;

int dosDy = 2 * dy,

dosDyMenosDx = 2 * (dy - dx);

int x, y;

/* Determinamos que punto usamos como inicio. */

if (x0 > xFin) {

x = xFin;

y = yFin;

xFin = x0;

}

else {

x = x0;

y = y0;

}

setPixel (x, y);

while (x <>

x++;

if (p <>

p += dosDy;

else {

y++;

p += dosDyMenosDx;

}

setPixel (x, y);

}

}


1.3 PUNTO MEDIO PARA CIRCULOS:

El algoritmo de línea de Bresenham se adapta a la generación de circunferencias al establecer los parámetros de decisión para identificar el pixel más cercano a la circunferencia en cada paso del muestreo.Además sincroniza el dibujado de los píxeles en cada octante de la circunferencia.



Código:


void circuloPtoMedio(scrPt circCtr, GLint radio)

{

scrPt circPt;

GLint p = 1 - radio;

circPt.x = 0;

circPt.y = radio;

void circuloPuntos(scrPt, scrPt);

/* Dibujamos el punto inicial en cada cuadrante del circulo*/

circuloPuntos(circCtr, circPt);

/* Calculamos los siguientes puntos y los dibujamos en cada octante*/

while (circPt.x <>

circPt.x++;

if (p <>

p += 2 * circPt.x + 1;

else {

circPt.y--;

p += 2 * (circPt.x - circPt.y) + 1;

}

circuloPuntos(circCtr, circPt);

}

}

void circuloPuntos(scrPt circCtr, scrPt circPt);

{

setPixel (circCtr.x + circPt.x, circCtr.y + circPt.y);

setPixel (circCtr.x - circPt.x, circCtr.y + circPt.y);

setPixel (circCtr.x + circPt.x, circCtr.y - circPt.y);

setPixel (circCtr.x - circPt.x, circCtr.y - circPt.y);

setPixel (circCtr.x + circPt.y, circCtr.y + circPt.x);

setPixel (circCtr.x - circPt.y, circCtr.y + circPt.x);

setPixel (circCtr.x + circPt.y, circCtr.y - circPt.x);

setPixel (circCtr.x - circPt.y, circCtr.y - circPt.x);

}


1.4 PUNTO MEDIO PARA ELIPSES

Expresado de forma ambigua, una elipse es una circunferencia alargada. Por lo tanto, las curvas elípticas se pueden generar al modificar los procedimientos para el trazo de circunferencias con el fin de considerar las diversas dimensiones de una elipse a lo largo de los ejes mayor y menor.



Codigo:


void puntomedioElipse(int xc,int yc,int rx, int ry)

{

int Rx2 = rx*rx; //rx^2

int Ry2 = ry*ry; //ry^2

int DosRx2 = 2*Rx2; //2rx^2

int DosRy2 = 2*Ry2; //2ry^2

int p1;

int p2;

int x = 0;

int y = ry;

int px = 0; //2ry^2

int py = DosRx2 * y; //2rx^2*ry

//Region 1

p1=Ry2-(Rx2*ry) + (0.25*Rx2);

while (px <>

x++;

px = px + DosRy2;

if (p1 <>

p1 = p1 + Ry2 + px;

else {

y--;

py = py - DosRx2;

p1 = p1 + Ry2 + px - py;

}

setPixel(xc+x,yc+y);

setPixel(xc-x,yc+y);

setPixel(xc+x,yc-y);

setPixel(xc-x,yc-y);

}

//Region 2

p2=Ry2*(x+0.5)*(x+0.5) + Rx2*(y-1)*(y-1)-Rx2*Ry2;

while (y > 0){

y--;

py = py - DosRx2;

if (p2 > 0)

p2 = p2 + Rx2 - py;

else {

x++;

px = px + DosRy2;

p2 = p2 + Rx2 - py + px;

}

setPixel(xc+x,yc+y);

setPixel(xc-x,yc+y);

setPixel(xc+x,yc-y);

setPixel(xc-x,yc-y);

}

}

1.5 TRANSFORMACIONES



Traslacion:(verde) las traslaciones son movimientos directos, es decir, mantienen la forma y el tamaño de las figuras, a las cuales deslizan según el vector t.

Código:

int Xo,Yo,Xfin,Yfin;

int Tx=10,Ty=15,Sx=2,Sy=3,angulo=37;

void traslacion()

{

glBegin(GL_LINES);

glColor3f(0.0,1.0,0.0);

glVertex2i(Xo+Tx,Yo+Ty);

glVertex2i(Xfin+Tx,Yfin+Ty);

glEnd();

glFlush();

}

Rotacion:(negro) las rotaciones son movimientos directos, es decir, mantienen la forma y el tamaño de las figuras. El sentido de rotación puede ser positivo (en contra del sentido horario) o negativo (a favor del sentido horario).

Código:

int Xo,Yo,Xfin,Yfin;

int Tx=10,Ty=15,Sx=2,Sy=3,angulo=37;

void rotacion()

{ double Xp,Yp,Xp1,Yp1;

Xp=Xo*(cos(angulo)) - Yo*(sin(angulo));

Yp=Xo*(sin(angulo)) + Yo*(cos(angulo));

Xp1=Xfin*(cos(angulo)) - Yfin*(sin(angulo));

Yp1=Xfin*(sin(angulo)) + Yfin*(cos(angulo));

glBegin(GL_LINES);

glColor3f(0.0,0.1,0.0);

glVertex2i((int)Xp,(int)Yp);

glVertex2i((int)Xp1,(int)Yp1);

glEnd();

glFlush();

}

Escalado:(azul) con el escalamiento podemos aumentar/disminuir un objeto en cuanto a tamaño. Tan sólo tendremos que multiplicar a cada uno de sus coordenadas por una variable de escalamiento.

Código:

int Xo,Yo,Xfin,Yfin;

int Tx=10,Ty=15,Sx=2,Sy=3,angulo=37;

void escalado()

{

glBegin(GL_LINES);

glColor3f(0.0,0.0,1.0);

glVertex2i(Xo*Sx,Yo*Sy);

glVertex2i(Xfin*Sx,Yfin*Sy);

glEnd();

glFlush();

}