Author Topic: "Mediana" de una imagen  (Read 8288 times)

Offline David Serrano

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 503
"Mediana" de una imagen
« on: 2007 September 17 06:54:20 »
¿Qué **** es eso de la "mediana" de una imagen? ;)

Es que llevo así como 5 horas dándole vueltas al script este, para finalmente hallar que el script funciona como es debido, y que yo simplemente creía que funcionaba mal porque la mediana no me coincidía... :evil:

En el script tengo dos funciones tales que:

Code: [Select]
   this.get_luma = function (view) {
        view.image.extractLuminance (luma = new Image);
        return luma;
    }

    // obtains luma, then its median. Obtaining directly the median of the
    // view resulted in the median of the red channel only.
    this.get_median = function (view) {
        var l = this.get_luma (view);
        stats.generate (l);
        return stats.median;
    }


Tal y como puede verse, cuando hago "get_median (view)", primero saco la luminancia y después devuelvo la mediana de la luminancia. Al principio no extraía la luminancia y vi que al hacer "stats.median" sobre la imagen original, obtenía un valor X que era el mismo que el proceso Statistics mostraba en el lugar de la mediana del canal rojo. ¿Sería una coincidencia? Da igual, inmediatamente decidí poner esto de la luminancia para quitarme los canales de enmedio :).

¿Es esto correcto?

Por otro lado tenemos la forma en que yo comprobaba que el script funcionaba bien o mal: dos instancias de PixelMath.

Code: [Select]
Lum($target)
Code: [Select]
Med($target)

En teoría lo mismo, verdad? Pues no... Al aplicar la primera instancia sobre una imagen, obviamente se me pone en blanco y negro. Al aplicar la segunda, obtengo una imagen totalmente gris, y espero que el valor de cada píxel en esa imagen sea la mediana de la imagen anterior, es decir de la luminancia, tal como hago desde javascript. Sin embargo los valores obtenidos distan con frecuencia más de un 10%.

Es decir, resumiendo, que estos dos valores:

 - El resultado de llamar a get_median (view).
 - El valor de cada píxel tras aplicar esos dos PixelMath's.

no son iguales.

En ningún momento he tocado para nada ningún RGBWS, que podría ser un posible factor que alterara la luminancia de una imagen y, por ende, su mediana (aunque al fin y al cabo también debería ser indiferente puesto que en ambos procesos estaría vigente el mismo WS).

Hala, ahí va eso :^P.
--
 David Serrano

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
"Mediana" de una imagen
« Reply #1 on: 2007 September 17 08:44:25 »
La mediana de una imagen (en realidad, de un canal de una imagen) es la mediana de los valores de todos sus píxeles. La mediana en este caso es el valor para el cual es igualmente probable encontrar un píxel más oscuro que uno más brillante en la imagen.

Gráficamente, siempre que la distribución de valores de píxel sea claramente unimodal (= fuertemente dominada por un único pico), la mediana coincide con la posición del pico principal del histograma en el eje X.

En imágenes de cielo profundo en las que se representan grandes zonas del cielo libres de objetos, el pico principal del histograma corresponde a los valores del fondo del cielo, ya que éstos son los valores más probables en una imagen de este tipo. Por lo tanto, la posición del pico define con bastante exactitud el valor medio del cielo en estas imágenes. En imágenes en las que hay muy pocas zonas de cielo libre, caracterizar el cielo mediante el histograma general de ia imagen puede llegar a ser mucho más difícil, si no imposible. En estos casos, es necesario o bien considerar las estadísticas de zonas seleccionadas, o bien utilizar un sistema de rechazo de píxeles basado en estadísticas locales (= de pequeñas zonas alrededor de objetos o puntos de interés).
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
"Mediana" de una imagen
« Reply #2 on: 2007 September 17 09:14:37 »
Vale, ahora te contesto estrictamente a la duda de programación.

En PCL, y por extensión en PJSR, se utiliza un sistema de selecciones para acceder a diferentes canales o grupos de canales de una imagen, así como para definir y actuar sobre una ROI (Region of Interest) rectangular.

Por ejemplo, si quieres invertir sólo los píxeles del segundo canal de una imagen, dentro de un rectángulo de ancho=256 y alto=45, cuyo vértice superior izquierdo está en coordenadas de imagen {100,200}:

Code: [Select]
var img = new Image;
// ...
img.selectedChannel = 1; // 1 es el segundo canal
img.selectedRect = new Rect( 100, 200, 100+256, 200+45 );
img.invert();


O bien, supongamos que queremos hacer lo mismo para los canales segundo y tercero:

Code: [Select]
img.firstSelectedChannel = 1; // 1 es el segundo canal
img.lastSelectedChannel = 2; // 2 es el tercer canal
img.selectedRect = new Rect( 100, 200, 100+256, 200+45 );
img.invert();


Ahora supón que tienes dos imágenes, img1 e img2, y quieres restar el segundo canal de img2 del primer canal de img1, pero desplazando img2 100 píxeles a la derecha y 50 píxeles hacia abajo con respecto a img1:

Code: [Select]
var img1 = new Image;
var img2 = new Image;
// ...
img1.selectedChannel = 0;
img1.selectedPoint = new Point( 100, 50 );
img2.selectedChannel = 1;
img1.apply( img2, ImageOp_Sub );


Si usas selecciones de este tipo, asegúrate de resetearlas cuando no sean necesarias:

Code: [Select]
img1.resetSelections(); img2.resetSelections();

o si no tendrás "sorpresas".

