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 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
  #2  
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
  #3  
Antiguo 02-03-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
Algo no anda bien....?

Buenas, despues de una semana ya tengo implementado el algoritmo de sobel y otros más...

NOTA: el código lo he conseguido basandome en lo que amablemente seoane expuso. De hecho a pesar de contener unas variaciones en forma simple no deja de ser el mismo ¡No hay código más simple y sencillo! Le he buscado la vuelta... y la verdad es que el código de seoane es lo más directo y compacto.

NOTA2: mis variaciones están basadas en el hecho de que yo implemento el algoritmo para que funcione bajo tres condiciones:
* Obtener el gradiente horizontal,
* Obtener el gradiente vertical,
* U obtener el gradiente de ambos.

[off-topic]
seoane... encontré otro error, no es grave: en tus comentarios asociaste el del vertical al gradiente horizontal y viceversa. Me dí cuenta cuando estaba haciendo cuentas con papel y lapiz.
[/off-topic]

Y las pruebas que he realizado no me dejan muy contento. No si se deba a que la implentación del cálculo del valor a comparar con el umbral es incorrecta o es el valor del umbral el que no permite mostrar buenos resultados.

El algoritmo funciona... se vé que lo hace. Pero a mi modo de ver... por más que las imagenes tengan una buena distribución de frecuencia (desde el 0 al 255) en general al pasar un valor ya cercano al 40 o 50 como umbral el resultado ya deja ser algo entendible: alguna que otras lineas y/o puntos aislados.

Según mis cálculos la función módulo: sqrt(a^2 + b^2)/5,656 como máximo da un valor de: 1442,497/5,656 = 255 ¡Todo bien! y como mínimo: 0. Perfecto.... el rango es permitido. Lo que llama la atención es que con valores bajos da resultados.... pero al poner números elevados esto se estropea. Por ejemplo: si deseo que detecte contornos en el rango [0,210] debería poner como umbral 210 si se sigue la lógica de que:

if result[k] >= umbral
then result[k] := 0
else result[k] := 255;

He creado imagenes que contiene contorno en varios rangos... pero el algoritmo sólo funciona para números bajos. ¡No entiendo! según mis apuntes y fuentes debería poder funcionar con números elevados, de hecho el libro que tengo pone un ejemplo con un valor de umbral = 80.

Se que hay técnicas para el cálculo de un umbral óptimo. Pero sólo he conseguido bibliografía sobre el calculos en imágenes binarias.

Según mi bibliografía debería escoger un umbral de forma que del 5% al 10% de los pixeles que presentan un gradiente mayor sean declarados contornos.
Ahora ando pensando en técnicas basadas en histogramas... se que con estas podría hallar un valor... pero igualmente esto debería estar funcionando.

O yo estoy mal... o el código que armé está mal.

Si alguien tiene una idea, gracias.
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #4  
Antiguo 02-03-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
buscando... encontré: filtro paso-alto

Bueno... buscando mejor sobre Sobel, he encontrado un sitio en el que se menciona que para obtener buenos resultados previamente hay que pasar un flitrado de paso-alto para que se resalten mejor los bordes...

Voy a ver que sale de esto. Si no logro hacer que marche mejor... veré que hago.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
Responder Con Cita
  #5  
Antiguo 04-03-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
Buenas, sigo con esto del algoritmo de Sobel.. estoy empezando a calibrar ideas...

Y como dije antes... no estoy muy seguro de los resultados.
Verán, este es mi algoritmo. Bueno en realidad se muestra una parte, yo diría la más importante porque el resto puede seguirse de lo que seoane había comentado.

Código Delphi [-]
const
HORIZONTAL_GRADIENT_SOBEL: TTemplate = ((-1,0,1),(-2,0,2),(-1,0,1));
VERTICAL_GRADIENT_SOBEL: TTemplate = ((-1,-2,-1),(0,0,0),(1,2,1));

