Club Delphi  
    Paypal   FTP   CCD     Buscar   Trucos   Trabajo   Foros

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

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
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: 26
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
  #2  
Antiguo 19-02-2007
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 27
Delphius Va camino a la fama
Gracias maestro!

Pues gracias seoane, por ofrecer tu honorable y bien oportuna, sin olvidar tu profresional ayuda.

Cita:
Empezado por seoane
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
¿No te queda remedio? ¿O es que no quieres admitir que te gusta poner código y seguir ayudando en lo que puedas... sin olvidar que se trata de un área que dominas?

Como ya dije... ¡muchas gracias!
Yo todavía no había escrito nada de código (al menos dijitalmente). Seguía con mis pruebas a mano, papel y lapiz.

El código como es de esperar sigue siendo similar a los otros. Y te agradezco de que me hayas hecho ver un cálculo tonto:

Cita:
Empezado por seoane
(hay filas y columnas nulas en el filtro Sobel)
Se me había olvidado que Algo por cero es cero

Pero algo del código me llama la atención:
Código Delphi [-]
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
      );
Ese famoso sqrt()/5.66 ¿que es? ¿Es el "umbral previo" del que
comentas en?:

Cita:
Empezado por seoane
En cuanto al Umbral, en algunos texto recomiendan pasar
la imagen por un umbral después de aplicar el filtro
Yo simplemente le metería:

Código Delphi [-]
result[k] := trunc(Modulo_Gradiente);
Siendo Modulo_Gradiente la raiz cuadrada de la suma de los cuadrados de los
resultados de las plantillas. Tal como operas.
No termina de cuadrarme la idea del 5.66

Muchas gracias seoane....
Saludos,

EDITO Y AGREGO:
he visto en el e-mail (una vez que he terminado de responder este mensaje) de tu respuesta... y me di con que inicialmente tu mensaje fue:

Cita:
Empezado por seoane
En cuanto a los parámetros Umbral y divisor, tienen el siguiente significado. El
divisor es el numero por el que se divide después de multiplicar la matriz, a mi
entender este debería ser 120 (10x12), pero en el filtro de Gimp utilizan un
valor de 56 (56.6 para ser exactos), sus razones tendrán que a mi se me escapan,
pero el efecto es que la imagen resultante es mas luminosa.
Pues... eso ya me ha confundido más... ahora veo porque editaste el mensaje.

Voy a probar el código... dejo mi lapiz y papel. Tengo que hacerles varias pruebas. Y ver de donde sale ese numero mágico...
Pero claro, que tonto soy . En cualquier filtrado hay que dividir el resultado con la "suma" de los elementos de la matriz (si los elementos están expresados en forma entera) (se evitaría la división si fueran reales: Num/divisor). Pero a mi la "suma" me da cero . Tu dices que es 120.
Esto me marea... pero de algún modo voy a sacar esto...

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]

Última edición por Delphius fecha: 19-02-2007 a las 07:59:40.
Responder Con Cita
  #3  
Antiguo 19-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: 26
seoane Va por buen camino
Antes de nada Delphius no hagas caso a lo que te llego por email, debí modificar como 20 veces el código. Cada vez que lo editaba, volvía a encontrar otro detalle para corregir . La versión que puedes ver ahora es la definitiva, y arroja un resultado similar al filtro Sobel de Gimp (con un Umbral=0).

Cita:
Empezado por Delphius
Ese famoso sqrt()/5.66 ¿que es? ¿Es el "umbral previo" del que comentas en?:
Jeje, el famoso 5.66. Pues si te digo la verdad no estoy muy seguro de donde sale, aunque tengo mi teoría, pero la verdad es que copie ese valor del código de Gimp

Mi teoría es la siguiente, en el peor de los casos al aplicar el filtro podemos llegar a obtener un valor de 4 * 255, este valor es demasiado alto para guardarlo en un byte. Así que dividimos todos los valores por cuatro, de hecho este el valor que debemos de usar si solo aplicamos unos de los filtros (horizontal o vertical)

Ahora bien si aplicamos ambos filtros a la vez debemos combinar ambos valores de la siguiente manera sqrt(sqr(a)+sqr(b)), siendo a y b los valores resultantes de aplicar cada filtro. En el peor de los casos tendríamos a = 4*255 y b=4*255, como ya explique en el párrafo anterior, así que si aplicamos la formula anterior la suma de los dos peores casos es sqrt(32*sqr(255)), y sorpresa la raiz cuadrada de 32 es 5,656 . Por lo que según entiendo esta división se realiza para asegurarse de que ningún valor sobrepase el limite de 255.

En cuento al Umbral, simplemente se aplica cuando se quiere tener un borde muy definido. Me explico, si solo se aplica el filtro, los bordes pueden tener mas o menos luminosidad. Si lo que nos interesa es que todos los bordes tengan la máxima luminosidad es cuando aplicamos el umbral.

Esto de los filtros es un mundo, y yo ya tengo bastante olvidadas las clases de matemáticas, así que espero no estar diciendo ninguna burrada

Última edición por seoane fecha: 19-02-2007 a las 17:54:46.
Responder Con Cita
  #4  