Todo este rollo es para explicarte por qué estabas obteniendo las estadísticas del canal rojo de una imagen en color: porque el primer canal es la selección de canales por defecto. Ahora ya sabes cómo obtener estadísticas (y muchas otras cosas) sólo para determinados canales, o incluso regiones rectangulares de una imagen.
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
"Mediana" de una imagen
« Reply #3 on: 2007 September 17 09:22:33 »
Más respuestas :)

Code: [Select]
Lum($target)
Med($target)


No, claro que no son iguales. Lum($target) te devuelve la luminancia del píxel actual en PixelMath, calculada en el RGBWS de la imagen $target, mientras que Med($target) es una expresión constante que te devuelve la mediana de la imagen $target en el canal actual.

Si le aplicas a una imagen Med($target), lo que vas a obtener es que cada píxel va a ser sustituído por la mediana, o sea que cada canal de la imagen lo vas a convertir en una imagen gris con valor constante igual a la mediana.

Si le aplicas Lum($target), obviamente vas a hacer sustituir cada píxel con el valor de su luminancia para todos los canales de la imagen.
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline David Serrano

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 503
"Mediana" de una imagen
« Reply #4 on: 2007 September 17 09:29:38 »
Bueno, no nos hemos entendido, me parece.

Conozco lo que es la mediana de un conjunto de datos. Ahora bien, cuando ese conjunto es una imagen con tres canales, me despisto un poco. Cuando dices "la mediana de los valores de todos sus píxels", supongo que tenemos que considerar cada canal por separado, con lo cual entonces tenemos realmente 3 medianas, no? ¿O por el contrario se halla metiendo todos los valores de cada píxel en cada canal, dentro del mismo saco? Hmmm...

[...]

Aquí tenía puestos un par de párrafos con muchos números que no me cuadraban nada.... hasta que caí en la cuenta de que PixelMath hace un rescale de los datos :idea:.

Desactivando el rescale, las cuentas ya me dan, y consigo obtener con PixelMath el mismo valor de la luminancia que con javascript.

¡Qué alivio!

Voy a reproducir algunos de estos números porque me da pena borrarlos :^P:

Quote
- Med($target[0]) --> imagen gris, los píxels valen 0.1604.
 - Med($target[1]) --> imagen gris, los píxels valen 0.1006.
 - Med($target[2]) --> imagen gris, los píxels valen 0.0749.
 - Med($target) --> imagen naranja chillón, los píxels valen 1.0000, 0.3009, 0.0000.


Imaginaos el cacao mental que tenía encima!! Desactivando el rescale, el naranja es mucho más débil, y los valores de pixel en cada canal coinciden con los de $target[0], [1] y [2].
--
 David Serrano

Offline David Serrano

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 503
"Mediana" de una imagen
« Reply #5 on: 2007 September 17 09:36:16 »
Quote from: "Juan Conejero"
Si le aplicas a una imagen Med($target), lo que vas a obtener es que cada píxel va a ser sustituído por la mediana, o sea que cada canal de la imagen lo vas a convertir en una imagen gris con valor constante igual a la mediana.


Exacto, y si antes de hacer eso hacemos Lum($target), obtengo una imagen gris, que es precisamente lo que quería. Buscaba una forma alternativa de obtener la mediana de una imagen, sin ser con el .extractLuminance de javascript. Haciendo estas dos operaciones, una después de la otra, obtenía el valor de la mediana en cada píxel. Un poco tosco, pero efectivo ;^).

Y sin hacer el rescale, tal como acabo de poner en el otro mensaje, ya consigo con PixelMath el mismo valor de 0.1110 que me sale con javascript.
--
 David Serrano

Offline Juan Conejero

  • PTeam Member
  • PixInsight Jedi Grand Master
  • ********
  • Posts: 7111
    • http://pixinsight.com/
"Mediana" de una imagen
« Reply #6 on: 2007 September 17 10:04:47 »
Pues entonces disculpa por el rollazo que te he soltado antes :-|

Bueno, efectivamente sí podrías usar PixelMath de esa forma truquera para obtener la mediana. Simplemente podrías definir una instancia de PixelMath que generara una nueva imagen de 1x1, con id de imagen preestablecido, y cuya expresión fuera Med($target). Luego lees el valor del único píxel de esa imagen y la cierras.

Pero la verdad no sé para qué quieres montar semejante tinglado, si ImageStatistics hace todo eso y mucho más, y además corre código nativo que va a toda leche. Or am I missing something here?
Juan Conejero
PixInsight Development Team
http://pixinsight.com/

Offline David Serrano

  • PTeam Member
  • PixInsight Guru
  • ****
  • Posts: 503
"Mediana" de una imagen
« Reply #7 on: 2007 September 17 10:39:48 »
Quote from: "Juan Conejero"
Pues entonces disculpa por el rollazo que te he soltado antes :-|


Ha venido bien. Cuando se empieza en algo, todo viene bien :).


Quote from: "Juan Conejero"
Pero la verdad no sé para qué quieres montar semejante tinglado, si ImageStatistics hace todo eso y mucho más


Ya lo estaba haciendo así en el script, y así se va a quedar (el objeto "stats" del trozo de código que puse, es un ImageStatistics precisamente). Simplemente quería comprobar que el script funcionaba como yo quería, una segunda opinión médica.

Como el proceso Statistics no me daba la "mediana de la imagen", que es lo que quería saber antes (cuando no conocía esto del image.selectedChannel) (y de ahí el título de este hilo), se me ocurrió hacerlo con PixelMath. Ejecutar esas dos instancias manualmente, una tras otra, sobre la imagen final y ver qué salía. Y al no coincidir los valores, me rallé mucho...

Ya está, ya está :).
--
 David Serrano