Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Función de desenfoque

Iniciado por ethernet, 11 de Noviembre de 2002, 12:10:19 PM

« anterior - próximo »

ethernet



    Esta función realiza el desenfoque de una imagen. Lo que hace es sumar todos los colores que hay alrededor de cada pixel y hacer la media, dandole más importancia al color central (8 veces más importancia), según el siguiente esquema:

    pixel1  pixel2  pixel3             1   1   1

    pixel4  pixel5  pixel6      *      1   8   1

    pixel7  pixel8  pixel9             1   1   1

    pixel5 = (pixel1*1 + pixel2*1 + pixel3*1 + pixel4*1 + pixel5*8 + pixel6*1 + pixel7*1 + pixel8*1 + pixel9*1) / 16

    La función necesita de 5 variables para su funcionamiento (yo las tengo como variables miembro de la superficie). Las variables son:

    m_lpBuffer = Es el puntero al inicio de la superficie. En el caso de una superficie DX se puede conseguir con la función Lock

    m_lPitch   = Es el número de bytes de cada línea de la superficie. En el caso de una superficie DX se puede conseguir con la función Lock

    m_bpp      = Son los bits bor pixel de la superficie

    m_bypp     = Son los bytes por pixel de la superficie. Aunque este valor tambien se puede deducir de la variable anterior

    m_Rect     = Está almacenado el rectángulo de la superficie (tamaño)

    Mediante la configuración de estas variables se controla el tamaño y el formato de la imagen, por lo que se puede aplicar la función a una superficie de render, una textura, etc

    Cuantas más veces seguidas se llama a la función, más efecto de desenfoque se produce

    Hay que tener en cuenta que aunque está hecha con funciones MMX, no deja de ser muy lenta, así que solo se puede usar para cosas muy puntuales o simplemente como curiosidad




void Superficie::Desenfoque()