Antiguo 19-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: 26
seoane Va por buen camino
Y ya que estamos podemos obtener bonitos resultados con este metodo. Podemos realzar los bordes de una imagen, como si estuviera perfilada con un rotulador negro, como en un comic.

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
      );
    //  --- Esta es la parte importante --- 
    // Pintamos los bordes de negro y dejamos sin tocar el resto de la imagen
    if Umbral > 0 then
      if Result[k] > Umbral then
      begin
        FillChar(Result,Sizeof(Result),0);
        break;
      end else
        Result[k]:= F2[i][k];
  end;
end;

procedure Comic(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;

// Por ejemplo
  Comic(Image1.Picture,16);
  Image1.Refresh;
Dependiendo de la imagen original y el valor de umbral que escojamos, podemos conseguir un efecto bastante bueno.

PD: Delphius este ultimo mensaje, es solo lúdico. Espero que no te importe
Responder Con Cita
  #5  
Antiguo 19-02-2007
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 27
Delphius Va camino a la fama
Seoane... tu teoria suena mejor que la mia.
Medité que el filtro espacial tiene todos los elementos distintos de cero... hay nueve casillas... y en la forma que estaba expresado el filtro tanto la suma como el conteo me daban igual... pero al estar expresados en forma real se ve que el denominador corresponde a la cantidad de casillas distintas de cero y/o que corresponde a los vecinos a filtrar (1). Como la plantilla de sobel tiene 6 elementos... y considerando el factor de error que se tiene al operar con sqrt()... me dije: ¡por eso el 5.66!

Si no se me entendió... disculpen... uno alucina a las 4 AM (a esa hora se me ocurrió la teoria) ... sobre todo si tiene el estómago vacio y el no haber dormido.

(1) Esto lo comprobé (o será una simple coincidencia) mediante la observación y comparación con otras plantillas de filtros.

Cita:
Empezado por seoane
En cuento al Umbral, simplemente se aplica cuando se quiere tener un borde muy definido. Me explico, si solo se aplica el filtro, los bordes pueden tener mas o menos luminosidad. Si lo que nos interesa es que todos los bordes tengan la máxima luminosidad es cuando aplicamos el umbral.
Si he visto ese efecto. Además, el umbral se emplea (en estos propósitos) para determinar (a prueba de ensayo y error) cuales de los pixeles serán considerados para el análisis y declarados contornos.

Ahorita que me acuerdo, tengo que seguir con estos tipos de análisis: de puntos, detección de tranciones de claro-oscuro en 8 direcciones... Cada vez me está gustando más esto.

Y lástima... que haya dejado de lado (tal vez algun momento intente de nuevo) a la amplicación mediante interpolación lineal.

Cita:
Empezado por seoane
Y ya que estamos podemos obtener bonitos resultados con este metodo. Podemos realzar los bordes de una imagen, como si estuviera perfilada con un rotulador negro, como en un comic.
Lo tomo como un elemento más de aprendizaje, y aplicaciones.

Cita:
Empezado por seoane
PD: Delphius este ultimo mensaje, es solo lúdico. Espero que no te importe
No hay problema... y ¡gracias! Tal vez sea algo de juego... pero para mi sigue siendo otra manera de aprender y entender las aplicaciones y usos de estos métodos de tratamiento de imagen. Cuando termine mi tesis (si es que la termino) me voy a hacer mi propio PhotoShop.

Y esto de los tratamiento de imagen.. recien comienza para mi. Ya me ando acercando al análisis y posicionamiento de formas (mediante plantillas), por esto me resulta de importancia implementar sobel. De los contornos que detecte dependerán los resultados de mi sistema.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #6  
Antiguo 20-02-2007
Avatar de Delphius
[Delphius] Delphius is offline
Miembro Premium
 
Registrado: jul 2004
Ubicación: Salta, Argentina
Posts: 5.582
Poder: 27
Delphius Va camino a la fama
La verdad es que perdi la cuenta de las veces que te he agradecido seoane... pero alli va... gracias!

Probé el código que me enviaste y ahora lo voy a adaptar a mi caso.
Solamente debo decir que a mi parecer, el efecto debe ser inverso. Tu código implementa el umbral de la siguiente manera:

Código Delphi [-]
if Result[k] > Umbral then
        Result[k]:= 255
      else
        Result[k]:= 0;
Yo, en cambio lo prefiero asi:

Código Delphi [-]
if Result[k] > Umbral then
        Result[k]:= 0
      else
        Result[k]:= 255;
Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #7  
Antiguo 20-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: 26
seoane Va por buen camino
Cita:
Empezado por Delphius
Solamente debo decir que a mi parecer, el efecto debe ser inverso. Tu código implementa el umbral de la siguiente manera
Eso ya es mas una cuestión estética, con el umbral tal como lo implemento, el fondo es negro y los bordes son colores claros. Supongo que lo contrario, bordes oscuros sobre fondo blanco puede resultar mas atractivo. De hecho, en el código para simular el cómic, si coloreo los bordes de negro.
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

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 11:22:51.


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