Combinación con Operadores de BiCoTI-I


Aplicaremos ahora varios algoritmos de BiCoTI-I a otra imagen leída del disco. Una novedad con respecto al caso anterior, es la posibilidad de ver las imágenes intermedias durante el curso de la aplicación.

El siguiente es el fragmento de código a estudiar:
 

#include <actor_image_2D_double_qt.hpp>

typedef bicotiActorImage2DDoubleQT ImaT;
          
void main( int argc, char ** argv )  
{ 
  ImaT ima1;
  ima1.BuildMapper();
  ima1.GetMapper()->BuildDeviceFile( "imagen.jpg" );
  ima1.GetMapper()->BuildMapperJPEGIJG();
  ima1.GetMapper()->Read();
  ima1.DestroyMapper();

  ImaT :: HomologousFactory factory;
  ImaT :: EventLoopManager event_loop( argc, argv );
  ima1.GetActor()->SetSize( ima1.GetImplementation()->GetX0Size(), ima1.GetImplementation()->GetX1Size() );
  ima1.GetActor()->SetMainActor( true );
  factory.CreateHomologous( ima1.GetActor() );
  event_loop.Start();

  ima1.BuildOperatorUnary();
  ima1.GetOperatorUnary()->Addition( 10 );
  ima1.GetActor()->SetVisible( true );
  ima1.GetActor()->RefreshImage();
  event_loop.Start();

  ima1.GetOperatorUnary()->Product( 3 );
  ima1.GetActor()->SetVisible( true );
  ima1.GetActor()->RefreshImage();
  event_loop.Start();

  ima1.GetOperatorUnary()->Logarithm();
  ima1.GetOperatorUnary()->Product( 35 );
  ima1.GetActor()->SetVisible( true );
  ima1.GetActor()->RefreshImage();
  event_loop.Start();

  ima1.DestroyOperatorUnary();

  ImaT ima2;
  ima2.BuildMapper();
  ima2.GetMapper()->BuildDeviceFile( "imagen.jpg" );
  ima2.GetMapper()->BuildMapperJPEGIJG();
  ima2.GetMapper()->Read();
  ima2.DestroyMapper();

  ima2.BuildOperatorMultiple();
  ima2.GetOperatorMultiple()->Append( ima1.GetImplementation() );
  ima2.GetOperatorMultiple()->Product();
  ima2.DestroyOperatorMultiple();
  
  ima2.BuildOperatorUnary();
  ima2.GetOperatorUnary()->Product( 1.0/255 );
  ima2.GetActor()->SetMainActor( true );
  ima2.GetActor()->SetSize( ima2.GetImplementation()->GetX0Size(), ima2.GetImplementation()->GetX1Size() );
  factory.CreateHomologous( ima2.GetActor() );
  event_loop.Start();
};


Imagen Original

El primer bloque de código al igual que los ejmplos previos carga sobre una imagen de pixel double, la imagen del archivo imagen.jpg.
En el segundo bloque se crea un factory y un event loop, se fijan las dimensiones del actor (en este caso la ventana de visualización) para que coincidan con las de la imagen. Se fija el actor como actor principal, de esta forma al cerrar la ventana, además de hacer invisible al actor, se detiene el loop de eventos, volviendo la aplicación a su curso secuencial.
Una vez cerrada la ventana, se construye una fachada para operaciones de la imagen en si misma y se suma 10 a todos los pixeles de esta. Se vuelve a hacer visible el actor, se refrescan los cambios en el homólogo y se vuelve a lanzar el loop de eventos.

Sumando 10 a la original

En la imagen anterior se ve la saturación en algunos de los pixeles, especialmente en la esquina inferior izquierda. Cerrando la ventana nuevamente, se multiplican todos los pixeles por 3 y se refrescan los cambios, para ver la imagen inferior ahora completamente saturada.

Imagen de prueba

En tercer lugar se aplica el logaritmo a cada pixel. Esto reduce demasiado el brillo de la imagen y en consecuencia se multiplica toda por 35 para volver a recuperarlo. Es interesante destacar que de haber usado pixels unsigned char, el resultado tendría un puñado de niveles de gris debido a la discretización de los niveles.

Imagen de prueba

Seguidamente volvemos a leer la imagen ahora sobre ima2, se normalizan los niveles de gris, se multiplican ima1 e ima2 volcando el resultado en ima2. Mostramos ima2 y esperamos que la ventana sea cerrada para terminar la aplicación.

Imagen de prueba