Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Gráficos
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 16-02-2007
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Gradiante de Sobel. Detección de contornos

Buenas foristas...
Ando nuevamente a la carga...

Estoy implementando funciones de detección de contornos mediante gradientes. Por ahora estoy aplicando el de Sobel. Tengo entendido que aplica una plantilla:
-1 0 -1
-2 0 2
-1 0 1
Para contornos horizontales. Y:
-1 -2 -1
0 0 0
1 2 1
Para los verticales.

Al funcionamiento lo tengo bien en claro... con dichas plantillas le hago un filtrado espacial y se suman los valores de ambos gradientes. Y si es mayor a un umbral... el valor que corresponde a la imagen es 1, sino 0.

Mi duda pasa por una cuestión un poco más práctica... De otra ayuda que me vino de mano del buen amigo seoane. El filtrado no se aplica en los bordes. Pero claro... cuando se aplica el algoritmo... el borde queda negro. Y esto puede que no sea parte de las formas analizadas en la imagen. ¿Me explico?

La solución sería aplicar una plantilla como la de Roberts que es de 2x2 y esta si podría usarse en los bordes. Pero esta plantilla tiene el defecto de no ser sencible a transiciones suaves.

¿Habría un método... predictivo o matemático que permita determinar si algún valor del borde forma parte del contorno de los objetos o formas que contiene una imagen? Estaba pensando en asignar un valor en blanco en los bordes... Pero a lo mejor no es una buena solución.

Gracias a todos que se hayan tomado las molestias de leer este hilo.
Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #2  
Antiguo 17-02-2007
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Buenas...
Después de buscar alguna info por la red para ver si logro despejar mi duda... no he logrado responderme.
La cuestión sigue en pie.

Agradecería si alguien sabría indicarme como tratar correctamente a este "inconveniente"

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #3  
Antiguo 18-02-2007
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
A ver, si me explico bien... pues... lo más que he logrado encontrar (serio, confiable,académico y por supuesto sencillo) fue en la wikipedia

En el enlace se ve claramente un ejemplo de lo que me refiero: ¿Forma o no el pixel (bajo estudio) correspondiente al borde de la imagen PARTE de algún objeto visualizado en la imagen?

Veran el mecanismo de filtrado que empleo no parte desde el borde, sino desde un pixel más interior. Ya que a lo sumo tiene 5 pixeles vecino con los cuales se estima el valor de filtrado. Si se realizan las operaciones con estos vecinos el valor que se obtiene es cercano al negro y el valor estimado no es correcto.

Como el gradiente de sobel se realiza tanto en dirección horizontal como vertical el valor obtenido de entre ellos (suma) se compara con un valor umbral para determinar si dicho pixel es o no parte del contorno. Con que uno de los valores de los gradientes sea lo suficientemente cercano al negro podría predecirse erroneamente que se trata del contorno de algun objeto.

Al evitarme el análisis desde el borde... queda éste sin filtrar... y por tanto... el efecto que se obtiene es una imagen con los contornos y un "borde" falso. Y existe el peligro de que algun punto del borde corresponda a algun contorno.

Espero haberme explicado bien. La verdad es que esto me está dejando sin cerebro... Por favor si alguien tiene conocimientos de ésto (muy posiblemente todo lo que dije suene chino para varios) y entiende mi dilema le agradecería si me puede dar una pequeña mano.

Gracias
Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #4  
Antiguo 18-02-2007
Avatar de seoane
[seoane] seoane is offline
Miembro Premium
 
Registrado: feb 2004
Ubicación: A Coruña, España
Posts: 3.717
Poder: 24
seoane Va por buen camino
Bueno, puedes resolver el problema de los bordes de la misma manera que lo hace Gimp. Si es bueno para ellos, supongo que para nosotros también sera suficiente

Aquí tienes el código en C del plugin de sobel del Gimp:
http://www.koders.com/c/fid044208159...F79285EC1.aspx

Si te fijas en el código, se puede ver que en el caso de los bordes utiliza para reemplazar a la columna o fila que falta, la propia fila o columna que se esta analizando. Es decir, si estamos en la primera fila, utilizamos como fila anterior también la primera fila. Si estamos en la ultima fila, utilizamos como fila siguiente la ultima fila. Y lo mismo con las columnas.
Responder Con Cita
  #5  
Antiguo 18-02-2007
Avatar de seoane
[seoane] seoane is offline
Miembro Premium
 
Registrado: feb 2004
Ubicación: A Coruña, España
Posts: 3.717
Poder: 24
seoane Va por buen camino
Bueno, puedes resolver el problema de los bordes de la misma manera que lo hace Gimp. Si es bueno para ellos, supongo que para nosotros también sera suficiente

Aquí tienes el código en c del plugin de sobel del Gimp:
http://www.koders.com/c/fid044208159...F79285EC1.aspx

Si te fijas en el código, se puede ver que en el caso de los bordes utiliza para reemplazar a la columna o fila que falta, la propia fila o columna que se esta analizando. Es decir, si estamos en la primera fila, utilizamos como fila anterior también la primera fila. Si estamos en la ultima fila, utilizamos como fila siguiente la ultima fila. Y lo mismo con las columnas.

PD: Delphius, creo que esta misma solución también se podría aplicar para el caso del suavizado.
Responder Con Cita
  #6  
Antiguo 18-02-2007
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 25
Delphius Va camino a la fama
Gracias seoane. Le heché un buen ojo al código... pues mucho de C no entiendo (es más... creo que esta es la 3ra o 4ta vez que veo codigo C )