GRADIENT_DIVIDING_ONLY = 4;

type
TGradientOption = (goHorizontal,goVertical,goBoth);

function GetGradient(F1, F2, F3: PTFila; Gradient: TGradientOption; PosX, PosY,
         Threshold: integer): TRGBCanal;
{******************************************************************************
 Descripción:
 Devuelve el valor de gradiente de sobel asociado a una posición determinada de
 la imagen dependiendo si debe evaluar uno o ambos gradientes.

 Parámetros:
 - F1, F2, F3: Filas correspondientes al filtrado.
 - Gradient: Gradiente a evaluar.
   * Horizontal
   * Vertical
   * Ambos
 - PosX, PosY: Posición actual de los pixel vecinos x e y al evaluado.
 - Threshold: Umbral de decisión.
 ******************************************************************************}
var k: integer;
    GHor, GVer: byte;
begin
  // Para cada canal:
  for k := RED downto BLUE do
    begin
      // Calculamos:
      // ...El Gradiente Horizontal
      GHor := round(
                    (F1[1][k] * HORIZONTAL_GRADIENT_SOBEL[1,1] +
                     F1[PosY][k] * HORIZONTAL_GRADIENT_SOBEL[1,3] +
                     F2[1][k] * HORIZONTAL_GRADIENT_SOBEL[2,1] +
                     F2[PosY][k] * HORIZONTAL_GRADIENT_SOBEL[2,3] +
                     F3[1][k] * HORIZONTAL_GRADIENT_SOBEL[3,1] +
                     F3[PosY][k] * HORIZONTAL_GRADIENT_SOBEL[3,3])
                     /GRADIENT_DIVIDING_ONLY);
      // ...El Gradiante Vertical
      GVer := round(
                    (F1[1][k] * VERTICAL_GRADIENT_SOBEL[1,1] +
                     F1[PosX][k] * VERTICAL_GRADIENT_SOBEL[1,2] +
                     F1[PosY][k] * VERTICAL_GRADIENT_SOBEL[1,3] +
                     F3[1][k] * VERTICAL_GRADIENT_SOBEL[3,1] +
                     F3[PosX][k] * VERTICAL_GRADIENT_SOBEL[3,2] +
                     F3[PosY][k] * VERTICAL_GRADIENT_SOBEL[3,3])
                     /GRADIENT_DIVIDING_ONLY);
      // Determinamos que gradiante usamos
      case Gradient of
        goHorizontal: result[k] := GHor;
        goVertical: result[k] := GVer;
        goBoth: result[k] := GHor + GVer;
      end; // Fin case

      if Threshold > 0
         then begin
                if result[k] >= Threshold
                   then result[k] := 0
                   else result[k] := MAX_RGB;
              end;
    end;
end; {* Fin F. GetGradient *}

Hay una pequeña diferencia con lo descripto en las referencias que tengo. Mis fuentes indican que para obtener la imagen real debe obtenerse el módulo de entre ambos gradientes. Es decir la raiz cuadrada de la suma de los cuadrados de los gradientes.
De lo que pude averiguar en internet, se recomienda implementar la suma directa, tal como pueden observar, ya que simplica las operaciones y se obtiene una buena aproximación.
No me convence todavía algunos resultados... consigo unos bordes gruesos no se si realmente estoy codificando algo mal.
Le agradecería si alguien puede ver este código y/o conoce del tema y me de unas pautas para corregir mi inconveniente.

Como prueba... vean esto:




Este resultado se obtiene siguiendo dos pasos:
1. Se convierte a nivel de gris
2. Se le aplica un suavizado
3. Se calcula el contorno mediante Sobel con un valor de 80.

¿Se entiende lo que trato de explicar? Eso espero.
Gracias, pero mucha gracias a toda persona que se haya tomado el tiempo y las molestias.

Saludos,
__________________
Delphius
[Guia de estilo][Buscar]
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 19:40:29.


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