{

int maxlinea,pixelsx,pixelsy,bypp,bpp,incxlinea,maxlinea2,contpixel;

unsigned char *dirw;

dirw=m_lpBuffer;

maxlinea=m_lPitch;

bypp=m_bypp;  

bpp=m_bpp;

pixelsx=m_Rect.Width()-2;

pixelsy=m_Rect.Height()-2;

_asm{

 mov eax,maxlinea

 mov esi,eax

 shl eax,1

 mov maxlinea2,eax

 mov eax,pixelsx

 imul bypp

 mov edx,esi

 sub edx,eax

 mov incxlinea,edx

 sub esi,bypp

 mov edi,dirw

 add edi,maxlinea

 add edi,bypp

 psrld mm7,32

linea:

 mov eax,pixelsx

 mov contpixel,eax

 cmp bpp,32

 jz linea32

 cmp bpp,24

 jz linea24

 cmp bpp,16

 jz linea16

linea15:

 sub esi,maxlinea2

 mov ax,word ptr [edi+esi]

 mov bx,word ptr [edi+esi+2]

 shrd edx,eax,5

 shrd ecx,ebx,5

 shr eax,5

 shr ebx,5

 shr edx,3

 shr ecx,3

 shrd edx,eax,5

 shrd ecx,ebx,5

 shr eax,5

 shr ebx,5

 shr edx,3

 shr ecx,3

 shrd edx,eax,13

 shrd ecx,ebx,13

 movd mm0,edx

 punpcklbw mm0,mm7

 movd mm1,ecx

 punpcklbw mm1,mm7

 paddw mm0,mm1

 mov ax,word ptr [edi+esi+4]

 add esi,maxlinea

 mov bx,word ptr [edi+esi]

 shrd edx,eax,5

 shrd ecx,ebx,5

 shr eax,5

 shr ebx,5

 shr edx,3

 shr ecx,3

 shrd edx,eax,5

 shrd ecx,ebx,5

 shr eax,5

 shr ebx,5

 shr edx,3

 shr ecx,3

 shrd edx,eax,13

 shrd ecx,ebx,13

 movd mm1,edx

 punpcklbw mm1,mm7

 paddw mm0,mm1

 movd mm1,ecx

 punpcklbw mm1,mm7

 paddw mm0,mm1

 mov ax,word ptr [edi+esi+2]

 mov bx,word ptr [edi+esi+4]

 shrd edx,eax,5

 shrd ecx,ebx,5

 shr eax,5

 shr ebx,5

 shr edx,3

 shr ecx,3

 shrd edx,eax,5

 shrd ecx,ebx,5

 shr eax,5

 shr ebx,5

 shr edx,3

 shr ecx,3

 shrd edx,eax,13

 shrd ecx,ebx,13

 movd mm1,edx

 punpcklbw mm1,mm7

 psllw mm1,3

 paddw mm0,mm1

 movd mm1,ecx

 punpcklbw mm1,mm7

 paddw mm0,mm1

 add esi,maxlinea

 mov ax,word ptr [edi+esi]

 mov bx,word ptr [edi+esi+2]

 shrd edx,eax,5

 shrd ecx,ebx,5

 shr eax,5

 shr ebx,5

 shr edx,3

 shr ecx,3

 shrd edx,eax,5

 shrd ecx,ebx,5

 shr eax,5

 shr ebx,5

 shr edx,3

 shr ecx,3

 shrd edx,eax,13

 shrd ecx,ebx,13

 movd mm1,edx

 punpcklbw mm1,mm7

 paddw mm0,mm1

 movd mm1,ecx

 punpcklbw mm1,mm7

 paddw mm0,mm1

 mov ax,word ptr [edi+esi+4]

 shrd edx,eax,5

 shr eax,5

 shr edx,3

 shrd edx,eax,5

 shr eax,5

 shr edx,3

 shrd edx,eax,13

 movd mm1,edx

 punpcklbw mm1,mm7

 paddw mm0,mm1

 psrlw mm0,4

 packuswb mm0,mm0

 movd eax,mm0

 shr eax,3

 shrd edx,eax,5

 shr eax,8

 shrd edx,eax,5

 shr eax,8

 shrd edx,eax,22

 mov word ptr [edi],dx

 add edi,2

 dec contpixel

 jnz linea15

 mov eax,pixelsx

 mov contpixel,eax

 add edi,incxlinea

 dec pixelsy

 jnz linea15

 jmp final

linea16:

 sub esi,maxlinea2

 mov ax,word ptr [edi+esi]

 mov bx,word ptr [edi+esi+2]

 shrd edx,eax,5

 shrd ecx,ebx,5

 shr eax,5

 shr ebx,5

 shr edx,2

 shr ecx,2

 shrd edx,eax,6

 shrd ecx,ebx,6

 shr eax,6

 shr ebx,6

 shr edx,3

 shr ecx,3

 shrd edx,eax,13

 shrd ecx,ebx,13

 movd mm0,edx

 punpcklbw mm0,mm7

 movd mm1,ecx

 punpcklbw mm1,mm7

 paddw mm0,mm1

 mov ax,word ptr [edi+esi+4]

 add esi,maxlinea

 mov bx,word ptr [edi+esi]

 shrd edx,eax,5

 shrd ecx,ebx,5

 shr eax,5

 shr ebx,5

 shr edx,2

 shr ecx,2

 shrd edx,eax,6

 shrd ecx,ebx,6

 shr eax,6

 shr ebx,6

 shr edx,3

 shr ecx,3

 shrd edx,eax,13

 shrd ecx,ebx,13

 movd mm1,edx

 punpcklbw mm1,mm7

 paddw mm0,mm1

 movd mm1,ecx

 punpcklbw mm1,mm7

 paddw mm0,mm1

 mov ax,word ptr [edi+esi+2]

 mov bx,word ptr [edi+esi+4]

 shrd edx,eax,5

 shrd ecx,ebx,5

 shr eax,5

 shr ebx,5

 shr edx,2

 shr ecx,2

 shrd edx,eax,6

 shrd ecx,ebx,6

 shr eax,6

 shr ebx,6

 shr edx,3

 shr ecx,3

 shrd edx,eax,13

 shrd ecx,ebx,13

 movd mm1,edx

 punpcklbw mm1,mm7

 psllw mm1,3

 paddw mm0,mm1

 movd mm1,ecx

 punpcklbw mm1,mm7

 paddw mm0,mm1

 add esi,maxlinea

 mov ax,word ptr [edi+esi]

 mov bx,word ptr [edi+esi+2]

 shrd edx,eax,5

 shrd ecx,ebx,5

 shr eax,5

 shr ebx,5

 shr edx,2

 shr ecx,2

 shrd edx,eax,6

 shrd ecx,ebx,6

 shr eax,6

 shr ebx,6

 shr edx,3

 shr ecx,3

 shrd edx,eax,13

 shrd ecx,ebx,13

 movd mm1,edx

 punpcklbw mm1,mm7

 paddw mm0,mm1

 movd mm1,ecx

 punpcklbw mm1,mm7

 paddw mm0,mm1

 mov ax,word ptr [edi+esi+4]

 shrd edx,eax,5

 shr eax,5

 shr edx,2

 shrd edx,eax,6

 shr eax,6

 shr edx,3

 shrd edx,eax,13

 movd mm1,edx

 punpcklbw mm1,mm7

 paddw mm0,mm1

 psrlw mm0,4

 packuswb mm0,mm0

 movd eax,mm0

 shr eax,3

 shrd edx,eax,5

 shr eax,7

 shrd edx,eax,6

 shr eax,9

 shrd edx,eax,21

 mov word ptr [edi],dx

 add edi,2

 dec contpixel

 jnz linea16

 mov eax,pixelsx

 mov contpixel,eax

 add edi,incxlinea

 dec pixelsy

 jnz linea16

 jmp final

linea24:

 sub esi,maxlinea2

 movd mm0,dword ptr [edi+esi]

 punpcklbw mm0,mm7

 movd mm1,dword ptr [edi+esi+3]

 punpcklbw mm1,mm7

 paddw mm0,mm1

 movd mm1,dword ptr [edi+esi+6]

 punpcklbw mm1,mm7

 paddw mm0,mm1

 add esi,maxlinea

 movd mm1,dword ptr [edi+esi]

 punpcklbw mm1,mm7

 paddw mm0,mm1

 movd mm1,dword ptr [edi+esi+3]

 punpcklbw mm1,mm7

 psllw mm1,3

 paddw mm0,mm1

 movd mm1,dword ptr [edi+esi+6]

 punpcklbw mm1,mm7

 paddw mm0,mm1

 add esi,maxlinea

 movd mm1,dword ptr [edi+esi]

 punpcklbw mm1,mm7

 paddw mm0,mm1

 movd mm1,dword ptr [edi+esi+3]

 punpcklbw mm1,mm7

 paddw mm0,mm1

 movd mm1,dword ptr [edi+esi+6]

 punpcklbw mm1,mm7

 paddw mm0,mm1

 psrlw mm0,4

 packuswb mm0,mm0

 movd eax,mm0

 mov word ptr [edi],ax

 shr eax,16

 mov byte ptr [edi+2],al

 add edi,3

 dec contpixel

 jnz linea24

 mov eax,pixelsx

 mov contpixel,eax

 add edi,incxlinea

 dec pixelsy

 jnz linea24

 jmp final

linea32:

 sub esi,maxlinea2

 movd mm0,dword ptr [edi+esi]

 punpcklbw mm0,mm7

 movd mm1,dword ptr [edi+esi+4]

 punpcklbw mm1,mm7

 paddw mm0,mm1

 movd mm1,dword ptr [edi+esi+8]

 punpcklbw mm1,mm7

 paddw mm0,mm1

 add esi,maxlinea

 movd mm1,dword ptr [edi+esi]

 punpcklbw mm1,mm7

 paddw mm0,mm1

 movd mm1,dword ptr [edi+esi+4]

 punpcklbw mm1,mm7

 psllw mm1,3

 paddw mm0,mm1

 movd mm1,dword ptr [edi+esi+8]

 punpcklbw mm1,mm7

 paddw mm0,mm1

 add esi,maxlinea

 movd mm1,dword ptr [edi+esi]

 punpcklbw mm1,mm7

 paddw mm0,mm1

 movd mm1,dword ptr [edi+esi+4]

 punpcklbw mm1,mm7

 paddw mm0,mm1

 movd mm1,dword ptr [edi+esi+8]

 punpcklbw mm1,mm7

 paddw mm0,mm1

 psrlw mm0,4

 packuswb mm0,mm0

 movd dword ptr [edi],mm0

 add edi,4

 dec contpixel

 jnz linea32

 mov eax,pixelsx

 mov contpixel,eax

 add edi,incxlinea

 dec pixelsy

 jnz linea32

final:

 emms

}

}




    Éste código fue enviado por fiero el 3 de noviembre del 2002
fierodeval@hotmail.com

Si quieres enviar tu propio código hazlo a eth_cotd@lycos.es

    synchrnzr

                                    Ola! Como nadie pone nada, lo pongo yo :D

    Notad que el filtrado es anisotrópico (para los no iniciados, quiere decir que no filtra igual en todas las direcciones ;))

    Sync                                

    fiero

                                    vaya churro!
    He de decir que aunque parezca un lio de instrucciones es bastante facil, solo fijaros en la parte de 32 o 24 bits. Lo que lía la cosa son los bucles de 16 y 15 bits, ya que hay que pasar los colores a 32 bits para descomponer los valores RGB he ir sumandolos en los registros mmx.

    No me habia parado a pensar en eso de "anisotropias"  :ojo: , de todas formas hacerlo de derecha a izquierda o de abajo a arriba no seria muy perceptible a nuestros cansados ojos no sync?

    un saludo                                
    www.videopanoramas.com Videopanoramas 3D player

    fiero

                                    bueno, no puedo editar, así que escribo otro....

    [synchrnzr]
    Se me ocurre que para que fuese un filtro perfecto habria que usar diferentes imagenes de entrada y salida no? para no ir machacando los colores...                                
    www.videopanoramas.com Videopanoramas 3D player

    ethernet

    No he mirado demasiado el codigo (mode flame ON) el codigo ensamblador me produce nauseas. Creo q en c /c++ hubiera estado mejor por 2 cosas. Mas claridad, mas rapidez (estaria por jugarme el cuello) . De q sirve tener un codgo muy bueno si despues nadie lo puede entender o es dificil su lectura?.
    Por otro lado es el tipico caso de filtro. Supongo q habras usado una convolucion para obtener el resultado. Se puede demostrar q es mucho mas eficiente cara al numero de operaciones q  es mucho mejor hacerlo con FFT's. Moraleja: trata de optimizar los algoritmos y no tu codigo.
    (mode flame OFF)
    saludos. si tengo algun tiempo tratare de descifrarlo :))

    synchrnzr

                                    Este filtrado convolutivo no filtra igual las direcciones horizontales o verticales que las diagonales, aunque es lo más utilizado en la demoscene para efectos de soften y desenfoque ;)

    Pos no sé qué formas hay de hacer un filtrado isotrópico, yo sólo sé hacer filtrados isotrópicos a partir de la transformada de Fourier de la imagen que es lo que me enseñaron en la asignatura de proceso de imágenes:

    [abstenerse no iniciados :I]

    La idea es hacer una convolución con una imagen cuyo espectro sea una función gaussiana del mismo tamaño que la imagen. La FFT se aplica en este proceso porque acelera mucho los cálculos (una convolución en el domino espacial es una simple multiplicación en el domino frecuencial) aunque para aplicar la FFT necesitamos que la imagen tenga unas dimensiones concretas (imagen cuadrada, potencia de 2...)

    La metodología sería:

    a) Tenemos una imagen nxm
    B) La convertimos en una imagen qxq (q es un número potencia de 2) y la pasamos a una imagen de complejos para poder aplicar la FFT
    c) Hacemos la FFT de la imagen
    d) Generamos el espectro de una gaussiana (es más fácil y rápido generar el espectro directamente)
    e) Multiplicamos ambos espectros
    f) Antitransformamos la imagen resultante
    g) Devolvemos a la imagen resultante la profundidad de bits que corresponde (después de la convolución, los valores de cada pixel habran aumentado una burrada)

    Cuando hablo de espectro me refiero al módulo de la imagen compleja, supongo que se da por supuesto ;)

    Sync

    PD: Por cierto, aunque parezca muy complicado y rebuscado, se puede hacer a tiempo real con un coste parecido al del otro método gracias a la FFT

    PPD: Más info sobre el tema en www.cvc.uab.es :X9:                                

    Loover

                                    ¿Tiempo real? Mola. ¿Puedes postear un código que use ese método? Quizás para la semana que viene, :D                                
    IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
    Indie Rover The monkeys are reading!

    fiero

                                    [ethernet]
    La verdad es que tengo la manía de hacer los bucles muy repetitivos en ensamblador, aunque sé que en muchos casos no merece la pena...
    Sin embargo en este caso hacerlo en C sería improductivo. No se me ocurre ninguna forma más rápida de sumar dos colores RGB que esta:


         movd mm0,dword ptr [edi+esi]     //Primer color en mm0=00000RGB

         punpcklbw mm0,mm7                  //Desempaquetado de los componentes (de bytes a words)  mm0=000R0G0B

         movd mm1,dword ptr [edi+esi+4] //Segundo color en mm1=00000RGB

         punpcklbw mm1,mm7                 //Desempaquetado de los componentes (de bytes a words) mm1=000R0G0B

         paddw mm0,mm1                       //Suma de los componentes en words



    //Después de la suma:



         psrlw mm0,1                              //Se dividen el resultado entre 2

         packuswb mm0,mm0                  //Se empaquetan los componentes (de words a bytes) mm0= 0RGB0RGB

         movd dword ptr [edi],mm0         //Se almacena el color de 32 bits





    Si se haria el código en C no se sumarian las 3 componentes a la vez en una misma instrucción, ya que los compiladores no suelen meter mmx (de esto no estoy muy seguro)


    [synchrnzr]
    En cuanto a lo de usar FFT, no tengo ni idea de hacer filtros así  :oops: , aunque bueno es saberlo... :ojo:

    saludos                                
    www.videopanoramas.com Videopanoramas 3D player

    synchrnzr

                                    Loover: lo único que tengo es en ViLi, una especie de versión visual del Lisp desarrollado en el propio CVC. Además no es muy didáctico porque lo que es hacer la FFT ya está implementado en el propio lenguaje. En C supongo que sabría hacerlo, pero la verdad es que no me he puesto nunca porque me dedico más a cosillas de sonido :loco:

    En cualquier caso no creo que sea el código de la semana que viene pero a lo mejor algun dia de estos me animo y envio algo sobre sonido, si tengo tiempo :)

    Sync                                

    ethernet

    Quizas eso q comentas de sumar dos colores sea lo mas rapido. Yo no digo q no se use asm, por ejemplo para ese caso es util, pero el resto del codigo en c estoy casi seguro q el compilador lo haria mas optimo. Para muestra, un boton :) -> http://www.codepixel.com/modules.php?op=mo...ewthread&tid=53

    saludos

    fiero

                                    Examinando ese código de codepixel me parecía muy raro que ganara C. Estos con los resultados que he obtenido yo con ese mismo código:

    time_c++: 1.121921
    time_asm: 0.106562

    (compilado con VC6)

    Por cierto, he leido algo sobre el memcpy() en ese mismo hilo. Esa función de microsoft está integramente realizada en asm, hay un fichero por el visual studio llamado memcpy.c en el que está tol cotarro...

    Lo que me resulta extraño son tus tiempos ethernet  :-?

    un saludo

    PD: ethernet, una vez dijiste que con el compilador de intel te salia un botoncito en la barra del VC, ¿como se hace para que salga?                                
    www.videopanoramas.com Videopanoramas 3D player

    ethernet

    Juro por dios q me daba esos tiempos, ademas lo probe un monton de veces cambiando la memoria el tamaño y demas. Por cierto, con intel me daba mas lento q con vc++.

    fiero: no es un boton. En project->settings->c/c++-> preprocesor definitions pones: USE_INTEL_COMPILER (creo q es eso, en la ayuda delcompilador te pone lo q debes poner)

    MChiz

                                    Hola!
    He probado el codigo de codepixel y en Debug me va mas lento el codigo en C ( casi que es normal :b )
    En release obtengo estos resultados:

    time_c++: 0.062924
    time_asm: 0.099366

    Parece mentira!!
    Un saludo!                                

    fiero

                                    ups, error mio, lo estaba probando en modo debug. En modo release:

    time_c++: 0.073878
    time_asm: 0.158920

    :o  realmente increible!!!

    voy a destriparlo a ver lo que hace el compilador con ese bucle for.....

    un saludo                                
    www.videopanoramas.com Videopanoramas 3D player

    Lord Trancos

                                    poned el codigo en C pa q los q no controlamos asm le echemos un vistazo :)                                
    i>SaludoteZ de Lord Trancos!
    http://www.dxlab.tk - http://dxlab.host.sk - programación de DirectX con Delphi.






    Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
    Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
    Muchísimas gracias.