Cita:
Empezado por seoane
Si te fijas en el código, se puede ver que en el caso de los bordes utiliza para reemplazar a la columna o fila que falta, la propia fila o columna que se esta analizando. Es decir, si estamos en la primera fila, utilizamos como fila anterior también la primera fila. Si estamos en la ultima fila, utilizamos como fila siguiente la ultima fila. Y lo mismo con las columnas.
Algo asi estaba intentando pensar... buscarle la "vuelta" al tema de los bordes. Yo inicialmente estaba pensando en tomar los dos vecinos disponibles y no uno, pero a lo mejor sería complicarlo demasiado y tal vez el suavisado sea un valor más bajo del real.

Y de acuerdo a lo que dices tu y el código parece que el ponderar el análisis de la fila/columna borde dos veces... ofrece un valor mejor. Al menos en la teoria suena tentadora... voya ver que dice la práctica

Gracias!
Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #7  
Antiguo 18-02-2007
Avatar de seoane
[seoane] seoane is offline
Miembro Premium
 
Registrado: feb 2004
Ubicación: A Coruña, España
Posts: 3.717
Poder: 24
seoane Va por buen camino
Bueno, como ayer ya me metí en el tema, ahora no me queda mas remedio que acabarlo. Si no lo termino no me quedo contento

El código seria el siguiente:
Código Delphi [-]
type
  TRGB = array[1..3] of Byte;
  PRGB = ^TRGB;
  TFila = array[1..3] of TRGB;
  PFila = ^TFila;

function Calcular(F1, F2, F3: PFila; i,j, Umbral: integer): TRGB;
var
  k: integer;
begin
  for k:= 1 to 3 do
  begin
    Result[k]:=
      Trunc(
        sqrt(
          // Horizontal
          sqr((F1[1][k]*(-1)) + (F1[i][k]*(-2)) + (F1[j][k]*(-1)) +
              (F3[1][k]*1) + (F3[i][k]*2) +(F3[j][k]*1)) +
          // Vertical
          sqr((F1[1][k]*(-1)) + (F1[j][k]*1) +
              (F2[1][k]*(-2)) + (F2[j][k]*2) +
              (F3[1][k]*(-1)) + (F3[j][k]*1) )
        )  / 5.66
      );
    // Umbralizar ¿se dice asi?, si el Umbral es cero no lo usamos
    if Umbral > 0 then
      if Result[k] > Umbral then
        Result[k]:= 255
      else
        Result[k]:= 0;
  end;
end;

procedure Sobel(Img: TPicture; Umbral: Integer);
var
  Bitmap: TBitmap;
  P1,P2,P3,P4: PByte;
  i,j: Integer;
begin
  Bitmap:= TBitmap.Create;
  try
    Bitmap.Width:= Img.Width;
    Bitmap.Height:= Img.Height;
    Bitmap.Canvas.Draw(0,0,Img.Graphic);
    if not (Img.Graphic is TBitmap) then
      Img.Assign(Bitmap);
    Img.Bitmap.PixelFormat:= pf24bit;
    Bitmap.PixelFormat:= pf24bit;
    for j:= -1 to Bitmap.Height - 2 do
    begin
      // Ajustamos el borde superior
      if j < 0 then
        P1:= Bitmap.ScanLine[0]
      else
        P1:= Bitmap.ScanLine[j];
      P2:= Bitmap.ScanLine[j+1];
      // Ajustamos el borde inferior
      if j > Bitmap.Height - 3 then
        P3:= Bitmap.ScanLine[Bitmap.Height - 1]
      else
        P3:= Bitmap.ScanLine[j+2];
      P4:= Img.Bitmap.ScanLine[j+1];
      // Primera columna
      PFila(P4)[1]:=
        Calcular(PFila(P1),PFila(P2),PFila(P3),1,2,Umbral);
      for i:= 0 to Bitmap.Width - 3 do
      begin
        PFila(P4)[2]:=
          Calcular(PFila(P1),PFila(P2),PFila(P3),2,3,Umbral);
        inc(P1,Sizeof(TRGB));
        inc(P2,Sizeof(TRGB));
        inc(P3,Sizeof(TRGB));
        inc(P4,Sizeof(TRGB));
      end;
      // Ultima columna
      PFila(P4)[2]:=
        Calcular(PFila(P1),PFila(P2),PFila(P3),2,2,Umbral);
    end;
  finally
    Bitmap.Free;
  end;
end;
Como veras aparecen los tipos ya conocidos TRGB y TFila, y sus correspondientes PRGB y PFila. El calculo de la matriz pasa a estar dentro de una función, para mayor comodidad, y se han eliminado algunos cálculos innecesarios (hay filas y columnas nulas en el filtro Sobel). El resto es muy similar a los códigos anteriores de filtros, solo que se hacen las correcciones de fila y columna que te comentaba antes.

En cuanto al Umbral, en algunos texto recomiendan pasar la imagen por un umbral después de aplicar el filtro, si no lo quieres usar (Gimp tampoco lo usa) simplemente usa el valor 0.

Bueno, pruebalo y me cuentas que tal te funciona. Ya sabes, la forma de usarlo como siempre:
Código Delphi [-]
  Sobel(Image1.Picture,0);
  Image1.Refresh;

Última edición por seoane fecha: 18-02-2007 a las 21:34:22.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Deteccion de Dispositivos USB marceloalegre Varios 9 22-09-2016 13:12:55
Detección de una unidad removible Pascalizado API de Windows 13 22-05-2011 18:54:51
Detección de navegador WEB aerosB4 Internet 5 08-03-2004 17:27:10
Detección de Carga de un programa craven Varios 3 24-11-2003 16:10:46


La franja horaria es GMT +2. Ahora son las 15:48:56.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi