Sobre el Balance de blancos con parches

Estás viendo el contenido archivado del viejo foro de Ojodigital. No podrás iniciar sesión ni crear nuevo contenido o comentarios.

El foro de ojodigital ha migrado a: https://foro.ojodigital.com, con un aspecto mucho más moderno, amigable y adaptado a dispositivos móviles.

¡¡PINCHA AQUÍ PARA ACCEDER AL NUEVO FORO!!

Resultados 1 al 10 de 10
  1. #1
    Ingreso
    07 mar, 06
    Ubicación
    Madrid (a ratos Alicante)
    Mensajes
    9,426
    Post Thanks / Like

    Sobre el Balance de blancos con parches

    Cita Iniciado por ManuelLlorens Ver mensaje
    No me refiero a dónde se aplique la corrección de WB, sino a sobre qué buffer se hará el cálculo de los multiplicadores seleccionando una zona en la vista de perfectRAW. ¿Quieres decir que tendremos que calcular el balance de blancos sobre un buffer de dcraw antes de la interpolación?

    (...)

    A mí sí, salvo por la duda que pongo arriba, ¿el cálculo de WB de perfectRAW debe hacerse sobre un buffer pre-interpolado? Si es así habrá que guardar siempre ese buffer y no vamos a poder optimizar mucho más el uso de memoria de la DLL, quizás pueda quitar algún otro buffer pero lo veo cada vez más difícil (no de programar que ya lo tengo pensado sino que al final necesitamos casi todos los buffers para una cosa u otra). Le daré otra vuelta.
    Ah perdón, o sea hablablas del cálculo del balance de blancos mediante parches no? en ese caso para nada ha de ser post-interpolación, hay que interceptar la imagen (ni siquiera se necesita un buffer adicional, es solo ver en el código de Coffin donde la tenemos en este estado) cuando se ha reescalado por su punto negro y saturación (es decir, ya es un float lineal), pero aún no se ha interpolado.

    Es donde DCRAW aún tiene bucles sobre 4 valores (los FORC4 de Coffin), ahora no recuerdo el nombre del array que contiene los canales: R, G1, G2, B. Además es imprescindible hacerlo así (antes de interpolar) si se quiere un ajuste preciso del balance G1/G2 para evitar los laberintos en las Oly por ejemplo.

    De los volcados de memoria que me pasó en su día otro forero, antes de interpolar estos canales tienen a cero 3 de cada 4 píxels (lógico). No es problema, el rectángulo o elipse seleccionado por el usuario abarcará un número de píxels grande, y para cada uno tomaremos un valor de R, G1, G2 y B en el cálculo.

    En realidad creo que basta hacer un bucle con lo que vendría a ser un step 2. Pseudocódigo:

    Código:
    // Umbrales de aceptación del cálculo del WB (rango 16 bits)
    Umin=5000.0
    Umax=60000.0
    
    // suma de los niveles de cada canal en todo el parche
    for c=0 to 3
      sum(c)=0.0
    next c
    
    // bucle que recorre el parche (xmin,ymin)->(xmax,ymax)
    // (solo uno de cada 4 pixels para independizarnos de la topología Bayer)
    for x=xmin to xmax step 2
      for y=ymin to ymax step 2
        for c=0 to 3
          nivel(c)=0
        next c
        for c=0 to 3  // canales R, G1, B, G2
          nivel(c)=imagen(c,x,y)+imagen(c,x+1,y)+imagen(c,x,y+1)+imagen(c,x+1,y+1)
          // de esos 4 sumandos solo uno será distinto de 0
        next c
        if Umin<=nivel(0)<=Umax and Umin<=nivel(1)<=Umax and
           Umin<=nivel(2)<=Umax and Umin<=nivel(3)<=Umax then
          for c=0 to 3
            sum(c)=sum(c)+nivel(c)
          next c
        endif
      next y
    next x
    
    // Ahora calculamos los multiplicadores del WB:
    maximo=max(sum(0),sum(1),sum(2),sum(3))
    for c=0 to 3
      m(c)=maximo/sum(c)
    next c
    Los multiplicadores calculados serán los aplicados luego en el revelado de toda la imagen como si los hubiéramos introducido por cualquier otra vía (-w -r -a)
    Por cierto, lograr soltura en interceptar la imagen en este estado (resta de negro y reescalado al punto de saturación en float), será clave en PerfectBLEND; de hecho no se necesitará mucho más que esto (la propagación del balance de blancos como te dije y alguna chorradilla más, pero leer los datos RAW reescalados es lo más importante).
    "En ocasiones veo halos."

    http://www.guillermoluijk.com para suscribirte haz clic aquí
    Último contenido: EL MITO DEL TRÍPODE QUE ASESINÓ A UN ESTABILIZADOR

  2. #2
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por _GUI_ Ver mensaje
    Ah perdón, o sea hablablas del cálculo del balance de blancos mediante parches no? en ese caso para nada ha de ser post-interpolación, hay que interceptar la imagen (ni siquiera se necesita un buffer adicional, es solo ver en el código de Coffin donde la tenemos en este estado) cuando se ha reescalado por su punto negro y saturación (es decir, ya es un float lineal), pero aún no se ha interpolado.
    Sí, eso había pensado.

    Cita Iniciado por _GUI_ Ver mensaje
    Por cierto, lograr soltura en interceptar la imagen en este estado (resta de negro y reescalado al punto de saturación en float), será clave en PerfectBLEND; de hecho no se necesitará mucho más que esto (la propagación del balance de blancos como te dije y alguna chorradilla más, pero leer los datos RAW reescalados es lo más importante).
    Sólo hay que separar scale_colors() de Coffin en dos funciones una antes y otra después del WB, muy fácil, aunque algo más chungo de mantener. Otra opción es llamarla con y sin WB... lo tengo que estudiar, ya sabes que quiero modificar/duplicar el menor código de Coffin posible.

    Un saludo:
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  3. #3
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    El flujo de revelado creo que lo has dejado bastante claro...

    No estaría mal que Manuel pusiera ahora (sobre el flujo de revelado que tú has puesto) dónde están los buffers intermedios que se almacenan y si son de 32 o de 16.

    Creo que lo que dice Manuel es importante: el proceso de interpolación creo que es de los más lentos. Si se pone antes el balance de blancos que la interpolación, la cosa va a ir bastante más lenta, pues cada vez que se toque el balance de blancos (que puede ser algo más o menos habitual) hay que reinterpolar y rehacer todos los buffers.

    Si es crítico que el balance de blancos se haga antes para obtener mejor calidad y precisión en los resultados, pues habrá que asumir que la cosa vaya más lenta.

    En cualquier caso el ajuste del balance debería de ser lo primero que haga el usuario y procurar no volver a tocarlo.

    ¿Sería factible que en la etapa de visualización el balance se aplicara después de la interpolación y en el revelado final antes? Quizás fuera una solución de compromiso, aunque claro entonces el efecto que vemos no es exactamente lo que se obtendrá en el resultado final. Pero a lo mejor con los ajustes de gamma para monitor y demás que se hacen después es posible que la diferencia entre una y otra cosa no se llegue a apreciar en un monitor ¿o sí que se aprecia? En el revelado final habrá que hacerlo como sea lo ideal que para eso es un PerfectRaw

    Poner un buffer tras la aplicación del balance de blancos no mejoraría nada creo yo Manuel, pues el cálculo del balance de blancos creo yo que se muchísimo más rápido que el interpolado ¿no? (al fin y al cabo es sumar un valor a cada canal) y por tanto no se notará diferencia entre hacer la interpolación a partir de la salida del balance de blancos o hacerla desde el principio, incluyendo el balance.

    El cuello de botella estará en que cada vez que se toque el balance se tendrá que hacer la interpolación y todo lo demás, mientras que poniéndolo después de la interpolación, se evita tener que hacer esa interpolación (que por lo que dijo manuel en su momento era una de las tareas más lentas).

  4. #4
    Ingreso
    07 mar, 06
    Ubicación
    Madrid (a ratos Alicante)
    Mensajes
    9,426
    Post Thanks / Like
    Cita Iniciado por ManuelLlorens Ver mensaje
    Sólo hay que separar scale_colors() de Coffin en dos funciones una antes y otra después del WB, muy fácil, aunque algo más chungo de mantener. Otra opción es llamarla con y sin WB... lo tengo que estudiar, ya sabes que quiero modificar/duplicar el menor código de Coffin posible.
    Yo te propuse reutilizarla (el balance de blancos por parche es algo puntual y rapidísimo de hacer, no forma parte del flujo normal de la imagen), es decir, dejar scale_colors() tal cual está, pero hacer una paralela que no aplique el balance de blancos y solo sirva para el cálculo de los multiplicadores.

    De hecho, si me confirmas que el flujo de todo DCRAW es en enteros de 16 bits, solo haría falta restar el negro y conocer la saturación, pero no reescalar por dicha saturación (que no aporta nadá más que errores de redondeo).

    Lo que llamaba Umax se calcularía como un % sobre la (saturación-black), p.ej. el 90% de dicha rango (en scale_colors() la sat. se llama maximum), y el Umin lo mismo pero por abajo, p.ej. el 10% de (saturación-black).
    Última edición por Guillermo Luijk; 21/05/2008 a las 12:38
    "En ocasiones veo halos."

    http://www.guillermoluijk.com para suscribirte haz clic aquí
    Último contenido: EL MITO DEL TRÍPODE QUE ASESINÓ A UN ESTABILIZADOR

  5. #5
    Ingreso
    07 mar, 06
    Ubicación
    Madrid (a ratos Alicante)
    Mensajes
    9,426
    Post Thanks / Like
    Cita Iniciado por ariznaf Ver mensaje
    Creo que lo que dice Manuel es importante: el proceso de interpolación creo que es de los más lentos. Si se pone antes el balance de blancos que la interpolación, la cosa va a ir bastante más lenta, pues cada vez que se toque el balance de blancos (que puede ser algo más o menos habitual) hay que reinterpolar y rehacer todos los buffers.

    Si es crítico que el balance de blancos se haga antes para obtener mejor calidad y precisión en los resultados, pues habrá que asumir que la cosa vaya más lenta.
    Sí es crítico, porque de no hacerlo antes de interpolar se crean artefactos horribles (comprobado: antes de interp. vs después de interp.) además de que rompe toda la casuística de multiplicadores >1, o <1 y la recuperacion de altas luces.

    Creo que hay que asumir que el balance de blancos es uno de los controles que más buffers actualizarán y por tanto más retardo introducirá tocarlo.

    Respecto a la interpolación, creo que debería mostrarse la elegida, sea la que sea. Si para operar rápido al principio elegimos bilineal, pues bien, pero que nunca se impida al usuario VER en pantalla exactamente como quedará su TIFF.
    "En ocasiones veo halos."

    http://www.guillermoluijk.com para suscribirte haz clic aquí
    Último contenido: EL MITO DEL TRÍPODE QUE ASESINÓ A UN ESTABILIZADOR

  6. #6
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por _GUI_ Ver mensaje
    Yo te propuse reutilizarla (el balance de blancos por parche es algo puntual y rapidísimo de hacer, no forma parte del flujo normal de la imagen), es decir, dejar scale_colors() tal cual está, pero hacer una paralela que no aplique el balance de blancos y solo sirva para el cálculo de los multiplicadores.
    O llamamos a scale_colors() dos veces, una con los multiplicadores a 1 (para que no haga WB), calculamos multiplicadores a partir del parche y volvemos a llamarla para que haga WB, pero no esta vez no haga otra cosa; o duplicamos una parte de su código en una función aparte, entiendo que es eso a lo que tú llama pasarela.

    Cita Iniciado por _GUI_ Ver mensaje
    De hecho, si me confirmas que el flujo de todo DCRAW es en enteros de 16 bits, solo haría falta restar el negro y conocer la saturación, pero no reescalar por dicha saturación (que no aporta nadá más que errores de redondeo).
    Claro que es de 16 bits, nunca reserva memoria para floats, pero convierte a 32 cuando es necesario. Lo de "scale" me suena a que sí que hace un reescalado:

    Código:
    void CLASS scale_colors()
    {
      unsigned bottom, right, size, row, col, ur, uc, i, x, y, c, sum[8];
      int val, dark, sat;
      double dsum[8], dmin, dmax;
      float scale_mul[4], fr, fc;
      ushort *img=0, *pix;
    
      if (user_mul[0])
        memcpy (pre_mul, user_mul, sizeof pre_mul);
      if (use_auto_wb || (use_camera_wb && cam_mul[0] == -1)) {
        memset (dsum, 0, sizeof dsum);
        bottom = MIN (greybox[1]+greybox[3], height);
        right  = MIN (greybox[0]+greybox[2], width);
        for (row=greybox[1]; row < bottom; row += 8)
          for (col=greybox[0]; col < right; col += 8) {
        memset (sum, 0, sizeof sum);
        for (y=row; y < row+8 && y < bottom; y++)
          for (x=col; x < col+8 && x < right; x++)
            FORC4 {
              if (filters) {
            c = FC(y,x);
            val = BAYER(y,x);
              } else
            val = image[y*width+x][c];
              if (val > maximum-25) goto skip_block;
              if ((val -= black) < 0) val = 0;
              sum[c] += val;
              sum[c+4]++;
              if (filters) break;
            }
        FORC(8) dsum[c] += sum[c];
    skip_block: ;
          }
        FORC4 if (dsum[c]) pre_mul[c] = dsum[c+4] / dsum[c];
      }
      if (use_camera_wb && cam_mul[0] != -1) {
        memset (sum, 0, sizeof sum);
        for (row=0; row < 8; row++)
          for (col=0; col < 8; col++) {
        c = FC(row,col);
        if ((val = white[row][col] - black) > 0)
          sum[c] += val;
        sum[c+4]++;
          }
        if (sum[0] && sum[1] && sum[2] && sum[3])
          FORC4 pre_mul[c] = (float) sum[c+4] / sum[c];
        else if (cam_mul[0] && cam_mul[2])
          memcpy (pre_mul, cam_mul, sizeof pre_mul);
        else
          fprintf (stderr,_("%s: Cannot use camera white balance.\n"), ifname);
      }
      if (pre_mul[3] == 0) pre_mul[3] = colors < 4 ? pre_mul[1] : 1;
      dark = black;
      sat = maximum;
      if (threshold) wavelet_denoise();
      maximum -= black;
      for (dmin=DBL_MAX, dmax=c=0; c < 4; c++) {
        if (dmin > pre_mul[c])
        dmin = pre_mul[c];
        if (dmax < pre_mul[c])
        dmax = pre_mul[c];
      }
      if (!highlight) dmax = dmin;
      FORC4 scale_mul[c] = (pre_mul[c] /= dmax) * 65535.0 / maximum;
      if (verbose) {
        fprintf (stderr,
          _("Scaling with darkness %d, saturation %d, and\nmultipliers"), dark, sat);
        FORC4 fprintf (stderr, " %f", pre_mul[c]);
        fputc ('\n', stderr);
      }
      size = iheight*iwidth;
      for (i=0; i < size*4; i++) {
        val = image[0][i];
        if (!val) continue;
        val -= black;
        val *= scale_mul[i & 3];
        image[0][i] = CLIP(val);
      }
      if ((aber[0] != 1 || aber[2] != 1) && colors == 3) {
        if (verbose)
          fprintf (stderr,_("Correcting chromatic aberration...\n"));
        for (c=0; c < 4; c+=2) {
          if (aber[c] == 1) continue;
          img = (ushort *) malloc (size * sizeof *img);
          merror (img, "scale_colors()");
          for (i=0; i < size; i++)
        img[i] = image[i][c];
          for (row=0; row < iheight; row++) {
        ur = fr = (row - iheight*0.5) * aber[c] + iheight*0.5;
        if (ur > iheight-2) continue;
        fr -= ur;
        for (col=0; col < iwidth; col++) {
          uc = fc = (col - iwidth*0.5) * aber[c] + iwidth*0.5;
          if (uc > iwidth-2) continue;
          fc -= uc;
          pix = img + ur*iwidth + uc;
          image[row*iwidth+col][c] =
            (pix[     0]*(1-fc) + pix[       1]*fc) * (1-fr) +
            (pix[iwidth]*(1-fc) + pix[iwidth+1]*fc) * fr;
        }
          }
          free(img);
        }
      }
    }
    Un saludo:
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es

  7. #7
    Ingreso
    07 mar, 06
    Ubicación
    Madrid (a ratos Alicante)
    Mensajes
    9,426
    Post Thanks / Like
    Cita Iniciado por ManuelLlorens Ver mensaje
    Lo de "scale" me suena a que sí que hace un reescalado
    Claro que lo hace, está aquí:

    (pre_mul[c] /= dmax) * 65535.0 / maximum;

    junta en un único factor el escalado que supone el propio balance de blancos con el escalado a la saturación (maximum debe ser la saturación-black). dmax ni idea de lo que es.

    Lo que digo es que para nuestro cálculo de WB no necesitamos hacerlo. Esta noche a ver si me estudio un poco scale_colors() y la reciclo.
    "En ocasiones veo halos."

    http://www.guillermoluijk.com para suscribirte haz clic aquí
    Último contenido: EL MITO DEL TRÍPODE QUE ASESINÓ A UN ESTABILIZADOR

  8. #8
    Ingreso
    22 mar, 08
    Ubicación
    Oviedo
    Mensajes
    14,367
    Post Thanks / Like
    Sí es crítico, porque de no hacerlo antes de interpolar se crean artefactos horribles (comprobado: antes de interp. vs después de interp.) además de que rompe toda la casuística de multiplicadores >1, o <1 y la recuperacion de altas luces.
    Hombre tanto como horribles ... a mi me ha costado verlo Es que mi ojo es muy malo y tú eres muy perfeccionista....
    Pero de eso se trata de conseguir lo mejor que se pueda dar. Si la diferencia es visible en pantalla, habrá que hacerlo "bien" aunque sea más lento.

    Está claro en el ejemplo, hacerlo después crea algunos artefactos de color en los bordes... donde mejor se ve en el ejemplo es donde la veleta ¿no? que aparece como un halo amarillento o blanquecino y queda como con menos definición.
    En los bordes de la cúpula también se ve algo así. ¿A eso te refieres no?

    Pues nada, lo que el usuario tendrá que tener claro es que debe de hacer el balance lo primero, y con la interpolación en lineal. Una vez que no lo vaya a tocas, pasar a otra interpolación más sofisticada.

  9. #9
    Ingreso
    07 mar, 06
    Ubicación
    Madrid (a ratos Alicante)
    Mensajes
    9,426
    Post Thanks / Like
    Cita Iniciado por ariznaf Ver mensaje
    Está claro en el ejemplo, hacerlo después crea algunos artefactos de color en los bordes...
    son los tonos verdosos que aparecen en ciertas aristas. Es todo debido a tonos falsos generados al hacer el demosaicing de la matriz de Bayer.
    En un sensor Foveon por ejemplo no pasaría nada de esto y el balance de blancos puede hacerse a posteriori sin problemas.
    "En ocasiones veo halos."

    http://www.guillermoluijk.com para suscribirte haz clic aquí
    Último contenido: EL MITO DEL TRÍPODE QUE ASESINÓ A UN ESTABILIZADOR

  10. #10
    Ingreso
    30 abr, 08
    Ubicación
    Madrid
    Mensajes
    883
    Post Thanks / Like
    Cita Iniciado por _GUI_ Ver mensaje
    son los tonos verdosos que aparecen en ciertas aristas. Es todo debido a tonos falsos generados al hacer el demosaicing de la matriz de Bayer.
    Eso es lo que quita bastante bien el median filter, sin apenas afectar a la textura.

    Un saludo:
    Manuel Llorens

    Olympus E-P1, E-510, E-300
    www.rawness.es


 

Marcadores

Marcadores

Permisos de publicación

  • No puedes crear nuevos temas
  • No puedes responder temas
  • No puedes subir archivos adjuntos
  • No puedes editar tus mensajes
  •