Introducción al manejo de imágenes con Visual Basic.NET...

103
T T RATAMIENTO RATAMIENTO R RADIOMÉTRICO ADIOMÉTRICO 1.1.- Introducción al manejo de imágenes con Visual Basic.NET Las imágenes en .NET se gestionan a través de GDI+ (Graphics Device Interface). Esto amplia las características de ediciones anteriores de VB, porque añade funciones gráficas que anteriormente no estaban disponibles. Con GDI+, Visual Basic proporciona capacidades gráficas en todos los sentidos, desde el manejo de gráficos vectoriales hasta la gestión de la impresión, pasando por el tratamiento de imágenes que, en definitiva, es la cuestión que nos interesa en esta parte de la asignatura. Todas estas funcionalidades se proporcionan dentro de un NameSpace llamado System.Drawing. 1.1.1.- Creación de una aplicación Abre un proyecto nuevo de VB, del tipo Aplicación para Windows, y guárdalo como ProcesadorImagen. Cuando terminemos de definir los controles que insertaremos en este formulario, finalmente tendrá el siguiente aspecto: Figura 1.1.- Aspecto final de la aplicación ProcesadorImagen. 1

Transcript of Introducción al manejo de imágenes con Visual Basic.NET...

Page 1: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

TTRATAMIENTORATAMIENTO R RADIOMÉTRICOADIOMÉTRICO

1.1.− Introducción al manejo de imágenes con Visual Basic.NET

Las imágenes en .NET se gestionan a través de GDI+ (Graphics Device Interface). Esto amplia las características de ediciones anteriores de VB, porque añade funciones gráficas que anteriormente no estaban disponibles. Con GDI+, Visual Basic proporciona capacidades gráficas en todos los sentidos, desde el manejo de gráficos vectoriales hasta la gestión de la impresión, pasando por el tratamiento de imágenes que, en definitiva, es la cuestión que nos interesa en esta parte de la asignatura. Todas estas funcionalidades se proporcionan dentro de un NameSpace llamado System.Drawing.

1.1.1.- Creación de una aplicación

Abre un proyecto nuevo de VB, del tipo Aplicación para Windows, y guárdalo como ProcesadorImagen. Cuando terminemos de definir los controles que insertaremos en este formulario, finalmente tendrá el siguiente aspecto:

Figura 1.1.- Aspecto final de la aplicación ProcesadorImagen.

1

Page 2: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

CURSO 2009-2010 HERRAMIENTAS INFORMÁTICAS

GEOTECNOLOGÍAS CARTOGRÁFICAS EN INGENIERÍA Y ARQUITECTURA PARA EL GEOPROCESADO

Como vemos, hay dos contenedores de imagen con barras de desplazamiento. En el izquierdo mostraremos la imagen original mientras que en el derecho la misma imagen tras haber hecho alguna operación. Además, tenemos un menú principal en la parte superior del formulario, donde podremos seleccionar las acciones a realizar, y en la parte inferior una barra de estado donde se mostrarán mensajes de estado, una barra de progreso y coordenadas de las imágenes.

En primer lugar inserta un menú (MenuStrip) y una barra de estado (StatusStrip). Dentro del menú coloca los elementos principales: Archivo, Operaciones y Transformaciones. Dentro del primero coloca las opciones clásicas Abrir, Guardar, Cerrar, y Salir.

Figura 1.2.- Ítems del menú Archivo

Hay varias maneras de mostrar imágenes: en el fondo de un formulario, dentro de un control PictureBox, ... . La primera es la más cómoda y proporciona las barras de desplazamiento de forma automática, pero puede generar problemas si en el formulario se introducen elementos (menús y barras de herramientas) que pueden ser desplazados por el usuario en tiempo de ejecución. Por otro lado, cargar la imagen directamente en un contenedor de imagen como PictureBox no ofrece la posibilidad de utilizar las barras de desplazamiento (scroll) de forma automática.

Una solución pasa por utilizar un control de tipo Panel¸ que proporciona las barras de desplazamiento, e introducir dentro un control PictureBox donde se cargará la imagen. Este control PictureBox se debe acoplar en el contenedor principal (que en este caso corresponde con el control Panel), y tener la propiedad SizeMode como Autosize.

Bien, pues inserta dos contenedores de imagen (Panel+PictureBox) como se ha indicado en el párrafo anterior.

1.1.2.- Visualización de imágenes

Ahora vamos a empezar a darle funcionalidad a la aplicación y empezaremos gestionando la apertura y cierre de imágenes. Para ello introduce en primer lugar un control del tipo OpenFileDialog, y luego introduce el siguiente código en el evento Click de la opción Abrir del menú Archivo:

2

Page 3: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

TRATAMIENTO RADIOMÉTRICO

BENJAMÍN ARIAS PÉREZ PROCESAMIENTO DIGITAL DE IMÁGENES

With OpenFileDialog1 .Filter = "Ficheros BMP|*.bmp" & _ "|Ficheros GIF|*.gif" & _ "|Ficheros JPG o JPEG|*.jpg;*.jpeg" & _ "|Ficheros PNG|*.png" & _ "|Ficheros TIFF|*.tif" .FilterIndex = 3 If (.ShowDialog() = Windows.Forms.DialogResult.OK) Then PictureBox1.Image = Image.FromFile(.FileName) Panel1.AutoScrollMinSize = PictureBox1.Image.Size End If End With

Se necesita inicializar la propiedad AutoScrollMinSize del control Panel1 con el tamaño de la imagen para poder mostrar las barras de desplazamiento.

Para cerrar la imagen deberemos incluir en la opción Cerrar del menú Archivo el siguiente código:

PictureBox1.Image = NothingPanel1.AutoScroll = False

Por último, en la opción Salir del menú Archivo introducimos simplemente End, para que la aplicación finalice al seleccionar esta opción.

1.1.3.- Acceso a los niveles digitales de la imagen

Ya hemos visto cómo cargar y visualizar imágenes, ahora vamos a ver cómo podemos acceder a los colores correspondientes a los píxeles de la imagen cargada de una forma intuitiva. En este tema se van a volcar los colores a una matriz bidimensional con las mismas dimensiones que la imagen.

Los colores se leen en un formato específico, System.Drawing.Color, que contiene los valores de rojo, verde y azul.

Como la matriz bidimensional la queremos poder utilizar en cualquier lugar de la aplicación, lo mejor es definirla sin dimensiones en la sección de Declaraciones del formulario.

3

Page 4: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

CURSO 2009-2010 HERRAMIENTAS INFORMÁTICAS

GEOTECNOLOGÍAS CARTOGRÁFICAS EN INGENIERÍA Y ARQUITECTURA PARA EL GEOPROCESADO

Public Matriz(,) As System.Drawing.Color

Utilizando Image del control PictureBox podemos acceder a diferentes propiedades de la imagen cargada, como son el ancho (Width) y el alto (Height), que nos van a hacer falta para dimensionar la matriz. Así, una vez cargada la imagen ya podremos redimensionar la matriz para que tenga capacidad de almacenar la imagen.

En el menú Operaciones añade un elemento llamado Cargar Matriz y escribe dentro el siguiente código: Dim i, j As Long ReDim Matriz(PictureBox1.Image.Width - 1, PictureBox1.Image.Height - 1) Dim bmp As New Bitmap(PictureBox1.Image) For i = 0 To PictureBox1.Image.Width - 1 For j = 0 To PictureBox1.Image.Height - 1 Matriz(i, j) = bmp.GetPixel(i, j) Next Next

En primer lugar fíjate que establecemos el ancho y el alto, pero descontamos la unidad. Esto es debido a que el mínimo valor de la matriz es 0, mientras que el alto y el ancho comienzan en 1.

Después definimos un objeto de tipo Bitmap, que nos va a permitir acceder a los colores de la imagen visualizada.

Posteriormente hemos implementado un doble bucle For, que va a recorrer todos y cada uno de los píxeles de la imagen. Los colores para cada uno de los píxeles (i,j) se van obtener con el método GetPixel del Bitmap antes definido. Cuando concluya este doble bucle tendremos en Matriz los colores de la imagen que hemos cargado, y tenemos la misma estructura bidimensional que la propia imagen.

1.1.4.- Pintar una imagen

Para dibujar la imagen que acabamos de cargar en la matriz, genera una nueva opción en Operaciones, que se llame Pintar Matriz. Vamos a ver qué código hace falta para generar una imagen nueva.

4

Page 5: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

TRATAMIENTO RADIOMÉTRICO

BENJAMÍN ARIAS PÉREZ PROCESAMIENTO DIGITAL DE IMÁGENES

Dim i, j As LongDim bmp As New Bitmap(Matriz.GetUpperBound(0) + 1, Matriz.GetUpperBound(1) + 1)Dim img As Imageimg = CType(bmp, Image)PictureBox2.Image = imgPanel2.AutoScrollMinSize = PictureBox2.Image.SizePictureBox2.Refresh()

For i = 0 To Matriz.GetUpperBound(0) For j = 0 To Matriz.GetUpperBound(1) bmp.SetPixel(i, j, Matriz(i, j)) NextNext img = CType(bmp, Image)PictureBox2.Image = imgPictureBox2.Refresh()

Hay que crear un nuevo Bitmap, mientras que Matriz va de 0 a alto-1 (ancho-1), el tamaño de la imagen va de 1 a alto (ancho).

5

Page 6: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

CURSO 2009-2010 HERRAMIENTAS INFORMÁTICAS

GEOTECNOLOGÍAS CARTOGRÁFICAS EN INGENIERÍA Y ARQUITECTURA PARA EL GEOPROCESADO

1.1.5.- Guardar una imagen

Las imágenes se pueden salvar en diferentes formatos, característica proporcionada por .NET de forma tan sencilla como especificar el formato. Inserta un control de tipo SaveFileDialog e implementa el siguiente código en la opción Guardar del menú Archivo:

With SaveFileDialog1 .Filter = "Ficheros BMP|*.bmp" & _ "|Ficheros GIF|*.gif" & _ "|Ficheros JPG o JPEG|*.jpg;*.jpeg" & _ "|Ficheros PNG|*.png" & _ "|Ficheros TIFF|*.tif" .FilterIndex = 3

If (.ShowDialog() = Windows.Forms.DialogResult.OK) Then If SaveFileDialog1.FileName <> "" Then Dim fs As System.IO.FileStream = CType(SaveFileDialog1.OpenFile(),

System.IO.FileStream) Select Case SaveFileDialog1.FilterIndex Case 1 PictureBox2.Image.Save(fs, _

System.Drawing.Imaging.ImageFormat.Bmp) Case 2 PictureBox2.Image.Save(fs, _

System.Drawing.Imaging.ImageFormat.Gif) Case 3 PictureBox2.Image.Save(fs, _

System.Drawing.Imaging.ImageFormat.Jpeg) Case 4 PictureBox2.Image.Save(fs, _

System.Drawing.Imaging.ImageFormat.Png) Case 5 PictureBox2.Image.Save(fs, _

System.Drawing.Imaging.ImageFormat.Tiff) End Select fs.Close() End If End If End With

6

Page 7: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

TRATAMIENTO RADIOMÉTRICO

BENJAMÍN ARIAS PÉREZ PROCESAMIENTO DIGITAL DE IMÁGENES

1.2.− Diagrama de flujo

La aplicación que hemos generado sigue el siguiente diagrama de flujo.

1.3.− Procesamiento de imágenes

En los apartados anteriores hemos visto una serie de tareas para empezar a trabajar con imágenes, y gracias a ellas ya estamos en disposición de empezar a realizar algún tipo de procesamiento a las imágenes, intercalando el procesamiento en el diagrama de flujo básico de la aplicación:

7

Abrir imagen

Cargar Matriz

Pintar Matriz

Guardar imagen

Procesamiento imagen

Abrir imagen

Cargar Matriz

Pintar Matriz

Guardar imagen

Page 8: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

CURSO 2009-2010 HERRAMIENTAS INFORMÁTICAS

GEOTECNOLOGÍAS CARTOGRÁFICAS EN INGENIERÍA Y ARQUITECTURA PARA EL GEOPROCESADO

Que lógicamente tiene que ir entre la carga de la imagen y el pintado de la matriz. Si el procesamiento es sencillo (inversión, binarización, …) se puede implementar directamente en el código correspondiente a Pintar Matriz. Por otro lado, si el procesamiento es algo más complicado (máscaras) es mejor copiar el código correspondiente en una nueva opción del menú Operaciones.

1.3.1.- Inversión de los colores de la imagen

Vamos a implementar un procesamiento de imagen sencillo, como es la inversión de los colores de la imagen, y posteriormente se dejará como tarea la realización de varios tipos de procesamiento. Para ello, implementa la variable Tipo_Procesado en la sección de Declaraciones del formulario, para que sea pública y de tipo cadena.

Public Tipo_Procesado As String

A continuación crea la opción Inversión en el menú Operaciones. En el evento Click de dicha opción incorpora el siguiente código:

Tipo_Procesado = "INVERSION"Call PintarMatrizToolStripMenuItem_Click(sender, e)

Lo que estamos es indicando que queremos hacer un procesado de tipo negativo y a continuación se llama al evento Click de la opción Pintar Matriz del menú Operaciones. El código de este evento lo introducimos anteriormente, pero es necesario realizar una serie de cambios, dado que no podremos realizar ningún cambio en el color porque la estructura System.Drawing.Color es de sólo lectura. Por ello, lo más adecuado es declarar tres variables de tipo Byte, que se pueden llamar Rojo, Verde y Azul y utilizarlas para hacer los cambios. Además, introducimos en el doble bucle For un Select Case que determinará qué tipo de procesamiento deseamos realizar (en este caso “INVERSION”). Por último, en SetPixel definimos el color mediante el método FromArgb.

8

Page 9: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

TRATAMIENTO RADIOMÉTRICO

BENJAMÍN ARIAS PÉREZ PROCESAMIENTO DIGITAL DE IMÁGENES

Dim Rojo, Verde, Azul As Byte For i = 0 To Matriz.GetUpperBound(0) For j = 0 To Matriz.GetUpperBound(1) Rojo = Matriz(i, j).R Verde = Matriz(i, j).G Azul = Matriz(i, j).B Select Case Tipo_Procesado Case Is = "INVERSION" Rojo = 255 - Rojo Verde = 255 - Verde Azul = 255 - Azul End Select bmp.SetPixel(i, j, Color.FromArgb(Rojo, Verde, Azul)) Next Next

Así, cuando queramos añadir un nuevo procesamiento deberemos seguir estos pasos:

1. Añadir una nueva opción en el menú Operaciones.

2. En el código de esta opción, definir Tipo_Procesado e invocar al evento Click de la opción Pintar Matriz.

3. En el doble bucle For del código de este evento, añadir en el Select Case el tipo de procesado con las nuevas fórmulas para las variables Rojo, Verde y Azul.

Generalmente se realizan los procesamientos a imágenes en niveles de gris. Los colores rojo, verde y azul de las imágenes en niveles de gris tienen el mismo valor para cada píxel.

1.3.2.- Máscaras

El procesamiento con máscaras implica trabajar con un entorno de un punto, representado por una matriz generalmente cuadrada y con número impar de píxeles (3x3, 5x5, etc…). Es decir, en lugar de considerar

9

Page 10: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

CURSO 2009-2010 HERRAMIENTAS INFORMÁTICAS

GEOTECNOLOGÍAS CARTOGRÁFICAS EN INGENIERÍA Y ARQUITECTURA PARA EL GEOPROCESADO

únicamente los niveles digitales (colores) de cada píxel, se consideran además los niveles digitales de los píxeles adyacentes.

Esto implica que el doble bucle For con el que estamos trabajando no puede empezar en la primera fila (ni en la primera columna) de la imagen, ni puede terminar en la última fila (última fila) de la imagen. Por ejemplo, si la máscara es 3x3, el doble bucle debe ser:

For i = 1 To (Matriz.GetUpperBound(0)-1) For j = 1 To (Matriz.GetUpperBound(1)-1)

... NextNext

En caso de ser de 5x5, irá desde 2 hasta el límite -2.

A modo de ejemplo vamos a implementar la máscara correspondiente a Sobel:

1 0 -1

41

2 0 -2

1 0 -1

Declaramos una matriz de tipo Byte en la sección de Declaraciones del formulario para poder acceder a ella desde donde nos interese, y la llamamos Mascara.

Public Mascara(,) as Integer

10

Page 11: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

TRATAMIENTO RADIOMÉTRICO

BENJAMÍN ARIAS PÉREZ PROCESAMIENTO DIGITAL DE IMÁGENES

Generamos la opción Sobel dentro del menú Operaciones con el siguiente código:

Dim i, j As Long Dim mi, mj As Long Dim SumaRojo, SumaMascara As Long Dim factor, desviacion As Double Dim Rojo, Verde, Azul As Integer Dim bmp As New Bitmap(Matriz.GetUpperBound(0) + 1, Matriz.GetUpperBound(1) + 1)

Dim img As Image img = CType(bmp, Image) PictureBox2.Image = img Panel2.AutoScrollMinSize = PictureBox2.Image.Size PictureBox2.Refresh()

ReDim Mascara(2, 2)

Mascara(0, 0) = 1 : Mascara(0, 1) = 0 : Mascara(0, 2) = -1 Mascara(1, 0) = 2 : Mascara(1, 1) = 0 : Mascara(1, 2) = -2 Mascara(2, 0) = 1 : Mascara(2, 1) = 0 : Mascara(2, 2) = -1

For mi = -1 To 1 For mj = -1 To 1 SumaMascara = SumaMascara + Mascara(mi + 1, mj + 1) Next Next If SumaMascara = 0 Then SumaMascara = 1 factor = 1/4 desviacion = 0

11

Page 12: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

CURSO 2009-2010 HERRAMIENTAS INFORMÁTICAS

GEOTECNOLOGÍAS CARTOGRÁFICAS EN INGENIERÍA Y ARQUITECTURA PARA EL GEOPROCESADO

'Con este cuadruple bucle se recorre la máscara y la matriz For i = 1 To Matriz.GetUpperBound(0) - 1 For j = 1 To Matriz.GetUpperBound(1) - 1 SumaRojo = 0 For mi = -1 To 1 For mj = -1 To 1 SumaRojo = SumaRojo + Matriz(i + mi, j + mj).R * Mascara(mi + 1, mj +

1) Next Next

Rojo = Math.Abs(SumaRojo / SumaMascara) Rojo = Math.Abs(Rojo / factor + desviacion) If Rojo > 255 Then Rojo = 255 bmp.SetPixel(i, j, Color.FromArgb(Rojo, Rojo, Rojo)) Next 'Esta aquí que se refresque línea a línea img = CType(bmp, Image) PictureBox2.Image = img PictureBox2.Refresh() Next

Donde hemos insertado el código de Pintar Matriz necesario para poder pintar en la imagen. Esto es más sencillo en este caso que añadir nuevos casos en el doble bucle For de Pintar Matriz, como hemos hecho para los procesamientos sencillos.

En el código se está considerando el uso de imágenes en niveles de gris, por ello se trabaja solamente con Rojo.

12

Page 13: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

TRATAMIENTO RADIOMÉTRICO

BENJAMÍN ARIAS PÉREZ PROCESAMIENTO DIGITAL DE IMÁGENES

1.4.− Información en la posición del ratón

Para terminar con este tema, vamos a ver cómo podemos acceder a las coordenadas y al nivel digital (color), y cómo cambiar el puntero de Windows cuando pase por encima de la imagen. Cuando generamos la aplicación, incluimos una barra de estado (StatusStrip), y en ella se irán incluyendo los elementos necesarios para poder visualizar esta información.

Para ello incluimos los siguientes objetos en la sección de Declaraciones del formulario: Friend WithEvents EtiquetaCoord_StatusStrip As ToolStripStatusLabel Friend WithEvents EtiquetaND_StatusStrip As ToolStripStatusLabel

En el método Load del formulario (cuidado con las llaves y los paréntesis): Me.EtiquetaCoord_StatusStrip = New ToolStripStatusLabel Me.StatusStrip1.Items.AddRange(New ToolStripItem() {Me.EtiquetaCoord_StatusStrip}) Me.EtiquetaND_StatusStrip = New ToolStripStatusLabel Me.StatusStrip1.Items.AddRange(New ToolStripItem() {Me.EtiquetaND_StatusStrip})

Y en el evento MouseMove del PictureBox1:

EtiquetaCoord_StatusStrip.Text = "COORDENADAS X: " & CStr(e.X) & " ; " & _ "Y: " & CStr(e.Y) 'X e Y empiezan en 0 If Not (Matriz Is Nothing) Then EtiquetaND_StatusStrip.Text = "COLOR R:" & CStr(Matriz(e.X, e.Y).R) & " ; " & _ "G:" & CStr(Matriz(e.X, e.Y).G) & " ; " & _ "B:" & CStr(Matriz(e.X, e.Y).B) End If

13

Page 14: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

CURSO 2009-2010 HERRAMIENTAS INFORMÁTICAS

GEOTECNOLOGÍAS CARTOGRÁFICAS EN INGENIERÍA Y ARQUITECTURA PARA EL GEOPROCESADO

Por último, para que el puntero del ratón se visualice como una cruz al pasar por encima de las imágenes, simplemente debemos incluir en el método Load del formulario las siguientes sentencias:

PictureBox1.Cursor = Cursors.Cross PictureBox2.Cursor = Cursors.Cross

Índice del tema

1.1.- Introducción al manejo de imágenes con Visual Basic.NET...................................................................1

1.1.1.- Creación de una aplicación...............................................................................................................1

1.1.2.- Visualización de imágenes................................................................................................................2

1.1.3.- Acceso a los niveles digitales de la imagen.......................................................................................3

1.1.4.- Pintar una imagen.............................................................................................................................5

1.1.5.- Guardar una imagen..........................................................................................................................6

1.2.- Diagrama de flujo....................................................................................................................................7

1.3.- Procesamiento de imágenes.....................................................................................................................7

1.3.1.- Inversión de los colores de la imagen...............................................................................................8

1.3.2.- Máscaras...........................................................................................................................................9

1.4.- Información en la posición del ratón.....................................................................................................13

14

Page 15: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

TTRATAMIENTORATAMIENTO G GEOMÉTRICOEOMÉTRICO

2.1. Introducción

En este tema se van a tratar las transformaciones geométricas píxel a píxel. Para ello, en los ejemplos que se exponen a continuación, se parte siempre de la situación en la que se encuentre la imagen abierta y cargada en una matriz. Cada uno de ellos se puede implementar como una nueva opción dentro de submenú llamado Transformaciones.

1

Page 16: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

Curso 2009-2010 Herramientas Informáticas

Geotecnologías Cartográficas en Ingeniería y Arquitectura para el Geoprocesado

2.2. Translación

'Declaración de variables auxiliares Dim i, j As Long Dim Rojo, Verde, Azul As Byte Dim Xo, Yo As Double

'Parámetros Xo = 100 Yo = 50 'Xo = CInt(InputBox("Introduce la translación en X", , 0)) 'Yo = CInt(InputBox("Introduce la translación en Y", , 0))

'Cálculo dimensiones nueva imagen Dim Ancho, Alto As Integer Ancho = Matriz.GetUpperBound(0) + 1 + Xo Alto = Matriz.GetUpperBound(1) + 1 + Yo

'Declaración del mapa de bits Dim bmp As New Bitmap(Ancho, Alto)

'Vinculación bitmap con image Dim img As Image img = CType(bmp, Image) PictureBox2.Image = img

'Activación de las barras de desplazamiento Panel2.AutoScrollMinSize = PictureBox2.Image.Size PictureBox2.Refresh()

'Doble bucle para efectuar la traslación For i = 0 To Matriz.GetUpperBound(0) For j = 0 To Matriz.GetUpperBound(1) Rojo = Matriz(i, j).R Verde = Matriz(i, j).G Azul = Matriz(i, j).B

2

Page 17: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

TRATAMIENTO GEOMÉTRICO

BENJAMÍN ARIAS PÉREZ PROCESAMIENTO DIGITAL DE IMÁGENES

bmp.SetPixel(Convert.ToInt32(i + Xo), Convert.ToInt32(j + Yo), Color.FromArgb(Rojo, Verde, Azul))

Next 'Esto es solo para que se refresque línea a línea img = CType(bmp, Image) PictureBox2.Image = img PictureBox2.Refresh() Next

Me.Refresh()

2.3. Escala

'Declaración de variables auxiliares Dim i, j As Long Dim Rojo, Verde, Azul As Byte Dim Escala As Double

'Parámetros Escala = 1.5 'Escala = CDbl(InputBox("Introduce el factor de Escala", , 1))

'Cálculo dimensiones nueva imagen Dim Ancho, Alto As Integer Ancho = (Matriz.GetUpperBound(0) + 1) * Escala Alto = (Matriz.GetUpperBound(1) + 1) * Escala

'Declaración del mapa de bits Dim bmp As New Bitmap(Ancho, Alto)

'Vinculación bitmap con image Dim img As Image img = CType(bmp, Image) PictureBox2.Image = img

'Activación de las barras de desplazamiento

3

Page 18: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

Curso 2009-2010 Herramientas Informáticas

Geotecnologías Cartográficas en Ingeniería y Arquitectura para el Geoprocesado

Panel2.AutoScrollMinSize = PictureBox2.Image.Size PictureBox2.Refresh()

'Doble bucle para efectuar el escalado For i = 0 To Matriz.GetUpperBound(0) For j = 0 To Matriz.GetUpperBound(1) Rojo = Matriz(i, j).R Verde = Matriz(i, j).G Azul = Matriz(i, j).B bmp.SetPixel(Convert.ToInt32(i * Escala), Convert.ToInt32(j * Escala),

Color.FromArgb(Rojo, Verde, Azul)) Next 'Esto es solo para que se refresque línea a línea img = CType(bmp, Image) PictureBox2.Image = img PictureBox2.Refresh() Next

Me.Refresh()

2.4. Sentido Inverso

Habrás visto el problema de huecos en la imagen que se genera con el código anterior. Esto se soluciona si se remuestrea a la inversa, es decir, se recorre la imagen destino y se busca el color en la imagen original.

'Declaración de variables auxiliares Dim i, j As Long Dim Rojo, Verde, Azul As Byte Dim Escala As Double

'Parámetros 'Escala = 1.5 Escala = CDbl(InputBox("Introduce el factor de Escala", , 1))

4

Page 19: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

TRATAMIENTO GEOMÉTRICO

BENJAMÍN ARIAS PÉREZ PROCESAMIENTO DIGITAL DE IMÁGENES

'Cálculo dimensiones nueva imagen Dim Ancho, Alto As Integer Ancho = (Matriz.GetUpperBound(0) + 1) * Escala Alto = (Matriz.GetUpperBound(1) + 1) * Escala

'Declaración del mapa de bits Dim bmp As New Bitmap(Ancho, Alto)

'Vinculación bitmap con image Dim img As Image img = CType(bmp, Image) PictureBox2.Image = img

'Activación de las barras de desplazamiento Panel2.AutoScrollMinSize = PictureBox2.Image.Size PictureBox2.Refresh()

'Doble bucle para efectuar el escalado For i = 0 To Convert.ToInt32(Ancho - (1 * Escala)) For j = 0 To Convert.ToInt32(Alto - (1 * Escala)) Rojo = Matriz(Convert.ToInt32(i / Escala), Convert.ToInt32(j / Escala)).R Verde = Matriz(Convert.ToInt32(i / Escala), Convert.ToInt32(j / Escala)).G Azul = Matriz(Convert.ToInt32(i / Escala), Convert.ToInt32(j / Escala)).B bmp.SetPixel(i, j, Color.FromArgb(Rojo, Verde, Azul)) Next 'Esto es solo para que se refresque línea a línea img = CType(bmp, Image) PictureBox2.Image = img PictureBox2.Refresh() Next

Me.Refresh()

5

Page 20: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

Curso 2009-2010 Herramientas Informáticas

Geotecnologías Cartográficas en Ingeniería y Arquitectura para el Geoprocesado

2.5. Transformación proyectiva

Ahora vamos a implementar la transformación proyectiva, tanto el cálculo de los parámetros como su aplicación en el remuestreo de una imagen. Para ello vamos a implementar una serie de operaciones matriciales necesarias para el cálculo.

Tanto en la asignatura Cámaras como en Procesamiento avanzado de imágenes digitales se dan los fundamentos necesarios para el uso de la transformación proyectiva.

El sistema de observación correspondiente expresado de forma matricial es:

[ ]VYX

hgfedcba

YYXYYXYXXXYX

=

−−−−

''

''1000''0001

VLXA =−∗

El cálculo de parámetros queda resuelto mediante (caso sobredeterminado):

T

T

AANdonde

LANX

∗=

= − 1

6

Page 21: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

TRATAMIENTO GEOMÉTRICO

BENJAMÍN ARIAS PÉREZ PROCESAMIENTO DIGITAL DE IMÁGENES

2.5.1.- Cálculos matriciales

Para implementar las operaciones matriciales inserta en el proyecto un módulo, y dentro de él inserta el código correspondiente a las funciones que se detallan a continuación. De esta manera podemos llamar a las funciones desde el código del formulario.

2.5.1.1.- Transpuesta de una matriz

Public Function Transpuesta(ByVal Matriz1(,) As Double) As Double(,)

'Creamos la matriz transpuesta Dim MatrizTranspuesta(Matriz1.GetUpperBound(1), Matriz1.GetUpperBound(0)) As Double

'Declaración de variables auxiliares Dim i, j As Short

'Doble bucle para efectuar la transposición For i = 0 To Matriz1.GetUpperBound(0) For j = 0 To Matriz1.GetUpperBound(1) MatrizTranspuesta(j, i) = Matriz1(i, j) Next Next

'Es necesario esta sentencia para que la función devuelva la matriz calculada Return MatrizTranspuesta

End Function

Ejemplo de uso de esta función. Escribe el siguiente código en el evento Load del formulario principal, introduce puntos de ruptura y agrega inspecciones para evaluar las variables en tiempo de ejecución:

Dim A(2, 1) As Double A(0, 0) = 2 : A(0, 1) = 3 A(1, 0) = 4 : A(1, 1) = 1 A(2, 0) = 9 : A(2, 1) = 8 Dim R(,) As Double = Transpuesta(A)

7

Page 22: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

Curso 2009-2010 Herramientas Informáticas

Geotecnologías Cartográficas en Ingeniería y Arquitectura para el Geoprocesado

2.5.1.2.- Suma de matrices

Public Function Suma(ByVal Matriz1(,) As Double, ByVal Matriz2(,) As Double) As Double(,)

'Comprobación de que las dos matrices son del mismo orden, If Not Matriz1.GetUpperBound(0) = Matriz2.GetUpperBound(0) AndAlso _ Matriz1.GetUpperBound(1) = Matriz2.GetUpperBound(1) Then Exit Function

'Creamos la matriz suma Dim MatrizSuma(Matriz1.GetUpperBound(0), Matriz1.GetUpperBound(1)) As Double

'Declaración de variables auxiliares Dim i, j As Short

'Doble bucle para efectuar la suma For i = 0 To Matriz1.GetUpperBound(0) For j = 0 To Matriz1.GetUpperBound(1) MatrizSuma(i, j) = Matriz1(i, j) + Matriz2(i, j) Next Next

'Es necesario esta sentencia para que la función devuelva la matriz calculada Return MatrizSuma

End Function

Ejemplo de uso:

Dim A(1, 1), B(1, 1) As Double A(0, 0) = 2 : A(0, 1) = 3 A(1, 0) = 4 : A(1, 1) = 1 B(0, 0) = 2 : B(0, 1) = 7 B(1, 0) = 5 : B(1, 1) = 3 Dim R As Double(,) = Suma(A, B)

8

Page 23: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

TRATAMIENTO GEOMÉTRICO

BENJAMÍN ARIAS PÉREZ PROCESAMIENTO DIGITAL DE IMÁGENES

2.5.1.3.- Producto de dos matrices

Public Function Producto(ByVal Matriz1(,) As Double, ByVal Matriz2(,) As Double) As Double(,)

'Comprobación de que las dos matrices son multiplicables If Not Matriz1.GetUpperBound(1) = Matriz2.GetUpperBound(0) Then Exit Function

'Creamos la matriz producto Dim MatrizProducto(Matriz1.GetUpperBound(0), Matriz2.GetUpperBound(1)) As Double

'Declaración de variables auxiliares Dim i, j, k As Short

'Triple bucle para efectuar el producto For i = 0 To MatrizProducto.GetUpperBound(0) For j = 0 To MatrizProducto.GetUpperBound(1) For k = 0 To Matriz1.GetUpperBound(1) MatrizProducto(i, j) = MatrizProducto(i, j) + _ Matriz1(i, k) * Matriz2(k, j) Next Next Next

'Es necesario esta sentencia para que la función devuelva la matriz calculada Return MatrizProducto

End Function

Ejemplo de uso:

Dim A(1, 2), B(2, 1) As Double

A(0, 0) = 2 : A(0, 1) = 3 : A(0, 2) = 2

9

Page 24: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

Curso 2009-2010 Herramientas Informáticas

Geotecnologías Cartográficas en Ingeniería y Arquitectura para el Geoprocesado

A(1, 0) = 4 : A(1, 1) = 1 : A(1, 2) = 5

B(0, 0) = 2 : B(0, 1) = 7 B(1, 0) = 5 : B(1, 1) = 3 B(2, 0) = 1 : B(2, 1) = 6

Dim R As Double(,) = Producto(A, B)

2.5.1.4.- Inversa de una matriz

Public Function Inversa(ByVal Matriz3(,) As Double) As Double(,)

'Método de inversión: matriz de paso

'Comprobación de que la matriz es cuadrada If Not Matriz3.GetUpperBound(0) = Matriz3.GetUpperBound(1) Then Exit Function

'Creamos dos matrices auxiliares Dim Matriz1(Matriz3.GetUpperBound(0), Matriz3.GetUpperBound(1)) As Double Dim Matriz2(Matriz3.GetUpperBound(0), Matriz3.GetUpperBound(1)) As Double

'Creamos la matriz inversa Dim MatrizInversa(Matriz1.GetUpperBound(0), Matriz1.GetUpperBound(1)) As Double

'Declaración de variables auxiliares Dim i, j, k As Short Dim factor As Double

'Copia de la matriz original For i = 0 To Matriz1.GetUpperBound(0) For j = 0 To Matriz1.GetUpperBound(0) Matriz1(i, j) = Matriz3(i, j)

10

Page 25: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

TRATAMIENTO GEOMÉTRICO

BENJAMÍN ARIAS PÉREZ PROCESAMIENTO DIGITAL DE IMÁGENES

Next Next

'Matriz de Paso inicial = Matriz Identidad (todo ceros excepto la diagonal formada por "unos")

For i = 0 To MatrizInversa.GetUpperBound(0) Matriz2(i, i) = 1 Next

'Se diagonaliza la matriz original y se aplican las mismas operaciones a la matriz de paso For j = 0 To Matriz1.GetUpperBound(0) For i = 0 To Matriz1.GetUpperBound(0) If i <> j Then If Matriz1(i, j) = 0 Then GoTo CUIDADO factor = Matriz1(j, j) / Matriz1(i, j) For k = 0 To Matriz2.GetUpperBound(0) Matriz1(i, k) = Matriz1(j, k) - factor * Matriz1(i, k) Matriz2(i, k) = Matriz2(j, k) - factor * Matriz2(i, k) NextCUIDADO: End If Next Next

'Se divide cada elemento de la diagonal por si mismo y se consigue: ' * En la matriz original la Matriz Identidad ' * A la derecha la matriz de Paso = Inversa de la Matriz normal For i = 0 To Matriz1.GetUpperBound(0) factor = Matriz1(i, i) 'En la matriz original sólo se divide la diagonal porque el resto es cero (ya es

diagonal) 'Si quieres ver cómo se modifica la matriz original activa la siguiente línea Matriz1(i, i) = Matriz1(i, i) / factor For j = 0 To Matriz1.GetUpperBound(0) MatrizInversa(i, j) = Matriz2(i, j) / factor Next

11

Page 26: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

Curso 2009-2010 Herramientas Informáticas

Geotecnologías Cartográficas en Ingeniería y Arquitectura para el Geoprocesado

Next

'Es necesario esta sentencia para que la función devuelva la matriz calculada Return MatrizInversa

End Function

Ejemplo de uso:

Dim A(2, 2) As Double

A(0, 0) = 2 : A(0, 1) = 3 : A(0, 2) = 2 A(1, 0) = 4 : A(1, 1) = 1 : A(1, 2) = 5 A(2, 0) = 3 : A(2, 1) = 3 : A(2, 2) = 1

Dim R_Inv As Double(,) = Inversa(A)

Dim Identidad As Double(,) = Producto(A, R_Inv)

2.5.2.- Cálculo de los parámetros y remuestreo

En primer lugar debes incluir en la sección de Declaraciones del formulario la definición de la estructura Punto:

Public Structure Punto Dim X As Double Dim Y As Double End Structure

Inserta el siguiente código en una nueva opción del menú Transformaciones llamada Proyectiva. Utiliza para probarlo la imagen Malla.bmp. Recuerda que debes abrir la imagen y luego cargar la matriz.

12

Page 27: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

TRATAMIENTO GEOMÉTRICO

BENJAMÍN ARIAS PÉREZ PROCESAMIENTO DIGITAL DE IMÁGENES

Dim Origen(3), Destino(3) As Punto

Origen(0).X = 50 Origen(0).Y = 50

Origen(1).X = 390 Origen(1).Y = 50

Origen(2).X = 390 Origen(2).Y = 440

Origen(3).X = 50 Origen(3).Y = 440

Destino(0).X = 64 Destino(0).Y = 66

Destino(1).X = 296 Destino(1).Y = 120

Destino(2).X = 401 Destino(2).Y = 441

Destino(3).X = 27 Destino(3).Y = 462

'Declaración de matrices Dim A(Origen.GetUpperBound(0) * 2 + 1, Origen.GetUpperBound(0) * 2 + 1) As Double Dim L(Origen.GetUpperBound(0) * 2 + 1, 0) As Double

'Declaración de variables auxiliares Dim i, j As Short

'Matriz de diseño For i = 0 To Origen.GetUpperBound(0) 'Primera fila A(2 * i, 0) = (Origen(i).X)

13

Page 28: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

Curso 2009-2010 Herramientas Informáticas

Geotecnologías Cartográficas en Ingeniería y Arquitectura para el Geoprocesado

A(2 * i, 1) = (Origen(i).Y) A(2 * i, 2) = 1 A(2 * i, 3) = 0 A(2 * i, 4) = 0 A(2 * i, 5) = 0 A(2 * i, 6) = -(Origen(i).X) * (Destino(i).X) A(2 * i, 7) = -(Origen(i).Y) * (Destino(i).X)

'Segunda fila A(2 * i + 1, 0) = 0 A(2 * i + 1, 1) = 0 A(2 * i + 1, 2) = 0 A(2 * i + 1, 3) = (Origen(i).X) A(2 * i + 1, 4) = (Origen(i).Y) A(2 * i + 1, 5) = 1 A(2 * i + 1, 6) = -(Origen(i).X) * (Destino(i).Y) A(2 * i + 1, 7) = -(Origen(i).Y) * (Destino(i).Y) Next

'Matriz de términos independientes For i = 0 To Origen.GetUpperBound(0) L(2 * i, 0) = Destino(i).X L(2 * i + 1, 0) = Destino(i).Y Next

'Cálculo de parámetros Dim N As Double(,) = Producto(Transpuesta(A), A) Dim N_inv As Double(,) = Inversa(N) Dim T As Double(,) = Producto(Transpuesta(A), L) Dim X As Double(,) = Producto(N_inv, T)

Dim Rojo, Verde, Azul As Byte Dim bmp As New Bitmap(Matriz.GetUpperBound(0) * 2, Matriz.GetUpperBound(1) * 2)

Dim img As Image img = CType(bmp, Image) PictureBox2.Image = img

14

Page 29: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

TRATAMIENTO GEOMÉTRICO

BENJAMÍN ARIAS PÉREZ PROCESAMIENTO DIGITAL DE IMÁGENES

Panel2.AutoScrollMinSize = PictureBox2.Image.Size PictureBox2.Refresh()

For i = 0 To Matriz.GetUpperBound(0) For j = 0 To Matriz.GetUpperBound(1) Rojo = Matriz(i, j).R Verde = Matriz(i, j).G Azul = Matriz(i, j).B Dim X_Dest, Y_Dest As Short X_Dest = (X(0, 0) * i + X(1, 0) * j + X(2, 0)) / (X(6, 0) * i + X(7, 0) * j + 1) Y_Dest = (X(3, 0) * i + X(4, 0) * j + X(5, 0)) / (X(6, 0) * i + X(7, 0) * j + 1) bmp.SetPixel(X_Dest + 100, Y_Dest + 100, Color.FromArgb(Rojo, Verde, Azul)) Next 'Esto es solo para que se refresque línea a línea img = CType(bmp, Image) PictureBox2.Image = img PictureBox2.Refresh() Next

Me.Refresh()

15

Page 30: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

Curso 2009-2010 Herramientas Informáticas

Geotecnologías Cartográficas en Ingeniería y Arquitectura para el Geoprocesado

Índice del tema

2.1. Introducción...............................................................................................................................................1

2.2. Translación................................................................................................................................................2

2.3. Escala.........................................................................................................................................................3

2.4. Sentido Inverso..........................................................................................................................................4

2.5. Transformación proyectiva........................................................................................................................6

16

Page 31: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

TTRABAJORABAJO CONCON M MAPASAPAS DEDE B BITSITS

3.1. - Introducción

Hasta ahora hemos trabajado con los píxeles como unidad de procesamiento. En este tema vamos a utilizar los mapas de bits como unidad de procesamiento geométrico (y radiométrico) de las imágenes.

Para todas las funciones que veamos en este tema debes implementar una nueva opción en el menú principal y llámala Mapa de bits.

Las funciones que vayas generando en este tema deben estar dentro nuevos submenús de Mapa de bits.

Por otro lado, las funciones de este tema no van a utilizar la matriz empleada en los temas anteriores, luego sólo será necesario abrir una imagen para poder aplicarlas, no siendo necesario cargar la matriz.

3.2.- Rotación con la clase Image

En primer lugar vamos a efectuar la única transformación que tiene la clase Image. Se trata de la rotación y se accede a ella a través de la función RotateFlip. Un ejemplo de llamada a esta función puede ser:

PictureBox1.Image.RotateFlip(RotateFlipType.Rotate180FlipX) PictureBox1.Refresh()

La enumeración RotateFlipType admite los siguientes miembros:

Nombre de Miembro DescripciónRotateNoneFlipNone Indica que no hay ni giro ni volteo.Rotate90FlipNone Indica un giro de 90 grados sin volteo.Rotate180FlipNone Indica un giro de 180 grados sin volteo.Rotate270FlipNone Indica un giro de 270 grados sin volteo.

1

Page 32: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

CURSO 2009-2010 HERRAMIENTAS INFORMÁTICAS

GEOTECNOLOGÍAS CARTOGRÁFICAS EN INGENIERÍA Y ARQUITECTURA PARA EL GEOPROCESADO

RotateNoneFlipX Indica que no hay giro, seguido por un volteo horizontal.Rotate90FlipX Indica un giro de 90 grados seguido por un volteo horizontal.Rotate180FlipX Indica un giro de 180 grados seguido por un volteo horizontal.Rotate270FlipX Indica un giro de 270 grados seguido por un volteo horizontal.RotateNoneFlipY Indica que no hay giro, seguido por un volteo vertical.Rotate90FlipY Indica un giro de 90 grados seguido por un volteo vertical.Rotate180FlipY Indica un giro de 180 grados seguido por un volteo vertical.Rotate270FlipY Indica un giro de 270 grados seguido por un volteo vertical.RotateNoneFlipXY Indica que no hay giro, seguido por un volteo horizontal y vertical.Rotate90FlipXY Indica un giro de 90 grados seguido por un volteo horizontal y vertical.Rotate180FlipXY Indica un giro de 180 grados seguido por un volteo horizontal y vertical.Rotate270FlipXY Indica un giro de 270 grados seguido por un volteo horizontal y vertical.

3.3.- El objeto Graphics

Vamos a utilizar una serie de funciones implementadas en el objeto Graphics y aplicar su método DrawImage para realizar las transformaciones.

3.3.1.- Translación

Dim G As Graphics Dim bmp As New Bitmap(1000, 1000)

Dim img As Image img = CType(bmp, Image) PictureBox2.Image = img

G = Graphics.FromImage(bmp)

'Borra la Matriz de transformación G.ResetTransform()

G.TranslateTransform(50, 50)

G.DrawImage(PictureBox1.Image, New PointF(0, 0)) 'Se necesita inicializar la propiedad AutoScrollMinSize con el tamaño de la imagen

para poder mostrar los Scrolls Panel2.AutoScrollMinSize = PictureBox2.Image.Size

3.3.2.- Escala

Dim G As Graphics Dim bmp As New Bitmap(1000, 1000)

2

Page 33: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

TRABAJO CON MAPAS DE BITS

BENJAMÍN ARIAS PÉREZ PROCESAMIENTO DIGITAL DE IMÁGENES

Dim img As Image img = CType(bmp, Image) PictureBox2.Image = img

G = Graphics.FromImage(bmp)

'Borra la Matriz de transformación G.ResetTransform()

G.ScaleTransform(4, 4)

G.DrawImage(PictureBox1.Image, New PointF(0, 0))

'Se necesita inicializar la propiedad AutoScrollMinSize con el tamaño de la imagen para poder mostrar los Scrolls

Panel2.AutoScrollMinSize = PictureBox2.Image.Size

3.3.3.- Giro

Dim G As Graphics Dim bmp As New Bitmap(1000, 1000)

Dim img As Image img = CType(bmp, Image) PictureBox2.Image = img

G = Graphics.FromImage(bmp)

'Borra la Matriz de transformación G.ResetTransform()

G.RotateTransform(45)

G.DrawImage(PictureBox1.Image, New PointF(150, 50))

'Se necesita inicializar la propiedad AutoScrollMinSize con el tamaño de la imagen para poder mostrar los Scrolls

Panel2.AutoScrollMinSize = PictureBox2.Image.Size

3

Page 34: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

CURSO 2009-2010 HERRAMIENTAS INFORMÁTICAS

GEOTECNOLOGÍAS CARTOGRÁFICAS EN INGENIERÍA Y ARQUITECTURA PARA EL GEOPROCESADO

3.3.4.-Combinación de operaciones geométricas

Se pueden combinar las operaciones anteriores de la siguiente forma:

Dim G As Graphics Dim bmp As New Bitmap(1000, 1000)

Dim img As Image img = CType(bmp, Image) PictureBox2.Image = img

G = Graphics.FromImage(bmp)

'Borra la Matriz de transformación G.ResetTransform()

G.TranslateTransform(50, 50) G.ScaleTransform(4, 4) G.RotateTransform(45)

G.DrawImage(PictureBox1.Image, New PointF(150, 50))

'Se necesita inicializar la propiedad AutoScrollMinSize con el tamaño de la imagen para poder mostrar los Scrolls

Panel2.AutoScrollMinSize = PictureBox2.Image.Size

3.4.-Drawing2D.Matrix

Ahora vamos a ver las posibilidades que ofrece Drawing2D.Matrix. La Transformación Afín implica geométricamente un giro, dos factores de escala (uno para cada eje de coordenadas) y una translación. Estos cinco parámetros se pueden agrupar en una matriz que proporciona un namespace llamado Drawing2D, que precisamente recibe el nombre de Matrix. Según la documentación proporcionada por MSDN corresponde a:

100

2221

1211

OffsetYOffsetXmmmm

Los términos de esta matriz corresponde a:

• Los términos mij engloban el giro y los dos factores de escala.• OffsetX y OffsetY, representan los valores de traslación.• La última columna (0,0,1)T corresponde con la Transformación Afín (ver contenido de la asignatura

Procesamiento Avanzado de Imágenes Digitales). Si los dos elementos nulos no lo fueran estaríamos ante una Transformación Proyectiva.

4

Page 35: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

TRABAJO CON MAPAS DE BITS

BENJAMÍN ARIAS PÉREZ PROCESAMIENTO DIGITAL DE IMÁGENES

3.4.1.-Translación

Dim G As Graphics Dim bmp As New Bitmap(1000, 1000)

Dim img As Image img = CType(bmp, Image) PictureBox2.Image = img

G = Graphics.FromImage(bmp)

'Borra la Matriz de transformación G.ResetTransform()

Dim TAfin As New Drawing2D.Matrix

TAfin.Translate(50, 25)

G.Transform = TAfin

G.DrawImage(PictureBox1.Image, New PointF(0, 0))

'Se necesita inicializar la propiedad AutoScrollMinSize con el tamaño de la imagen para poder mostrar los Scrolls

Panel2.AutoScrollMinSize = PictureBox2.Image.Size

3.4.2.-Escala

Dim G As Graphics Dim bmp As New Bitmap(1000, 1000)

Dim img As Image img = CType(bmp, Image) PictureBox2.Image = img

G = Graphics.FromImage(bmp)

'Borra la Matriz de transformación G.ResetTransform()

Dim TAfin As New Drawing2D.Matrix

TAfin.Scale(2, 3)

G.Transform = TAfin

G.DrawImage(PictureBox1.Image, New PointF(0, 0))

'Se necesita inicializar la propiedad AutoScrollMinSize con el tamaño de la imagen para poder mostrar los Scrolls

Panel2.AutoScrollMinSize = PictureBox2.Image.Size

5

Page 36: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

CURSO 2009-2010 HERRAMIENTAS INFORMÁTICAS

GEOTECNOLOGÍAS CARTOGRÁFICAS EN INGENIERÍA Y ARQUITECTURA PARA EL GEOPROCESADO

3.4.3.-Giro

Dim G As Graphics Dim bmp As New Bitmap(1000, 1000)

Dim img As Image img = CType(bmp, Image) PictureBox2.Image = img

G = Graphics.FromImage(bmp)

'Borra la Matriz de transformación G.ResetTransform()

Dim TAfin As New Drawing2D.Matrix

TAfin.Rotate(30)

G.Transform = TAfin

G.DrawImage(PictureBox1.Image, New PointF(0, 0)) 'Se necesita inicializar la propiedad AutoScrollMinSize con el tamaño de la imagen

para poder mostrar los Scrolls Panel2.AutoScrollMinSize = PictureBox2.Image.Size

3.4.4.-Transformación Afín

Dim G As Graphics Dim bmp As New Bitmap(1000, 1000)

Dim img As Image img = CType(bmp, Image) PictureBox2.Image = img

G = Graphics.FromImage(bmp)

'Borra la Matriz de transformación G.ResetTransform()

Dim TAfin As New Drawing2D.Matrix

TAfin.Translate(50, 25) TAfin.Scale(2, 3) TAfin.Rotate(30) G.Transform = TAfin

G.DrawImage(PictureBox1.Image, New PointF(0, 0))

'Se necesita inicializar la propiedad AutoScrollMinSize con el tamaño de la imagen para poder mostrar los Scrolls

Panel2.AutoScrollMinSize = PictureBox2.Image.Size

6

Page 37: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

TRABAJO CON MAPAS DE BITS

BENJAMÍN ARIAS PÉREZ PROCESAMIENTO DIGITAL DE IMÁGENES

3.5.-Interpolación

El namespace Drawing2D ofrece varias formas de interpolación, que corresponden con la enumeración InterpolationMode.

Nombre de miembro Descripción

Bicubic Especifica interpolación bicúbica. No se ha aplicado ningún filtro previo. Este modo no es adecuado para comprimir una imagen hasta por debajo de un 25% de su tamaño original.

Bilinear Especifica interpolación bilineal. No se ha aplicado ningún filtro previo. Este modo no es adecuado para comprimir una imagen hasta por debajo de un 50% de su tamaño original.

Default Especifica el modo predeterminado.

High Especifica interpolación de calidad alta.

HighQualityBicubic Especifica una interpolación bicúbica de gran calidad. Se aplica un filtro previo para garantizar una compresión de gran calidad. Este modo genera imágenes transformadas de la más alta calidad.

HighQualityBilinear Especifica una interpolación bilineal de gran calidad. Se aplica un filtro previo para garantizar una compresión de gran calidad.

Invalid Equivalente al elemento Invalid de la enumeración QualityMode.

Low Especifica interpolación de calidad baja.

NearestNeighbor Especifica interpolación de elemento más cercano.

Un ejemplo de uso de esta función (inserta el código antes de llamar a la función DrawImage):

G.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic

7

Page 38: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

CURSO 2009-2010 HERRAMIENTAS INFORMÁTICAS

GEOTECNOLOGÍAS CARTOGRÁFICAS EN INGENIERÍA Y ARQUITECTURA PARA EL GEOPROCESADO

3.6.-ColorMatrix

Es posible manejar radiométricamente un mapa de bits a través de ColorMatrix. Se trata de una matriz de 5x5 que contiene los pesos para tratar los colores Rojo, Verde, Azul, Transparencia y un valor w (por este orden). Con los siguientes ejemplos queda bastante claro su uso.

3.6.1.-Transparencia

With OpenFileDialog1 .Filter = "Ficheros BMP|*.bmp" & _ "|Ficheros GIF|*.gif" & _ "|Ficheros JPG o JPEG|*.jpg;*.jpeg" & _ "|Ficheros PNG|*.png" & _ "|Ficheros TIFF|*.tif" .FilterIndex = 1

If (.ShowDialog() = Windows.Forms.DialogResult.OK) Then Dim G As Graphics

Dim bmp As New Bitmap(1000, 1000)

Dim img As Image

img = CType(bmp, Image) PictureBox2.Image = img

'Esto asigna el Image pero no dibuja la imagen Dim imgOriginal As Image = Image.FromFile(.FileName)

G = Graphics.FromImage(bmp)

Dim rect As New Rectangle(0, 0, 1000, 1000)

Dim imgAtr As New Imaging.ImageAttributes

'Transparencia Dim clMatriz As Imaging.ColorMatrix = New Imaging.ColorMatrix(New Single()() _ {New Single() {1, 0, 0, 0, 0}, _ New Single() {0, 1, 0, 0, 0}, _ New Single() {0, 0, 1, 0, 0}, _ New Single() {0, 0, 0, 0.5, 0}, _ New Single() {0, 0, 0, 0, 1}})

imgAtr.SetColorMatrix(clmatriz)

G.DrawImage(imgOriginal, rect, 0, 0, 1000, 1000, GraphicsUnit.Pixel, imgAtr)

'Se necesita inicializar la propiedad AutoScrollMinSize con el tamaño de la imagen para poder mostrar los Scrolls

Panel2.AutoScrollMinSize = PictureBox2.Image.Size End If

End With

8

Page 39: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

TRABAJO CON MAPAS DE BITS

BENJAMÍN ARIAS PÉREZ PROCESAMIENTO DIGITAL DE IMÁGENES

3.6.2.-De color a niveles de gris

With OpenFileDialog1 .Filter = "Ficheros BMP|*.bmp" & _ "|Ficheros GIF|*.gif" & _ "|Ficheros JPG o JPEG|*.jpg;*.jpeg" & _ "|Ficheros PNG|*.png" & _ "|Ficheros TIFF|*.tif" .FilterIndex = 1

If (.ShowDialog() = Windows.Forms.DialogResult.OK) Then

Dim G As Graphics

Dim bmp As New Bitmap(1000, 1000)

Dim img As Image

img = CType(bmp, Image) PictureBox2.Image = img

'Esto asigna el Image pero no dibuja la imagen Dim imgOriginal As Image = Image.FromFile(.FileName)

G = Graphics.FromImage(bmp)

Dim rect As New Rectangle(0, 0, 1000, 1000)

Dim imgAtr As New Imaging.ImageAttributes

'Conversión a escala de gris Dim clmatriz As Imaging.ColorMatrix = New Imaging.ColorMatrix(New Single()() _ {New Single() {0.299, 0.299, 0.299, 0, 0}, _ New Single() {0.587, 0.587, 0.587, 0, 0}, _ New Single() {0.114, 0.114, 0.114, 0, 0}, _ New Single() {0, 0, 0, 1, 0}, _ New Single() {0, 0, 0, 0, 1}})

imgAtr.SetColorMatrix(clmatriz)

G.DrawImage(imgOriginal, rect, 0, 0, 1000, 1000, GraphicsUnit.Pixel, imgAtr)

'Se necesita inicializar la propiedad AutoScrollMinSize con el tamaño de la imagen para poder mostrar los Scrolls

Panel2.AutoScrollMinSize = PictureBox2.Image.Size End If

End With

9

Page 40: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

CURSO 2009-2010 HERRAMIENTAS INFORMÁTICAS

GEOTECNOLOGÍAS CARTOGRÁFICAS EN INGENIERÍA Y ARQUITECTURA PARA EL GEOPROCESADO

3.7.-Scan0

Para terminar con la implementación de código, vamos a ver una última forma de trabajar con imágenes en VB.NET a través de funciones que gestionan punteros y bloques de memoria. Es sólo un primer paso que os permitirá, si continuáis por esta línea, trabajar de forma muy eficiente con imágenes de gran tamaño.

'Crea un nuevo bitmap a partir de la imagen cargada en PictureBox1 Dim bmp As New Bitmap(PictureBox1.Image)

'Define una estructura de tipo Rectangle Dim rect As New Rectangle(0, 0, bmp.Width, bmp.Height)

'Define bmpData para acceder a los datos del mapa de bits 'y bloquea el mapa de bits Dim bmpData As System.Drawing.Imaging.BitmapData = bmp.LockBits(rect, _ Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat)

'Obtiene la dirección en memoria del mapa de bits Dim ptr As IntPtr = bmpData.Scan0

'Declara un array de bytes 'Este código es específico para un bitmap de 24 bits per pixels. Dim bytes As Integer = bmpData.Stride * bmp.Height Dim rgbValues(bytes - 1) As Byte

'Copia los valores RGB en el array System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes)

'Colocamos a 100 el cuarto componente (transparencia) For i As Integer = 3 To rgbValues.Length - 1 Step 4 rgbValues(i) = 100 Next

'Copia el array en la dirección de memoria System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes)

'Desbloquea el mapa de bits bmp.UnlockBits(bmpData)

'Dibuja la imagen Dim img As Image img = CType(bmp, Image) PictureBox2.Image = img PictureBox2.Refresh()

'Se necesita inicializar la propiedad AutoScrollMinSize con el tamaño de la imagen para poder mostrar los Scrolls

Panel2.AutoScrollMinSize = PictureBox2.Image.Size

10

Page 41: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

TRABAJO CON MAPAS DE BITS

BENJAMÍN ARIAS PÉREZ PROCESAMIENTO DIGITAL DE IMÁGENES

Índice del tema

3.1. - Introducción............................................................................................................................................1 3.2.- Rotación con la clase Image....................................................................................................................1 3.3.- El objeto Graphics...................................................................................................................................2 3.4.-Drawing2D.Matrix...................................................................................................................................4 3.5.-Interpolación............................................................................................................................................7 3.6.-ColorMatrix.............................................................................................................................................8 3.7.-Scan0.....................................................................................................................................................10

11

Page 42: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

Empleo de Imágenes Piramidales

Benjamín Arias Pérez Ingeniero Técnico en Topografía

Ingeniero en Geodesia y Cartografía e-mail: [email protected]

Resumen

En el presente artículo se expone un análisis acerca de la gestión y uso de imágenes piramidales. Para ello se define un formato de imagen propio, Mapa de Bits Jerárquico, y asociado al mismo se desarrollan dos controles ActiveX: uno para la creación de las imágenes con el nuevo formato, y otro para la explotación fotogramétrica de dichas imágenes.

1.- Introducción Este artículo abarca parte de los

conocimientos adquiridos y aplicados durante la generación del Proyecto Fin de Carrera de la Ingeniería Superior en Geodesia y Cartografía, Desarrollo de Software para Fotogrametría Digital, presentado en la Escuela Politécnica Superior de Ávila, perteneciente a la Universidad de Salamanca.

El gran impedimento a la hora de trabajar en Fotogrametría Digital y la implementación de algoritmos aplicados, está derivado por un lado de la necesidad de empleo de imágenes que ocupan mucho espacio de almacenamiento, y por otro lado del manejo en memoria de estas imágenes. Sobre cualquier lenguaje de programación pensado para desarrollo de software sobre Windows, se abre una imagen de un gran tamaño con los métodos que se ponen a disposición del usuario, el proceso se puede llegar a ralentizar tanto, que es posible que se termine bloqueando el ordenador.

Entonces, el interés está en cómo manejar estas imágenes en el caso de que ocupen tanto en memoria que al ordenador le cuesta mover la imagen en pantalla. Por ello, se decidió la creación de un nuevo formato, un formato propio, o si se quiere interno, para con él manejar grandes archivos de imagen.

1.1.- Objetivos

Los objetivos que se pretenden con la definición de un nuevo formato de imagen son:

Acceso rápido a la imagen: que se pueda abrir de forma rápida (o al menos que al usuario no le parezca una eternidad).

Navegabilidad: que se pueda realizar roaming con la imagen.

Imagen índice: que haya una imagen que nos muestre en todo momento que parte

de la imagen completa es la que se está visualizando en pantalla (Overview).

Acceso fotogramétrico: esto implica que se puedan conseguir aspectos necesarios en el manejo de una imagen dentro de la disciplina de la Fotogrametría. Se refiere, e.g., al posible acceso a las coordenadas píxel del puntero del ratón en un determinado momento, cómo obtener el valor del nivel de gris. También hace referencia a la posibilidad de manejar dos imágenes a la vez para ayudar a conseguir la visión estereoscópica. O tener más de dos imágenes abiertas en caso de Aerotriangulación.

Acceso al usuario: el posible usuario de este nuevo formato de imagen debe tener acceso fácil a la imagen, su percepción del código debe ser totalmente opaca y debe limitarse a utilizar el formato como una herramienta fotogramétrica más. Ello no excluye de la posibilidad de que ciertos usuarios puedan utilizar de forma un poco más cercana este formato propio de imagen, incluyéndolo en sus posibles aplicaciones, utilizando el código ya generado, creando algoritmos alrededor de él, i.e, que haya una interacción entre el programa a generar por el usuario y el nuevo formato de imagen, pero sin que aquel pueda modificar el contenido del formato, limitándose a emplearlo. Esta última alternativa se ha empleado con éxito en dos proyectos fin de carrera.

2.- Definición del nuevo formato de imagen

El formato de imagen que se describe a continuación consiste, en lo que se refiere a la representación interna de la imagen, en el formato de mapas de bits de Windows. Este proceder se sustenta por el hecho de que generalmente se

Page 43: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

trabaja con sistemas operativos Windows, y estos sistemas tienen dicho formato gráfico. Por lo tanto, Windows proporciona un juego de funciones gráficas para emplear con su formato de imagen, BMP, que hacen posible manejar las imágenes de una manera eficiente, aunque no por ello sencilla.

El nuevo formato de imagen creado contiene varios mapas de bits, que son copias de la imagen original a diferente tamaño, y por último un bitmap que servirá de overview. Por lo tanto, se trata de una pirámide de imágenes, y por ello este formato propio de imágenes recibe el nombre de Mapa de Bits Jerárquico, y sus archivos llevarán la extensión BMJ. Además, se implementa sólo bajo una profundidad de color de 8 bits, i.e., 256 colores, por lo tanto se emplea una paleta de colores para su visualización en pantalla.

Luego el formato BMJ está formado por las siguientes partes:

La imagen original: se copia la imagen original al nuevo archivo, y se copia tal cual, con la información de cabecera de archivo, cabecera de bitmap y paleta de colores, y el mapa de bits.

Estructura BMJ: datos acerca de la estructura de este archivo, como pueden ser el número de imágenes en la pirámide, posición en el archivo de las mismas, etc. Es una pieza fundamental dentro de este archivo.

Las sucesivas imágenes a diferente tamaño: son copias a distinto tamaño de la imagen original, dividiendo sucesivamente su alto y su ancho entre 2, hasta llegar a un tamaño mínimo especificado en el código. Estas imágenes se almacenan en el archivo con la información de cabecera de archivo, cabecera de bitmap y paleta y luego el bitmap, tal y como si se trata de un archivo de mapa de bits independiente. De esta manera, el algoritmo que se encargue de la visualización tiene los datos a su disposición y no necesita del cálculo de sus datos, aspecto éste esencial porque ahorra tiempo de cálculo en la visualización.

Imagen índice: es una imagen que servirá de Overview, de apoyo en la navegación por la imagen. También se incluyen en el archivo BMJ la cabeceras, paleta y el correspondiente bitmap.

Al final del archivo se puede incluir datos acerca de la imagen, como puede ser datos de la Orientación Interna, o de la Orientación Externa.

Lo más lógico es que la información de la estructura BMJ esté al inicio del archivo, así el código que se encargara de la visualización de la imagen empieza por leerla y actuar en consecuencia. Esto no es así debido a dos causas:

La primera es debida a la implementación del código para realizar el nuevo formato a partir de un mapa de bits, pues existen una serie de inconvenientes prácticos para colocar primero la estructura BMJ y luego la imagen original tal cual.

La segunda es una causa de carácter práctico, pues si al archivo generado con extensión BMJ se le cambia dicha extensión por BMP se podrá visualizar la imagen original, aunque el archivo contenga más bytes. Esto ocurre porque para visualizar un mapa de bits, el programa que se encargue de hacerlo, lee la cabecera del archivo y la cabecera del bitmap, donde trae información acerca del tamaño, resolución, profundidad de color, etc, luego carga el bitmap en memoria y posteriormente se produce la visualización del archivo en pantalla. Luego con el resto de la información del archivo BMJ, como no se hace referencia en la cabecera del bitmap a ellos, porque no pertenece al mapa de bits original, el programa no los lee ni sabe que están ahí.

El formato creado se especifica para operaciones de lectura/escritura en binario, y la estructura se puede resumir en la siguiente figura:

Page 44: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

Imagen Original

Estructura BMJ

Imagen 1

Imagen 2

Imagen n

. . .

Otros Datos (OI, OE, ...)

Mapa de Bits Jerárquico

Imagen Índice

Figura 1.- Estructura de archivo Mapa de Bits Jerárquico.

La imagen Original, sus correspondientes imágenes piramidales, y la imagen índice, tienen cada una la estructura de archivo de mapa de bits.

3.- Escritura del formato Mapa de Bits Jerárquico

3.1.- Desarrollo del código de escritura

Para la escritura de archivos en el formato diseñado se crea un control ActiveX, que se corresponde con la creación de una clase, a modo de objeto, que recibe el nombre de Convierte. Esta clase, u objeto, tiene un miembro o función externa principal, Carga, que es la única relación que existe entre el control y el hipotético usuario. También existen otra serie de funciones y procedimientos, pero éstos son de carácter interno y son de uso exclusivo del control Convierte, por lo que el usuario de este control no tiene acceso a ellos.

La función Carga de la clase Convierte tiene tan sólo un parámetro, y además de carácter opcional. El funcionamiento externo de esta función es bastante sencillo y tan sólo debe especificarse un parámetro, si se desea, o ninguno en otro caso. Este parámetro

simplemente se trata del nombre del archivo, directorio o camino (path) inclusive, que se desea convertir al formato Mapa de Bits Jerárquico.

Luego el código de escritura del formato de imagen Mapa de Bits Jerárquico consta de las siguientes partes:

1. Gestión de archivos: tanto del archivo de entrada o lectura, como del archivo de salida o escritura.

2. Lectura del archivo de mapa de bits que se desea transformar a BMJ. En concreto se lee la cabecera de archivo y la cabecera del mapa de bits.

3. Chequeo del tipo de mapa de bits, de la profundidad de color, y de que no se trate de una imagen comprimida. Esto es así porque sólo se trabaja con un determinado tipo de BMP.

4. Obtención de información de la memoria disponible del ordenador, para actuar en consecuencia.

5. Escritura del archivo BMJ de forma simultánea a la lectura del archivo BMP.

6. Visualización de un indicador del avance en la escritura del archivo BMJ.

3.2.- Alternativas

Page 45: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

Para la selección de píxeles se estudian varias alternativas para el ahorro de tiempo, o si se quiere, para la disminución del número de operaciones a realizar. En concreto 3 alternativas, que son las siguientes:

1º. Lectura del valor del píxel en la imagen original, uno a uno, y escritura de dichos valores en el mapa de bits correspondiente a la imagen n-ésima.

2º. Lectura de ciertas filas completas de la imagen original, escritura de dichas líneas en el mapa de bits correspondiente a la imagen n-ésima. Se completa esta técnica con la visualización escalada de estas líneas.

3º. Lectura de ciertas filas completas de la imagen original, y escritura seleccionada de píxeles en el mapa de bits correspondiente a la imagen n-ésima.

La primera alternativa es la opción intuitiva, la más lógica. Se trata simplemente de ir leyendo en el mapa de bits de la imagen original los valores de los píxeles que se deseen, y su posterior escritura en el mapa de bits de la imagen n-ésima. La cadencia en la lectura viene determinada por la división n-ésima de la imagen original. De esta forma, la primera imagen se genera con uno de cada dos píxeles de la imagen original en la primera línea, luego salta a la 3ª línea para coger 1 de cada dos líneas, etc...De forma generalizada, se toma un píxel de cada 2n píxeles de la imagen original en el n-esimo escalón de la pirámide. A continuación se muestra un ejemplo de forma gráfica. Se supone la imagen original formada por 16x16 píxeles, i.e, 256 píxeles.

La primera imagen de la pirámide se forma tomando un píxel de cada dos, que como se puede ver en la imagen superior, son los píxeles marcados con X. La imagen así formada es:

que tiene 8x8 píxeles, i.e, 64 píxeles. La siguiente imagen de la pirámide se forma a partir de la original tomando un píxel de cada 4:

luego la imagen resultante es:

con 4x4 píxeles, i.e., 16 píxeles.

Esta primera alternativa implica muchas operaciones de lectura y escritura, lo que a su vez implica mucho tiempo. Por ello se piensa en otras alternativas, que se explican más adelante.

En la Figura 2 se muestra una pirámide imágenes así obtenida. La imagen inferior es la imagen original, la imagen situada en el medio es la primera imagen generada por la primera división de la original, y la superior es la imagen generada por la segunda división de la original.

Page 46: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

Figura 2.- Ejemplo de imagen piramidal según la

primera alternativa.

La estrategia de la segunda alternativa es leer una fila completa de la imagen original en cada operación de lectura, y escribir dicha fila en una sola operación de escritura en el mapa de bits de la imagen n-ésima. Se leen sólo cada 2n filas para la generación de la imagen n-ésima. Con el mismo ejemplo anterior, como se puede ver en la siguiente figura:

una imagen de 16x16 píxeles, de la que se leen las filas completas, sólo una de cada dos filas. Las filas se leen cada una en una sola operación de lectura, y se escriben en una sola operación de

escritura. Entonces la primera imagen que se almacena es:

La segunda imagen se genera con una de cada 4 filas de la imagen original:

La segunda imagen generada es:

Para visualizar las imágenes así generadas se requiere el escalado de las imágenes dentro del código de visualización (control Imagen). A continuación se muestra una pirámide de imágenes así generada:

Page 47: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

Figura 3.- Ejemplo de imagen piramidal según la segunda alternativa.

El rendimiento de esta segunda alternativa es realmente espectacular, en términos tanto de número de operaciones como de tiempo necesario para convertir una imagen en formato de mapa de bits a una imagen en formato de Mapa de Bits Jerárquico. Sin embargo, no es la alternativa más adecuada debido al efecto de huecos, píxeles negros, que se produce al escalar la imagen para su visualización. En la Figura 4 se puede comprobar este efecto. La imagen situada a la izquierda es la imagen n-ésima generada mediante la primera alternativa, y la imagen situada a la derecha es la imagen n-ésima generada por la segunda alternativa.

Debido a este inconveniente se rechaza esta alternativa, porque no ofrece garantías en la visualización debido a la función de escalado, aunque tiene un reducido coste temporal.

Figura 4.- Efecto de huecos debidos a la función de escalado.

Por lo tanto, se piensa en una tercera alternativa, que en realidad es un híbrido de las otras dos anteriores, tomando de cada una ellas sus aspectos más positivos. En primer lugar, se lee cada fila completa en una sola operación de lectura y queda cargada en una matriz. Esto

ofrece ya una cierta mejora respecto a la primera alternativa al ahorrar operaciones de lectura. La escritura en el archivo no se realiza con la fila completa, sino un píxel de cada 2n píxeles. No se reduce el número de operaciones de escritura, pero se consigue una ventaja, porque se obtienen

Page 48: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

las imágenes piramidales correctas y no es necesario un escalado posterior de la imagen.

Utilizando el mismo ejemplo que se ha usado en las otras dos alternativas, se explica a continuación esta tercera y definitiva. En primer lugar, se parte de la imagen original, y para crear la primera imagen de la pirámide se leen una de cada dos filas de forma completa:

de cada fila leída, y que está cargada en una matriz unidimensional, se seleccionan uno de cada dos píxeles para escribirlo en el mapa de bits de la primera imagen original.

y la imagen generada es la siguiente, de 8x8 píxeles:

la siguiente imagen piramidal se hace leyendo cada fila de forma completa, una de cada 4 filas, y para la escritura se selecciona uno de cada 4 píxeles:

con lo que la imagen resultante es de 4x4 píxeles:

Esta es la alternativa implementada en el control Convierte.

A continuación se muestra un estudio de los tiempos y tamaños obtenidos para poder hacer una comparación entre alternativas. Los tiempos indicados corresponden a un ordenador Pentium a 166 MHz, con 64 MB de RAM., que si bien se puede considerar hoy día como desfasado, precisamente por ello resulta más adecuado para este tipo de estudios, pues acentúa las diferencias entre alternativas.

Page 49: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

Nombre Imagen

1ª Alternativa

(segundos)

2ª Alternativa(segundos)

3ª Alternativa(segundos)

%(1ª/2ª)

%(1ª/3ª)

Edif.bmp

17 0,6 7 2.733,33

142,86

tetraedro_d.bmp

44 1,5 18 2.833,33

144,44

Fot209.bmp

162 6 64 2.600,00

153,13

Catast188208.bmp

1.875 136 723 1.278,68

159,34

Como se puede observar hay un gran rendimiento temporal con la segunda alternativa. Aún cuando con la imagen más grande de todas, Catast188208.bmp, baja el rendimiento, sigue siendo una mejora espectacular. Con la alternativa definitiva, la tercera, se mejora el tiempo en buena

medida, en más de la mitad, e incluso la relación mejora con el tamaño de la imagen. Los tamaños van de menor tamaño, Edif.bmp, a mayor tamaño, Catast188208.bmp. El siguiente gráfico ayuda a ver las diferencias temporales:

0

200

400

600

800

1000

1200

1400

1600

1800

2000

1 2 3 4

Tie

mpo

en

segu

ndos

1ª Alternativa

2ª Alternativa

3ª Alternativa

Figura 6.- Diagrama de barras con estudio comparativo de tiempos.

donde los números se corresponden con la numeración de la siguiente forma:

Edif.bmp: se corresponde con 1.

tetraedro_d.bmp: se corresponde con 2.

Foto209.bmp: se corresponde con 3.

Catast188208.bmp: se corresponde con 4.

Una vez elegida la alternativa, se hizo un estudio de tamaños entre las imágenes originales los archivos BMJ obtenidos. Los datos se muestran en la siguiente tabla:

Nombre Imagen

Tamaño Imagen % Aumento

Page 50: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

Tamaño Imagen BMP (Bytes)

BMJ (Bytes)

Edif.bmp

692.224

958.464 38,46

tetraedro_d.bmp

2.109.440

2.801.664 32,82

Fot209.bmp

7.114.752

9.486.336 33,33

Catast188208.bmp

108.234.752 144.324.608 33,34

Como se puede observar la relación de aumento entre ambos archivos se mantiene en torno a un 33-34%, excepto el primero que es de 38.46%.

0

20.000.000

40.000.000

60.000.000

80.000.000

100.000.000

120.000.000

140.000.000

160.000.000

1 2 3 4

Byt

es A

lmac

enam

ient

o

Tamaño BMP

Tamaño BMJ

Figura 8.- Diagrama de barras con estudio comparativo de tamaños

4.- Desarrollo del código de lectura

El código de lectura se implementa sobre un Control ActiveX, en forma de Control de Usuario, y que recibe el nombre de Imagen. Por lo tanto, las características iniciales son similares al control Convierte, que es el control generado para la escritura del formato BMJ. Sin embargo, el control Imagen presenta más propiedades, métodos y elementos que el control Convierte.

4.1.- Gestión de archivos

La función del control Imagen para visualizar los archivos BMJ recibe el nombre de

Carga, y se puede llamar de forma externa al control Imagen. Esta función puede recibir dos parámetros:

nImagen: un número identificador de la imagen. Se define como de tipo Byte, luego su rango de valores se encuentra en 0 y 255 en números enteros.

NombreArchivo: el nombre del archivo que contiene el archivo BMJ. Este parámetro es opcional, por lo que su omisión ocasiona que aparezca una ventana para que el usuario elija el archivo BMJ que desea visualizar.

El parámetro nImagen es el que sirve de identificador en todo el código, por lo tanto es un elemento indispensable dentro del código del control Imagen. Tanto es así, que todas las propiedades, métodos y elementos hacen

Page 51: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

referencia a este identificador, por lo que la primera operación en aquellos es obtener el identificador de la imagen.

El parámetro NombreArchivo es el nombre del archivo más la ruta de directorios donde se encuentra. Es opcional, por lo que su omisión genera la presentación en pantalla de una ventana a modo de cuadro de diálogo, donde el usuario puede elegir el archivo de tipo Mapa de Bits Jerárquico que desea abrir. En el caso de que el usuario pulse Cancelar en esta ventana, se muestra un mensaje indicando que el usuario ha decidido Cancelar la acción, por lo que no se abrirá ninguna imagen.

La función Carga del control Imagen devuelve una variable boolena, y de esta forma se puede controlar si se ha producido un error en la visualización de la imagen. Si la función devuelve Verdadero se considera que no se producido ningún error en la visualización de la imagen. En cambio, si la función, una vez ejecutada, devuelve Falso, significa que ha habido algún error en la visualización.

4.2.- Lectura del archivo BMJ

Se pueden distinguir dos tipos de lecturas del archivo BMJ, dependiendo de cuándo se realice la lectura:

Lectura inicial: se realiza mediante la función Carga, de forma externa al Control Imagen. Esta lectura está gestionada por dicha función.

Lectura en tiempo de ejecución: se realiza de forma interna desde el Control Convierte, en respuesta a los eventos que pueda generar el usuario. Esta lectura no está gestionada por la función Carga.

La lectura inicial, gestionada por la función Carga, sigue los siguientes pasos:

1. Lectura de la cabecera del archivo y de la cabecera del mapa de bits.

2. Redimensionamiento de una matriz que almacenará los valores del mapa de bits que se van a cargar.

3. Almacenamiento del mapa de bits en la matriz redimensionada.

4. Preparación de las estructuras adecuadas para que puedan ser admitidas por las funciones de visualización.

5. Envío de las estructuras a las funciones de visualización.

Como ya se ha explicado anteriormente, el formato de archivo BMJ se fundamenta en el formato BMP, y éste está pensado para facilitar su visualización en Windows. Es por ello que las funciones que se utilizan para mostrar una imagen en pantalla admiten como parámetros las estructuras que existen dentro del formato BMP, éstas están contenidas en el archivo del formato BMP, y también están contenidas dentro del archivo de extensión BMJ.

Por lo tanto en la lectura de un archivo BMJ se pueden hablar de dos tipos de acciones, independientemente de si se trata de la lectura inicial o de la lectura en tiempo de ejecución:

Lectura propiamente dicha: se leen los valores correspondientes al formato y se almacenan en las variables adecuadas.

Preparación de la visualización: para ello se cargan los valores necesarios en variables que sean acordes con:

- las estructuras admitidas por las funciones de visualización

- la parte de la imagen que se desea mostrar

- la imagen que corresponda dentro de la pirámide de imágenes.

Las estructuras adecuadas para la visualización son la cabecera de mapa de bits (BITMAPINFOHEADER), la paleta de colores(RGBQUAD), y el mapa de bits propiamente dicho.

4.3- Pasos para mostrar un mapa de bits

Los pasos que hay que realizar para poder presentar un mapa de bits en pantalla, o si se quiere en cualquier otro dispositivo son los siguientes:

1. Obtención del bitmap

2. Creación de un contexto de dispositivo de memoria

3. Selección del bitmap en este último contexto de dispositivo.

4. Copia desde dicho contexto al dispositivo que se vaya a utilizar para su visualización.

5. Eliminación del contexto de dispositivo creado en el paso 2.

6. Eliminación del mapa de bits cuando se hay finalizado con él.

4.4.- Visualización de una parte de la imagen

Page 52: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

La zona de la imagen que se desea mostrar está determinada en todo momento por las acciones que el usuario considere conveniente realizar, por lo que la navegación por la imagen es controlada por el usuario. La zona de la imagen que se desea mostrar corresponde entonces con:

las coordenadas X, Y, del origen de la zona de la imagen.

el ancho y el alto de la ventana de visualización.

la imagen correspondiente dentro de la pirámide de imágenes.

el identificador de la imagen BMJ.

Estos valores son los que se determinan que zona de la imagen se visualiza, y estos valores son determinados en todo momento.

Conviene recordar la estructura del archivo BMJ, que por este orden tiene los siguientes elementos:

Imagen Original.

Estructura BMJ.

Pirámide de imágenes.

Imagen Índice.

Datos relativos a Orientaciones.

También conviene recordar la forma de un archivo BMP, que por orden está formado por:

Cabecera de archivo.

Cabecera del mapa de bits.

Paleta de colores.

Mapa de bits.

Por último recordar los conceptos de scan line, número de bytes necesario para representar una línea, e ídem del mapa de bits completo. Y sobre todo, es interesante refrescar ahora la estructura secuencial del mapa de bits.

La pregunta ahora es: ¿cómo se visualiza una zona de la imagen? La respuesta a esta cuestión es la pieza clave dentro de este Proyecto Fin de Carrera. La visualización de una zona de la imagen tiene varios pasos, y éstos son los siguientes:

1. En primer lugar, mediante el identificador de la imagen BMJ, se accede a la imagen BMJ correspondiente de las varias que es posible tener abiertas.

2. Después, se accede a la imagen n-ésima dentro de la pirámide.

3. Con las coordenadas X, Y del origen de la zona de la imagen, se accede dentro del

mapa de bits correspondiente al primer píxel.

4. Mediante el ancho y el alto de la zona a visualizar se leen los valores del mapa de bits correspondientes.

5. Se siguen los pasos necesarios para mostrar un mapa de bits en pantalla.

Los tres primeros pasos son de gestión de archivos. El primer paso se trata de saber sobre que archivo hay que efectuar la lectura. El segundo y tercer paso, acceden al primer píxel a visualizar, teniendo para ello en cuenta los valores almacenados en la estructura BMJ y las coordenadas del origen.

La estructura BMJ es:

Public Type BitMapJerarquico

Tipo As Byte

nBitmap As Byte

posBitmap() As Long

posDatos As Long

End Type

El miembro posBitmap(n) permite, dentro del archivo BMJ, acceder a la posición de inicio de la imagen n-ésima. A continuación se accede al inicio del mapa de bits de dicha imagen mediante el miembro bfOffBits de la estructura BITMAPFILEHEADER.

La siguiente acción será acceder a la píxel de inicio de la zona a visualizar mediante las coordenadas del origen. Sin embargo, debido a la configuración bottom-up del mapa de bits, por la que la imagen aparece invertida en el orden de sus filas, realmente se accede a la esquina inferior izquierda, en lugar de a la esquina superior izquierda, donde es norma común colocar el origen de coordenadas en una imagen digital.

Una vez que se accede a la esquina inferior izquierda, se lee por filas sólo el ancho a visualizar, con lo que la imagen que se carga en memoria es exclusivamente la que se desea visualizar. Para aclarar esta idea conviene observar la figura bajo estas líneas. Representa la imagen completa, y los píxeles marcados con una X son los correspondientes a la zona a visualizar. Pues la estrategia se basa en que se carga en memoria sólo la zona de la imagen a visualizar, y no toda la imagen.

Para visualizar una zona de la pantalla, se deben asignar valores a las estructuras del

Page 53: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

formato BMP para poder pasadas a las funciones de visualización. Por lo tanto, para cada zona de la imagen que se presente en pantalla es necesario modificar los siguientes miembros de la estructura BITMAPINFOHEADER:

biWidth: es el ancho de la zona a mostrar.

biHeight: es el alto de la zona a mostrar.

biSizeImage: tamaño del mapa de bits en bytes.

5.- Descripción de funcionalidades

En este apartado se describen de forma breve algunas de las funcionalidades del control Imagen, entendidas como propiedades, métodos y elementos que articulan las acciones del usuario hacia el control Imagen en tiempo de ejecución

Las restantes funcionalidades se explican en los capítulos posteriores, pues necesitan de explicaciones adicionales

Junto con la ventana que muestra la visualización en pantalla de la imagen también se han diseñado las siguientes ventanas:

Imagen Índice.

Zoom.

Factor de Zoom.

Paleta.

Histograma.

A continuación se describen estas ventanas, para qué sirven y cómo se implementan. Sin embargo, antes se detallarán las funciones de la ventana de Visualización.

Las opciones que se permiten son las siguientes:

Imagen Índice: visualiza la Imagen Índice.

Zoom +: si en el momento de ejecutar este comando la zona de la imagen mostrada corresponde a la imagen n-ésima de la pirámide, visualiza la zona de la imagen correspondiente a la imagen inmediatamente superior en cuanto a tamaño, i.e., la imagen (n-1)-ésima. Si no hay imagen superior se muestra el siguiente mensaje, y para seguir aumentando en tamaño es necesario hacer uso del comando Hacer Zoom.

Zoom -: si en el momento de ejecutar este comando la zona de la imagen mostrada corresponde a la imagen n-ésima, visualiza la zona de la imagen correspondiente a la imagen inmediatamente inferior en cuanto a tamaño, i.e., la imagen (n+1)-ésima de la pirámide. Si no hay imagen inferior se muestra el siguiente mensaje:

Hacer Zoom: permite realizar un Zoom de la imagen

Paleta: permite modificar la tabla de colores.

Anaglifo: permite mostrar el anaglifo de dos imágenes.

Roaming: Permite realizar el denominado Roaming, y además de dos formas, bien por medio de movimientos del ratón o bien por acción de la rueda superior del ratón.

Visión Estereoscópica: se consigue con la ayuda de un estereóscopo. Además, permite visualizar las marcas flotantes, moverlas de forma conjunta o independiente, y otras aplicaciones fotogramétricas.

Coordenadas Píxel: permite ver las Coordenadas Instrumentales en tiempo real. Se visualizan al lado del puntero del ratón, como se puede ver:

Page 54: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

Fotocoordenadas: permite ver las Fotocoordenadas en tiempo real. Se visualizan al lado del puntero del ratón.

Nivel Digital: permite ver el Nivel Digital del píxel sobre el que se sitúa el puntero del ratón.

Histograma: permite visualizar el histograma de la imagen

Orientación Interna: permite ver, introducir y modificar los parámetros de Orientación Interna de la imagen.

Orientación Externa: permite ver, introducir y modificar los parámetros de Orientación Externa de la imagen.

Focal cámara: permite ver, introducir y modificar la distancia focal de la cámara con la que se ha obtenido la imagen.

6.- Conclusiones Las ventajas de un desarrollo de formato propio de imagen para poder así manejar la imagen se pueden determinar como las siguientes:

Acceso a la imagen: en varias de sus vertientes. Se puede decir acceso directo a los píxeles que forman la imagen, a nivel de posición (geométrico) y a nivel de colores (radiométrico). También acceso a su tamaño, a su resolución, etc...

Manejabilidad de la imagen: si se puede mostrar en pantalla sólo partes de la imagen, si se puede hacer roaming con ella, etc..

Los inconvenientes de desarrollar un formato propio de imagen se podría decir que son los menos, pero no por ello carecen de importancia:

Desarrollo de software específico para poder manejar el formato de imagen a crear.

Desarrollo propio del formato, y de su implementación algorítmica.

Se deberá incorporar un paso previo en las aplicaciones que utilicen este formato para poder realizar una transformación del formato original al formato que se pretende realizar.

Otro formato gráfico más: esto enlaza con la idea de caos que se puede percibir en el mundo la informática gráfica, donde cada nuevo programa tiene su propio formato.

6.- Bibliografía

CHARTE, F., CLAVIJO, J.A., DE ANTONIO, A., PASCUAL, J., SEGARRA, M.J., Programación avanzada en Windows 2000, Ed. McGraw-Hill, 2000, Madrid.

GONZÁLEZ, R., WOODS, R., Digital image processing, Addison-Wesley Publishing Company, 1992. (Edición en castellano).

KRAUS, K., Photogrammetry, Ferd. Dümmlers Verlag.Bonn.

Volumen I: Fundamentals an Standard Processes, 4ª ed., 1993.

Volumen II: Advanced Methods and Applications, 4ª ed., 1997.

RICHTER, J., Programación avanzada en Windows, Ed. McGraw-Hill, 1997, Madrid.

WOLF, P. R., Elements of Photogrammetry, with air photo interpretation and remote sensing, 2ª ed., McGraw-Hill, 1983, New York.

Page 55: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

79

5.- LECTURA Y ESCRITURA DEL FORMATO MAPA DE BITS JERÁRQUICO

5.1.- Introducción

En los capítulos anteriores se expusieron las razones de la conveniencia del diseño de un nuevo formato propio de imagen, y además la forma de hacerlo. En este capítulo se trata de explicar la implementación del código de lectura y escritura de dicho formato. Por lo tanto, según se desprende de lo anterior, se puede subdividir el trabajo en dos partes diferenciadas: la escritura por un lado, y la lectura por otro. Y además, el orden lógico es así, primero la escritura del archivo según el nuevo formato diseñado, y posteriormente la lectura del archivo escrito. Aunque se explique por separado el desarrollo del código de escritura y de lectura del formato Mapa de Bits Jerárquico, conceptualmente no son dos elementos inseparables, dado que según sea la escritura del formato, así será su lectura, i.e., el desarrollo real de ambos códigos se hizo de forma simultánea, y las distintas alternativas de escritura que se explican más adelante, tienen su réplica en el código homólogo correspondiente a la lectura del formato.

De los diferentes formatos de BMP que existen, sólo se trabaja con uno, y además con una sola profundidad de color. El formato aceptado se corresponde con la estructura de cabecera BITMAPINFOHEADER, y la profundidad de color es 8 bits, i.e, 256 colores. Se utilizan sólo estas especificaciones por varias razones:

La estructura de cabecera BITMAPINFOHEADER es la más utilizada, estando garantizada su compatibilidad por Windows1.

La profundidad de color, 8 bits, es también ampliamente empleada. Una profundidad de color menor, de 1 o de 4 bits, puede no satisfacer las necesidades de niveles de gris, mientras que con una profundidad mayor es excesivo el número de niveles de gris a emplear. Se puede decir que con 256 valores de niveles de gris quedan satisfechas las necesidades.

La profundidad de color de 8 bits implica el uso de una paleta, y el mapa de bits contiene direcciones a dicha paleta, mientras que una profundidad de color superior implica no utilizar una paleta, ya que ésta sería muy grande, y entonces es el propio mapa de bits quien almacena los valores correspondientes a los colores. Luego utilizar una profundidad de 8 bits nos garantiza el uso de una paleta, y este hecho es de una importancia vital, al poder emplear esta paleta como una Look-Up Table (LUT).

1 N. del A.- Según las especificaciones del formato, no sucediendo lo mismo con la estructura de cabecera precedente, BITMAPCOREHEADER.

Page 56: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

BENJAMÍN ARIAS PÉREZ FOTOGRAMETRÍA DIGITAL Y PROGRAMACIÓN

80

5.2.- Escritura del formato Mapa de Bits Jerárquico 5.2.1.- Desarrollo del código de escritura Para la escritura de archivos en el formato diseñado se ha creado un control en Visual Basic, que se corresponde con la creación de una clase, a modo de objeto, que recibe el nombre de Convierte. Esta clase, u objeto, tiene un miembro o función externa principal, Carga, que es la única relación que existe entre el control, una vez compilado, y el hipotético usuario. También existen otra serie de funciones y procedimientos, pero éstos son de carácter interno y son de uso exclusivo del control Convierte, por lo que el usuario de este control no tiene acceso a ellos2. La función Carga de la clase Convierte tiene tan sólo un parámetro, y además de carácter opcional. El funcionamiento externo de esta función es bastante sencillo y tan sólo debe especificarse un parámetro, si se desea, o ninguno en otro caso. Este parámetro simplemente se trata del nombre del archivo, directorio o camino (path) inclusive, que se desea convertir al formato Mapa de Bits Jerárquico (BMJ). Luego el código de escritura del formato de imagen Mapa de Bits Jerárquico consta de las siguientes partes:

1) Gestión de archivos: tanto del archivo de entrada o lectura, como del archivo de salida o escritura.

2) Lectura del archivo de mapa de bits que se desea transformar a BMJ. En concreto se lee la cabecera de archivo y la cabecera del mapa de bits.

3) Chequeo del tipo de mapa de bits, de la profundidad de color, y de que no se trate de una imagen comprimida. Esto es así porque sólo se trabaja con un determinado tipo de BMP, como ya se ha explicado anteriormente.

4) Obtención de información de la memoria disponible del ordenador, para actuar en consecuencia.

5) Escritura del archivo BMJ de forma simultánea a la lectura del archivo BMP.

6) Visualización de un indicador del avance en la escritura del archivo BMJ.

5.2.1.1.- Gestión de archivos La función Carga de la clase Convierte admite un único parámetro, y además tiene el carácter de opcional. Se trata del nombre del archivo con extensión BMP que se desea transformar al formato BMJ. Entonces, si no se pasa el nombre del archivo a convertir, aparece un cuadro de diálogo de tipo Abrir.

2 N. del A.- Es lo que se conoce como Encapsulamiento

Page 57: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

DESARROLLO DE SOFTWARE. LECTURA Y ESCRITURA DEL FORMATO PROPIO

81

En caso de pasar el nombre en la función Carga, este cuadro de diálogo no aparece porque no es necesario. Sin embargo, independientemente de si el parámetro se incluye o no en la función Carga, el cuadro de diálogo correspondiente al archivo a guardar como BMJ siempre aparece. 5.2.1.2.- Lectura del archivo BMP Esta parte del código está referida a la lectura de las cabeceras, tanto de archivo como del mapa de bits, con varios objetivos:

Obtener la información necesaria para convertir después a formato de imagen BMJ.

Poder efectuar el chequeo del tipo de mapa de bits. La lectura del archivo se completa, una vez chequeado el tipo de mapa de bits,

con la lectura de los datos del mapa de bits propiamente dicho. Esta parte de la lectura es simultánea a la escritura del formato BMJ.

5.2.1.3.- Chequeo del archivo BMP Se efectúa el chequeo del formato de imagen para no seguir ejecutando el programa en caso de que no se cumpla con las especificaciones requeridas, que son las siguientes3:

Profundidad de color de 8 bits: se comprueba que el miembro biBitCount de la estructura BITMAPINFOHEADER sea 8. En caso de que sea distinto de 8 se detiene el programa.

Tipo de estructura de cabecera de bitmaps: se comprueba que efectivamente sea la estructura BITMAPINFOHEADER. Para ello el valor del miembro biSize de dicha estructura debe ser 40.

Tipo de compresión de la imagen: se comprueba que la imagen no está en ningún formato de compresión, para lo que el miembro biCompression de la estructura BITMAPINFOHEADER debe ser 0.

Si la imagen que se desea convertir a BMJ no cumple estas especificaciones, se

envía información al usuario, mediante mensajes en pantalla, del motivo por el cual no se realiza la conversión. Si la imagen a transformar al formato BMJ cumple las especificaciones anteriores, el código sigue ejecutándose, siendo el siguiente paso la obtención de información sobre la memoria disponible. 3 N. del A.- Se recomienda observar las definiciones de las estructuras en el capítulo 3.

Page 58: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

BENJAMÍN ARIAS PÉREZ FOTOGRAMETRÍA DIGITAL Y PROGRAMACIÓN

82

5.2.1.4.- Obtención de información de la memoria disponible La primera parte del archivo BMJ contiene el archivo en formato BMP original, y la copia de éste sobre el primero se puede realizar de forma simple, byte a byte. Sin embargo, si el archivo original contiene 1.000 bytes, e.g., se emplearán 1.000 operaciones de lectura y otras tantas de escritura, i.e., 2.000 operaciones de lectura y escritura, que a su vez se pueden transformar a tiempo en función del ordenador con el que se trabaje y en función del dispositivo del almacenamiento. Por lo tanto esto no es muy práctico a efectos de rendimiento temporal del código. Para paliar este inconveniente, se puede recurrir a funciones de la API de Windows que permitan manejar bloques de memoria. Entonces el elemento de lectura/escritura pasa de ser 1 byte a ser un bloque de bytes, con lo que disminuye de forma considerable el número de operaciones, y por tanto el tiempo empleado. Los pasos básicos para copiar un bloque de memoria son4: 1.- Asignación de memoria de la pila global.

2.- Bloqueo de la memoria asignada. Una vez bloqueada la memoria, ésta no se puede mover ni destruir, en cambio se puede copiar.

3.- Copia del contenido de la memoria bloqueada a otro bloque. 4.- Desbloqueo de la memoria bloqueada. 5.- Liberación del bloque de memoria. Se puede considerar que el paso 4º es el inverso del 2º, que el paso 5º es el inverso del 1º.

Es necesario salir de Visual Basic para poder realizar estas operaciones, puesto que las funciones que aporta Visual Basic no permiten manejar bloques de memoria. Por lo tanto, hay que realizar llamadas a funciones de la API que permiten hacer este tipo de operaciones.

Con estas operaciones se reduce el tiempo de lectura/escritura del archivo original sobre el archivo final. Pero cabe plantearse una pregunta, ¿qué ocurre cuando el bloque de memoria excede de la memoria que Windows maneja?, que implica otra cuestión, ¿se pueden realizar operaciones con grandes bloques de memoria?. La respuesta a esta última pregunta es que afirmativa. En cuanto a la primera pregunta, cuando se quiere asignar un bloque de memoria que excede la capacidad de Windows para manejarlo, Windows se dedica a ampliar la memoria virtual y su archivo de paginación, hasta que pueda asignar la memoria. Esto implica tiempo de espera mientras que Windows reorganiza la memoria virtual, y además este tiempo de espera es indeterminado, por lo tanto es un cabo suelto que conviene atar. Una posibilidad (hay varias), es determinar cuánta memoria RAM hay disponible en el ordenador, y realizar las operaciones de bloques de memoria con bloques de un tamaño inferior a dicha memoria disponible. De esta forma se realizan varias operaciones de lectura/escritura en vez de una sola, y el número de operaciones es pequeño si se compara con el número de operaciones a realizar si el elemento de lectura/escritura se trata de 1 byte.

4 PRETOUTSOS, E., La Biblia de Visual Basic 5, pág. 620.

Page 59: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

DESARROLLO DE SOFTWARE. LECTURA Y ESCRITURA DEL FORMATO PROPIO

83

Para obtener información de la memoria de Windows y del ordenador es necesario nuevamente realizar llamadas a la API. La información que se puede conseguir es la siguiente:

Porcentaje de la memoria usada. Número total de bytes de la memoria física. Número de bytes disponibles de la memoria física. Número total de bytes en el archivo de paginación. Número de bytes disponibles en el archivo de paginación. Número total de bytes virtuales. Número de bytes virtuales libres.

En el código implementado se opta por utilizar la cuarta parte del número de

bytes libres de la memoria física, que es la memoria RAM que no está siendo utilizada. No se utiliza toda la memoria disponible para dejar margen a Windows y para no agotar la memoria física disponible. También hay que añadir que las operaciones de lectura/escritura del contenido de un bloque de memoria sobre un archivo no se pueden realizar con las funciones que proporciona Visual Basic, y se hacen con llamadas a funciones de la API de Windows. 5.2.1.5.- Scan line Antes de continuar con la explicación de la escritura de la pirámide de imágenes es pertinente en este punto explicar el concepto scan line. El término scan line hace referencia (pero no se corresponde) a los conceptos de línea y columna en una imagen digital, y además está íntimamente relacionado con la profundidad de color de la imagen, y con la manera característica de Windows de escribir y visualizar los mapas de bits. En el tercer capítulo de este trabajo se explicaron los tipos de archivos BMP y las diferentes estructuras que pueden formar parte de ellos. Los mapas de bits están escritos de forma secuencial, de tal forma que se recorre la imagen píxel a píxel, y no hay bytes que marquen el final de una línea. Los mapas de bits están estructurados de la siguiente forma (Línea, Columna):

(1,1)(1,2)...(1,n)(2,1)(2,2)...(2,n)...(m,1)(m,2)...(m,n)

Windows entiende los mapas de bits en scan lines de 4 bytes, con independiencia del número de columnas reales que formen cada línea de la imagen. En el caso de que el número de columnas de la imagen no sea un múltiplo de 4 bytes, simplemente se rellena hasta completar los 4 bytes el resto de la scan line con valores nulos (cero). El concepto múltiplo de 4 bytes está relacionado con la profundidad de color, i.e., con el número de bits empleado para representar el color de un píxel. Si se trata de

Page 60: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

BENJAMÍN ARIAS PÉREZ FOTOGRAMETRÍA DIGITAL Y PROGRAMACIÓN

84

profundidad de color de 1, 4, u 8 bits, el mapa de bits contiene direcciones a la paleta. Si se trata de 16, 24 o 32 bits, el mapa de bits realmente contiene el color del píxel. En el caso de que se trate de 1 bit por color, una scan line, con 4 bytes, serán 32 bits, i.e., se podrán representar en cada scan line 32 píxeles. Si una imagen tiene un ancho de 30 píxeles, el mapa de bits secuencial tendrá un aspecto similar al siguiente: (1,1)...(1,30)(Nulo)(Nulo)(2,1)...(2,30)(Nulo)(Nulo)...(m,1)...

...(m,30)(Nulo)(Nulo)

donde cada paréntesis corresponde a 1 píxel, dado que en este caso se trata de profundidad de color de 1 bit. Para aclarar más las cosas, la primera scan line es:

(1,1)...(1,30)(Nulo)(Nulo) que corresponden a 32 bits o 4 bytes. Si el ancho de la imagen fuese mayor de 32 píxeles, e.g., 45 píxeles, con la profundidad de color de 1 bits son 2 scan lines, y se corresponden con una sola línea de la imagen. En este ejemplo, la primera scan line está completa, y la segunda sólo los 13 primeros bits (o píxeles en este caso) tienen valores, i.e, 32 + 13 = 45. Sin embargo, debido a la configuración scan line, se completan hasta 2*32 = 64 píxeles (o bits en este caso) con 19 valores nulos, i.e., 64 - 45 = 19. A continuación se expresa la primera línea de esta imagen de 45 píxeles de ancho:

(1,1)...(1,32)(1,33)...(1,45)(Nulo)...(Nulo) donde la primera scan line es:

(1,1)...(1,32)

y la segunda scan line es

(1,33)...(1,45)(Nulo)...(Nulo) Se puede decir que cada línea de la imagen original está representada en el mapa de bits bien por una scan line, si al ancho en píxeles es igual o menor de 32, o bien por un grupo de scan lines, si dicho ancho supera los 32 píxeles. Lógicamente, con cada profundidad de color varía el número de scan lines para representar una línea con el mismo número de píxeles, por lo que se debe hacer un estudio para cada tipo de profundidad de bits si se quiere acabar de entender este concepto. Por ejemplo, si se toman los mismos ejemplos pero con una profundidad de color de 8 bits. Cada píxel necesita de 1 byte de la scan line para poder ser representado, luego cada scan line recoge con esta profundidad de color 4 píxeles. En caso de que el ancho dela imagen no sea múltiplo de 4 bytes, se completa la última scan line con valores nulos. Hay, por

Page 61: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

DESARROLLO DE SOFTWARE. LECTURA Y ESCRITURA DEL FORMATO PROPIO

85

tanto, tantas últimas scan line como líneas reales de la imagen. Una imagen con 30 píxeles de lado tiene un aspecto semejante al que se muestra a continuación: (1,1)...(1,4)(1,5)...(1,8)(1,9)...(1,12)(1,13)...(1,16)(1,17)......(1,20)(1,21)...(1,24)(1,25)...(1,28)(1,29)(1,30)(Nulo)(Nulo) donde cada píxel corresponde con cada paréntesis. La primera scan line es:

(1,1)...(1,4)

y la segunda scan line es:

(1,5)...(1,8)

y la última scan line:

(1,29)(1,30)(Nulo)(Nulo) Si se trata de una imagen con 45 píxeles de ancho, una línea de la imagen original es así:

(1,1)...(1,4)(1,5)...(1,8)(1,9)...(1,12)(1,13)...(1,16)(1,17)......(1,20)(1,21)...(1,24)(1,25)...(1,28)(1,29)...(1,32)(1,33).......(1,36)(1,37)...(1,40)(1,41)...(1,44)(1,45)(Nulo)(Nulo)(Nulo) i.e., se necesitan 3 valores nulos para completar los 45 píxeles reales. La última scan line es:

(1,45)(Nulo)(Nulo)(Nulo)

En el caso de una profundidad de color de 32 bits cada píxel necesita de los 4 bytes de la scan line, luego en este caso el número de scan line corresponderá directamente con el número de columnas de la imagen original, i.e., con el ancho en píxeles de la imagen, y por lo tanto no es necesario rellenar con valores nulos para completar cada scan line.

Se ha explicado la forma secuencial de los mapas de bits para los de tipo top-down, y aunque éstos no son los más abundantes, si son los más intuitivos para explicar mejor el concepto de scan line. Los mapas de bits de tipo bottom-up difieren de estos en que invierten el orden de las filas de la imagen original, no así el de las columnas. Luego, el último ejemplo expuesto, con 45 píxeles de ancho y una profundidad de 8 bits, si se considera ahora que es del tipo bottom-up, la primera scan line que aparece para representar a la última fila, fila m, de la imagen original tiene el siguiente aspecto:

Page 62: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

BENJAMÍN ARIAS PÉREZ FOTOGRAMETRÍA DIGITAL Y PROGRAMACIÓN

86

(m,1)...(m,4)(m,5)...(m,8)(m,9)...(m,12)(m,13)...(m,16)(m,17)......(m,20)(m,21)...(m,24)(m,25)...(m,28)(m,29)...(m,32)(m,33).......(m,36)(m,37)...(m,40)(m,41)...(m,44)(m,45)(Nulo)(Nulo)(Nulo)

No hay más diferencias con respecto a los mapas de bits de tipo top-down que

esta inversión de las filas, no afectando a las columnas este cambio en el orden de las filas.

De lo arriba explicado se deduce que un mapa de bits no tendrá el mismo número de scan lines que líneas en la imagen original, y que además el número de scan lines depende de dos factores:

Profundidad de color, i.e., número de bits necesarios para representar el color de un píxel.

Número de columnas de la imagen original. El número de bytes está directamente relacionado con el número de scan lines,

dado que cada una de estas contiene invariablemente 4 bytes. Luego la relación entre el número de bytes necesario para representar una línea de la imagen y el número de scan lines es directa:

nBytes = nScanLine * 4

A efectos de implementación, el mapa de bits a visualizar se almacena en una

matriz unidimensional de bytes, lo que concuerda con la naturaleza secuencial del mapa de bits en el archivo de imagen, y concuerda también con las especificaciones de Windows para mostrar una imagen en un dispositivo de visualización. El tamaño de esta matriz está en función del número de scan lines necesarias para representar cada línea de la imagen, y del número de líneas de la imagen. Se puede decir que el número de scan lines se corresponde con el número de las columnas de la imagen original, siendo redondeado por exceso a múltiplos de 4. Sin embargo, la matriz unidimensional que contiene los datos del mapa de bits está formada por bytes, no por scan lines, luego hay que tener en cuenta el número de bytes necesario para representar una línea de la imagen original.

A continuación se lista el código que permite calcular el número de bytes para representar una línea de la imagen, nBytes, que corresponde a una scan line, en el caso de profundidad de color de 8 bits,

B = AnchoImagen * 8

If (B Mod 32) <> 0 Then

nBytes = ((B + 32 - (B Mod 32)) / 8)

Else

nBytes = B / 8

Page 63: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

DESARROLLO DE SOFTWARE. LECTURA Y ESCRITURA DEL FORMATO PROPIO

87

End If

donde Mod es un operador matemático que devuelve el resto de la división entre B y 32. La siguiente expresión:

nBytes = ((B + 32 - (B Mod 32)) / 8)

corresponde con el redondeo por exceso a múltiplos de 4 del número de columnas de la imagen original, o si se prefiere, del ancho en píxeles de la imagen original. Así, la matriz unidimensional se redimensiona en función a nBytes y al número de filas de la imagen original (alto en píxeles):

Redimensiona MatrizImagen(nBytes * AltoImagen)

Si en uno de los ejemplos anteriores, profundidad de color 8 bits y un ancho de imagen de 30 píxeles, se asignan 25 píxeles de alto. Las operaciones a realizar para redimensionar la matriz unidimensional que va a contener los datos del mapa de bits son:

B = 30 * 8 = 240

B Mod 32 = 16

como se puede ver el resto es distinto de cero, luego se aplica la siguiente fórmula:

nBytes = ((B + 32 - (B Mod 32)) / 8)

nBytes = ((240 + 32 - (16)) / 8) = 32

Luego hacen falta 32 bytes para representar cada línea de 30 píxeles de la imagen, y como la imagen tiene 25 filas:

32 * 25 = 800

Redimensiona MatrizImagen(800)

En el caso de 45 píxeles de ancho, 25 filas de alto y profundidad de 8 bits:

B = 45 * 8 = 360

B Mod 32 = 8

Page 64: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

BENJAMÍN ARIAS PÉREZ FOTOGRAMETRÍA DIGITAL Y PROGRAMACIÓN

88

nBytes = ((B + 32 - (B Mod 32)) / 8)

nBytes = ((360 + 32 - (8)) / 8) = 48

48 * 25 = 1200

Redimensiona MatrizImagen(1200) Esto se corresponde con lo anteriormente explicado, 48 bytes por cada línea.

Para saber el número de scan lines necesario para representar una línea, simplemente se trata de dividir entre 4 del número de bytes calculado para representar una línea.

El número preciso de scan lines, o de bytes si se prefiere, para representar una línea varía también en función del número de bits necesario para representar el color de un píxel. En el caso de profundidad de color de 1 bit, el cálculo de bytes se realiza de manera semejante a la anterior:

B = AnchoImagen * 1

If (B Mod 32) <> 0 Then

nBytes = ((B + 32 - (B Mod 32)) / 8)

Else

nBytes = B / 8

End If

Luego, en los ejemplos anteriores, harán falta 4 bytes para almacenar una línea a

de 30 píxeles, y 8 bytes para representar un línea de 45 píxeles de ancho, si la profundidad de color es de 1 bit.

En el caso de profundidad de color de 32 bits:

B = AnchoImagen * 32

If (B Mod 32) <> 0 Then

nBytes = ((B + 32 - (B Mod 32)) / 8)

Else

nBytes = B / 8

End If

por lo que la línea de 30 píxeles necesita de 120 bytes para ser almacenada. El código generalizado para cualquier profundidad de color, nBitColor, es:

B = AnchoImagen * nBitColor

If (B Mod 32) <> 0 Then

nBytes = ((B + 32 - (B Mod 32)) / 8)

Page 65: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

DESARROLLO DE SOFTWARE. LECTURA Y ESCRITURA DEL FORMATO PROPIO

89

Else

nBytes = B / 8

End If

Este código simplemente relaciona dos unidades, bits y bytes, con el redondeo

por exceso a 4 bytes, o a 32 bits. La unidad bit está implicada por ser la unidad empleada para representar la profundidad de color. La unidad byte está implicada por ser la unidad con que se redimensiona la matriz unidimensional que contiene los datos del mapa de bits. Y el redondeo a 32 bits, o a 4 bytes, está ligado a el concepto de scan line. El código anterior, si se quiere, también está relacionando el ancho de la imagen, en píxeles, y con la profundidad de color, en bits, para obtener el número de bytes necesario para almacenar una línea.

Como se puede comprobar, comprender el concepto de scan line es esencial para

manejar imágenes con Windows. En base a lo explicado se fundamenta la implementación del código tanto en el control Convierte, que se encarga de la transformación al formato BMJ, como en el control Imagen, que se encarga de la visualización de la pirámide de imágenes contenida en un archivo con formato Mapa de Bits Jerárquico. 5.2.1.6.- Escritura del archivo BMJ En este apartado se detalla la escritura del archivo BMJ, y como ya se ha comentado, está relacionada con la lectura previa a la visualización que realiza el control Imagen, que se describe en este mismo capítulo más adelante. Para retomar el hilo de la explicación de la escritura del archivo BMJ es conveniente recordar la estructura en forma secuencial del archivo BMJ: en primer lugar se encuentra la imagen original, después la estructura de datos BMJ, a continuación la pirámide de imágenes (de mayor a menor tamaño), después la imagen Índice, y por último, datos relativos a las Orientaciones Interna y Externa de la imagen. La escritura en el archivo BMJ de la imagen original está ya explicada en el apartado 5.2.1.4. La siguiente parte del archivo BMJ es la estructura BMJ:

Public Type BitMapJerarquico '6 + nBitmap*4 bytes

Tipo As Byte '1 byte

nBitmap As Byte '1 byte

posBitmap() As Long 'nBitmap*4 bytes

posDatos As Long '4 bytes

End Type

Page 66: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

BENJAMÍN ARIAS PÉREZ FOTOGRAMETRÍA DIGITAL Y PROGRAMACIÓN

90

A los elementos de la estructura BMJ se le asignan los siguientes valores antes de su escritura en el archivo:

Tipo: este elemento vale 1 para archivos BMJ que contienen imágenes en formato de mapa de bits.

nBitmap: indica el número de imágenes que hay en la pirámide de imágenes. Esto se calcula en función del tamaño de la imagen Índice. Cada imagen en la pirámide será la cuarta parte de la inmediatamente anterior, porque se divide entre dos el ancho y el alto de la imagen. Esta sucesión termina cuando la división por dos del ancho o alto sea inferior al ancho o alto predeterminado, respectivamente, de la imagen Índice.

posBitmap(i): indica la posición dentro del archivo BMJ donde comienza la imagen i-ésima. Esto no se calcula, sino que se trata del byte en el que se comienza a escribir la imagen i-ésima. La razón por la que se anota es para permitir al código de visualización (correspondiente al control Imagen), subir y bajar en la pirámide de imágenes.

posDatos: posición dentro del archivo de formato BMJ donde se encuentran los datos de Orientación Interna y Orientación Externa. Tampoco se calcula, pero se anota para poder acceder a estos datos con el control Imagen. Se trata del byte hacia el que apunta la función de escritura cuando se terminan de escribir las imágenes.

La siguiente parte dentro del archivo BMJ es la pirámide de imágenes.

Básicamente se trata de ir dividiendo sucesivamente el ancho y el alto de la imagen original entre potencias de dos, lo que hace que una imagen de la pirámide sea 4 veces menor que la anterior. Esta iteración de divisiones se realiza hasta que se llega a un límite, determinado por el tamaño de la imagen Índice. De esta forma la imagen Índice corresponde a la imagen más pequeña de la pirámide. La manera de realizar esta pirámide de imágenes se relata en el siguiente apartado (5.2.1.7.).

Una vez finalizada la creación y escritura de las imágenes de la pirámide, se crea y escribe la imagen Índice. Se crean las cabeceras y el mapa de bits correspondiente, y se escriben el archivo BMJ.

Y por último, una vez escritas todas las imágenes, se aprovecha que el byte de escritura del archivo BMJ queda señalando el último byte escrito, para escribir dicho byte en el archivo BMJ, que corresponde a la posición de los datos de la Orientación Interna.

Page 67: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

DESARROLLO DE SOFTWARE. LECTURA Y ESCRITURA DEL FORMATO PROPIO

91

5.2.1.7.- Creación de la pirámide de imágenes La creación de la pirámide de imágenes puede explicarse por medio de la escritura de una de sus imágenes, dado que la única diferencia entre las imágenes que conforman la pirámide es su tamaño, y no el modo en que es creada. Por lo tanto, en lo siguiente se supone la división n-ésima de la imagen original, y la imagen a considerar es la imagen n-ésima. El almacenamiento de la imagen n-ésima en al archivo BMJ se hace de forma completa, i.e., como si fuera un archivo en formato BMP incrustado en una determinada posición del archivo BMJ. Por lo tanto, se escriben la estructura BITMAPFILEHEADER (cabecera del archivo), la estructura BITMAPINFO y el mapa de bits. La estructura BITMAPINFO contiene a la estructura BITMAPINFOHEADER (cabecera del mapa de bits) y a la matriz de estructuras RGBQUAD (paleta de colores). La cabecera del archivo no es indispensable para la posterior lectura con fines de visualización, por lo que se podría obviar su inclusión el archivo BMJ. Sin embargo, dado que la estructura que la contiene no es grande, 14 bytes, y posibilita la extracción de la imagen n-ésima a un archivo independiente en formato BMP, se escriben en el archivo BMJ. Los pasos básicos a considerar para la escritura de la imagen n-ésima en un archivo BMJ son: 1.- Cálculo del ancho y del alto de la imagen n-ésima.

2.- Cálculo del número de bytes necesario para representar una línea de la imagen n-ésima. 3.- Cálculo y asignación de valores a los miembros de las distintas estructuras. 4.- Escritura de las estructuras de la imagen n-ésima en el archivo BMJ. 5.- Lectura del archivo original y escritura en el archivo BMJ del mapa de bits de la imagen n-ésima.

La imagen n-ésima tiene definido su alto y su ancho por la división del ancho y del alto, respectivamente, de la imagen original por la n-ésima potencia de 2. Este cálculo es el primer paso.

Después, en el segundo paso, se calcula el número de bytes necesario para representar una línea de la imagen n-ésima, del modo en que se explica arriba, en el apartado 5.2.1.6. Para ello es necesario el ancho de la imagen n-ésima, determinado en el primer paso. En el tercer paso, se calculan y asignan valores a las estructuras tanto de cabecera de archivo, como de cabecera del mapa de bits. Los cálculos son:

Cálculo del tamaño del mapa de bits en bytes: se realiza como se ha explicado en el apartado 5.2.1.6, mediante el producto del número de bytes necesario para representar una línea de la imagen n-ésima (calculado en el paso anterior) por el número de líneas de la imagen n-ésima.

Page 68: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

BENJAMÍN ARIAS PÉREZ FOTOGRAMETRÍA DIGITAL Y PROGRAMACIÓN

92

Cálculo del tamaño de archivo: mediante la suma del miembro bfOffBits de la estructura BITMAPFILEHEADER más el tamaño del mapa de bits en bytes. El miembro bfOffBits especifica la distancia, en bytes, desde la estructura BITMAPFILEHEADER hasta los bits del mapa de bits. Esto es, desde el byte inicial del archivo hasta el comienzo del mapa de bits. Este miembro, bfOffBits, no es necesario calcularlo porque es el mismo que el del fichero original, y el mismo que el de todas las imágenes, al ser todas del mismo tipo.

La estructura BITMAPFILEHEADER, que corresponde a la cabecera de archivo,

es la siguiente:

Type BITMAPFILEHEADER

bfType As Integer

bfSize As Long

bfReserved1 As Integer

bfReserved2 As Integer

bfOffBits As Long

End Type

A los miembros de esta estructura se les asignan los siguientes valores: bfType: Son los caracteres BM. bfSize: es la suma del miembro bfOffBits de la estructura

BITMAPFILEHEADER más el tamaño del mapa de bits en bytes.. bfReserved1: reservado, debe ser cero. bfReserved2: reservado, debe ser cero. bfOffBits: no se calcula, y se asigna el mismo que el del archivo

original.

La estructura BITMAPINFOHEADER también es necesario rellenarla:

Type BITMAPINFOHEADER

biSize As Long

biWidth As Long

biHeight As Long

biPlanes As Integer

biBitCount As Integer

biCompression As Long

biSizeImage As Long

biXPelsPerMeter As Long

biYPelsPerMeter As Long

Page 69: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

DESARROLLO DE SOFTWARE. LECTURA Y ESCRITURA DEL FORMATO PROPIO

93

biClrUsed As Long

biClrImportant As Long

End Type

Los miembros de la estructura BITMAPINFOHEADER toman los siguientes valores:

biSize: es el tamaño de la estructura BITMAPINFOHEADER. Son 40 bytes

biWidth: es el ancho de la imagen n-ésima. biHeight: es el alto de la imagen n-ésima. biPlanes: siempre es 1. biBitCount: la profundidad de color es la misma que la de la imagen

original. En el caso de las imágenes que se tratan en este trabajo su valor es siempre 8.

biCompression: ningún tipo de compresión, por lo tanto siempre es 0. biSizeImage: tamaño del mapa de bits en bytes. biXPelsPerMeter: resolución en X de la imagen n-ésima, dado que no

se cambia el tamaño del píxel, sino el número de píxeles, es la misma resolución que la de la imagen original.

biYPelsPerMeter: ídem. biClrUsed: este valor siempre es cero. biClrImportant: este valor siempre es cero.

La paleta de colores, considerada como la matriz de estructuras RGBQUAD, es

simplemente una copia de la paleta de la imagen original, porque no se trata de una modificación de colores, sino de una selección de píxeles.

El cuarto paso consiste en la escritura en el archivo BMJ de las estructuras anteriores con los valores ya reseñados.

El quinto paso es la selección de píxeles de la imagen original para formar la imagen más pequeña. Dado que se estudiaron varias alternativas para ello, en función de tiempo y número de operaciones, se explican en el siguiente apartado. 5.2.2.- Alternativas Para la selección de píxeles se estudiaron varias alternativas para el ahorro de tiempo, o si se quiere, para la disminución del número de operaciones a realizar. En concreto 3 alternativas, que son las siguientes:

1ª.- Lectura del valor del píxel en la imagen original, uno a uno, y escritura de dichos valores en el mapa de bits correspondiente a la imagen n-ésima.

Page 70: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

BENJAMÍN ARIAS PÉREZ FOTOGRAMETRÍA DIGITAL Y PROGRAMACIÓN

94

2ª.- Lectura de ciertas filas completas de la imagen original, escritura de dichas líneas en el mapa de bits correspondiente a la imagen n-ésima. Se completa esta técnica con la visualización escalada de estas líneas. 3ª.- Lectura de ciertas filas completas de la imagen original, y escritura seleccionada de píxeles en el mapa de bits correspondiente a la imagen n-ésima.

La primera alternativa es la opción intuitiva, la más lógica. Se trata simplemente de ir leyendo en el mapa de bits de la imagen original los valores de los píxeles que se deseen, y su posterior escritura en el mapa de bits de la imagen n-ésima. La cadencia en la lectura viene determinada por la división n-ésima de la imagen original. De esta forma, la primera imagen se genera con uno de cada dos píxeles de la imagen original en la primera línea, luego salta a la 3ª línea para coger 1 de cada dos líneas, etc...De forma generalizada, se toma un píxel de cada 2n píxeles de la imagen original en el n-esimo escalón de la pirámide. A continuación se muestra un ejemplo de forma gráfica. Se supone la imagen original formada por 16x16 píxeles, i.e, 256 píxeles.

X X X X X X X X

X X X X X X X X

X X X X X X X X

X X X X X X X X

X X X X X X X X

X X X X X X X X

X X X X X X X X

X X X X X X X X

La primera imagen de la pirámide se forma tomando un píxel de cada dos, que

como se puede ver en la imagen superior, son los píxeles marcados con X. La imagen así formada es:

X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X

Page 71: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

DESARROLLO DE SOFTWARE. LECTURA Y ESCRITURA DEL FORMATO PROPIO

95

que tiene 8x8 píxeles, i.e, 64 píxeles. La siguiente imagen de la pirámide se forma a partir de la original tomando un píxel de cada 4:

X X X X

X X X X

X X X X

X X X X

luego la imagen resultante es:

X X X X X X X X X X X X X X X X

con 4x4 píxeles, i.e., 16 píxeles. Esta primera alternativa implica muchas operaciones de lectura y escritura, lo que a su vez implica mucho tiempo. Por ello se piensa en otras alternativas, que se explican más adelante.

En la página siguiente se muestra una pirámide imágenes así obtenida. La imagen inferior es la imagen original, la imagen situada en el medio es la primera imagen generada por la primera división de la original, y la superior es la imagen generada por la segunda división de la original.

Page 72: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

BENJAMÍN ARIAS PÉREZ FOTOGRAMETRÍA DIGITAL Y PROGRAMACIÓN

96

La estrategia de la segunda alternativa es leer una fila completa de la imagen original en cada operación de lectura, y escribir dicha fila en una sola operación de escritura en el mapa de bits de la imagen n-ésima. Se leen sólo cada 2n filas para la generación de la imagen n-ésima. Con el mismo ejemplo anterior, como se puede ver en la siguiente figura:

X X X X X X X X X X X X X X X X

X X X X X X X X X X X X X X X X

X X X X X X X X X X X X X X X X

X X X X X X X X X X X X X X X X

X X X X X X X X X X X X X X X X

X X X X X X X X X X X X X X X X

X X X X X X X X X X X X X X X X

X X X X X X X X X X X X X X X X

Page 73: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

DESARROLLO DE SOFTWARE. LECTURA Y ESCRITURA DEL FORMATO PROPIO

97

una imagen de 16x16 píxeles, de la que se leen las filas completas, sólo una de cada dos filas. Las filas se leen cada una en una sola operación de lectura, y se escriben en una sola operación de escritura. Entonces la primera imagen que se almacena es:

X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X

La segunda imagen se genera con una de cada 4 filas de la imagen original:

X X X X X X X X X X X X X X X X

X X X X X X X X X X X X X X X X

X X X X X X X X X X X X X X X X

X X X X X X X X X X X X X X X X

La segunda imagen generada es:

X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X

Page 74: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

BENJAMÍN ARIAS PÉREZ FOTOGRAMETRÍA DIGITAL Y PROGRAMACIÓN

98

Para visualizar las imágenes así generadas se requiere el escalado de las imágenes dentro del código de visualización (control Imagen). A continuación se muestra una pirámide de imágenes así generada:

El rendimiento de esta segunda alternativa es realmente espectacular, en términos tanto de número de operaciones como de tiempo necesario para convertir una imagen en formato de mapa de bits a una imagen en formato de Mapa de Bits Jerárquico. Sin embargo, no es la alternativa más adecuada debido al efecto de huecos, píxeles negros, que se produce al escalar la imagen para su visualización. En la imagen situada en la página siguiente se puede comprobar este efecto. La imagen situada a la izquierda es la imagen n-ésima generada mediante la primera alternativa, y la imagen situada a la derecha es la imagen n-ésima generada por la segunda alternativa.

Debido a este inconveniente se rechaza esta alternativa, que aunque resulta bastante llamativa por el reducido coste temporal, no ofrece garantías en la visualización debido a la función de escalado.

Page 75: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

DESARROLLO DE SOFTWARE. LECTURA Y ESCRITURA DEL FORMATO PROPIO

99

Por lo tanto, se piensa en una tercera alternativa, que en realidad es un híbrido de las otras dos alternativas, tomando de cada una ellas sus aspectos más positivos. En primer lugar, se lee cada fila completa en una sola operación de lectura y queda cargada en una matriz. Esto ofrece ya una cierta mejora respecto a la primera alternativa al ahorrar operaciones de lectura. La escritura en el archivo no se realiza con la fila completa, sino un píxel de cada 2n píxeles. No se reduce el número de operaciones de escritura, pero se consigue una ventaja, porque se obtienen las imágenes piramidales correctas y no es necesario un escalado posterior de la imagen. Con el ejemplo con el que se han explicado las otras dos alternativas, se explica a continuación esta tercera y definitiva. En primer lugar, se parte de la imagen original, y para crear la primera imagen de la pirámide se leen una de cada dos filas de forma completa:

X X X X X X X X X X X X X X X X

X X X X X X X X X X X X X X X X

X X X X X X X X X X X X X X X X

X X X X X X X X X X X X X X X X

X X X X X X X X X X X X X X X X

X X X X X X X X X X X X X X X X

X X X X X X X X X X X X X X X X

X X X X X X X X X X X X X X X X

Page 76: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

BENJAMÍN ARIAS PÉREZ FOTOGRAMETRÍA DIGITAL Y PROGRAMACIÓN

100

de cada fila leída, y que está cargada en una matriz unidimensional, se seleccionan uno de cada dos píxeles para escribirlo en el mapa de bits de la primera imagen original.

X X X X X X X X y la imagen generada es la siguiente, de 8x8 píxeles:

X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X

la siguiente imagen piramidal se hace leyendo cada fila de forma completa, una de cada 4 filas, y para la escritura se selecciona uno de cada 4 píxeles:

X X X X con lo que la imagen resultante es de 4x4 píxeles:

X X X X X X X X X X X X X X X X

Esta es la alternativa implementada en el control Convierte.

A continuación se muestra un estudio de los tiempos y tamaños obtenidos para poder hacer una comparación entre alternativas. Los tiempos indicados corresponden a un ordenador Pentium a 166 MHz, con 64 MB de RAM.

Page 77: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

DESARROLLO DE SOFTWARE. LECTURA Y ESCRITURA DEL FORMATO PROPIO

101

Nombre Imagen

1ª Alternativa (segundos)

2ª Alternativa (segundos)

3ª Alternativa (segundos) %(1ª/2ª)

%(1ª/3ª)

Edif.bmp

17 0,6 7 2.733,33

142,86

tetraedro_d.bmp

44 1,5 18 2.833,33

144,44

Fot209.bmp

162 6 64 2.600,00

153,13

Catast188208.bmp

1.875 136 723 1.278,68

159,34

Como se puede observar hay un gran rendimiento temporal con la segunda alternativa. Aún cuando con la imagen más grande de todas, Catast188208.bmp, baja el rendimiento, sigue siendo una mejora espectacular. Con la alternativa definitiva, la tercera, se mejora el tiempo en buena medida, en más de la mitad, e incluso la relación mejora con el tamaño de la imagen. Los tamaños van de menor tamaño, Edif.bmp, a mayor tamaño, Catast188208.bmp. El siguiente gráfico ayuda a ver las diferencias temporales:

0

200

400

600

800

1000

1200

1400

1600

1800

2000

1 2 3 4

Tie

mpo

en

segu

ndos

1ª Alternativa

2ª Alternativa

3ª Alternativa

donde los números se corresponden con la numeración de la siguiente forma:

Edif.bmp: se corresponde con 1. tetraedro_d.bmp: se corresponde con 2. Foto209.bmp: se corresponde con 3. Catast188208.bmp: se corresponde con 4.

Page 78: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

BENJAMÍN ARIAS PÉREZ FOTOGRAMETRÍA DIGITAL Y PROGRAMACIÓN

102

Una vez elegida la alternativa, se hizo un estudio de tamaños entre las imágenes originales y los archivos BMJ obtenidos. Los datos se muestran en la siguiente tabla:

Nombre Imagen

Tamaño Imagen

BMP (Bytes)

Tamaño Imagen BMJ (Bytes)

% Aumento

Edif.bmp

692.224

958.464 38,46

tetraedro_d.bmp

2.109.440

2.801.664 32,82

Fot209.bmp

7.114.752

9.486.336 33,33

Catast188208.bmp

108.234.752 144.324.608 33,34

Como se puede observar la relación de aumento entre ambos archivos se mantiene en torno a un 33-34%, excepto el primero que es de 38.46%.

0

20.000.000

40.000.000

60.000.000

80.000.000

100.000.000

120.000.000

140.000.000

160.000.000

1 2 3 4

Byt

es A

lmac

enam

ient

o

Tamaño BMP

Tamaño BMJ

5.2.3.- Gestión de errores La función Carga, para el chequeo de errores que se puedan producir, incorpora como respuesta a la llamada a la función una variable booleana, de tal forma que en caso de que se produzca algún error interno la variable tenga el valor Falso, y en caso contrario, i.e., en caso de que no se produzca ningún error tenga el valor Verdadero. Esto es conveniente hacerlo así para que el programa que llame a la función Carga del

Page 79: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

DESARROLLO DE SOFTWARE. LECTURA Y ESCRITURA DEL FORMATO PROPIO

103

objeto Convierte sepa si se ha producido algún error durante la ejecución de dicha llamada, y por lo tanto, de esta manera sea fácil implementar el código correspondiente al producirse un error en la llamada a un procedimiento externo. La gestión de los errores es, por tanto, una cuestión intrínseca al objeto Convierte. Cuando se genera un error, el procedimiento que se sigue es el siguiente:

1. Se aborta la ejecución de la función Carga, generándose un código de error.

2. En base a dicho código de error se envía un mensaje al usuario para comunicarle la causa del error.

3. Se asigna Falso a la variable de repuesta de la función Carga. 4. Finaliza la ejecución de la función Carga.

5.3.- Lectura del formato Mapa de Bits Jerárquico

5.3.1.- Desarrollo del código de lectura El código de lectura se implementa sobre un Control ActiveX, en forma de Control de Usuario, y que recibe el nombre de Imagen. Por lo tanto, las características iniciales son similares al control Convierte, que es el control generado para la escritura del formato BMJ. Sin embargo, el control Imagen presenta más propiedades, métodos y elementos que el control Convierte. 5.3.1.1.- Gestión de archivos La función del control Imagen para visualizar los archivos BMJ recibe el nombre de Carga, y se puede llamar de forma externa al control Imagen. Esta función puede recibir dos parámetros:

nImagen: un número identificador de la imagen. Se define como de tipo Byte, luego su rango de valores se encuentra en 0 y 255 en números enteros.

NombreArchivo: el nombre del archivo que contiene el archivo BMJ. Este parámetro es opcional, por lo que su omisión ocasiona que aparezca una ventana para que el usuario elija el archivo BMJ que desea visualizar.

El parámetro nImagen es el que sirve de identificador en todo el código, por lo

tanto es un elemento indispensable dentro del código del control Imagen. Tanto es así, que todas las propiedades, métodos y elementos hacen referencia a este identificador, por lo que la primera operación en aquellos es obtener el identificador de la imagen.

Page 80: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

BENJAMÍN ARIAS PÉREZ FOTOGRAMETRÍA DIGITAL Y PROGRAMACIÓN

104

El parámetro NombreArchivo es el nombre del archivo más la ruta de directorios donde se encuentra. Es opcional, por lo que su omisión genera la presentación en pantalla de una ventana a modo de cuadro de diálogo, donde el usuario puede elegir el archivo de tipo Mapa de Bits Jerárquico que desea abrir. En el caso de que el usuario pulse Cancelar en esta ventana, se muestra un mensaje indicando que el usuario ha decidido Cancelar la acción, por lo que no se abrirá ninguna imagen.

La función Carga del control Imagen devuelve una variable boolena, y de esta forma se puede controlar si se ha producido un error en la visualización de la imagen. Si la función devuelve Verdadero se considera que no se producido ningún error en la visualización de la imagen. En cambio, si la función, una vez ejecutada, devuelve Falso, significa que ha habido algún error en la visualización. 5.3.1.2.- Lectura del archivo BMJ Se pueden distinguir dos tipos de lecturas del archivo BMJ, dependiendo de cuándo se realice la lectura:

Lectura inicial: se realiza mediante la función Carga, de forma externa al Control Imagen. Esta lectura está gestionada por dicha función.

Lectura en tiempo de ejecución: se realiza de forma interna desde el Control Convierte, en respuesta a los eventos que pueda generar el usuario. Esta lectura no está gestionada por la función Carga.

La lectura inicial, gestionada por la función Carga, sigue los siguientes pasos:

1.- Lectura de la cabecera del archivo y de la cabecera del mapa de bits. 2.- Redimensionamiento de una matriz que almacenará los valores del mapa de bits que se van a cargar. 3.- Almacenamiento del mapa de bits en la matriz redimensionada. 4.- Preparación de las estructuras adecuadas para que puedan ser admitidas por las funciones de visualización. 5.- Envío de las estructuras a las funciones de visualización.

Como ya se ha explicado anteriormente, el formato de archivo BMJ se

fundamenta en el formato BMP, y éste está pensado para facilitar su visualización en Windows. Es por ello que las funciones que se utilizan para mostrar una imagen en pantalla admiten como parámetros las estructuras que existen dentro del formato BMP, éstas están contenidas en el archivo del formato BMP, y también están contenidas dentro del archivo de extensión BMJ.

Por lo tanto en la lectura de un archivo BMJ se pueden hablar de dos tipos de acciones, independientemente de si se trata de la lectura inicial o de la lectura en tiempo de ejecución:

Page 81: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

DESARROLLO DE SOFTWARE. LECTURA Y ESCRITURA DEL FORMATO PROPIO

105

Lectura propiamente dicha: se leen los valores correspondientes al formato y se almacenan en las variables adecuadas.

Preparación de la visualización: para ello se cargan los valores necesarios en variables que sean acordes con:

- las estructuras admitidas por las funciones de visualización - la parte de la imagen que se desea mostrar - la imagen que corresponda dentro de la pirámide de

imágenes.

Las estructuras adecuadas para la visualización son la cabecera de mapa de bits (BITMAPINFOHEADER), la paleta de colores(RGBQUAD), y el mapa de bits propiamente dicho.

5.3.1.3- Pasos para mostrar un mapa de bits Los pasos que hay que realizar para poder presentar un mapa de bits en pantalla, o si se quiere en cualquier otro dispositivo son los siguientes5: 1.- Obtención del bitmap 2.- Creación de un contexto de dispositivo de memoria 3.- Selección del bitmap en este último contexto de dispositivo.

4.- Copia desde dicho contexto al dispositivo que se vaya a utilizar para su visualización.

5.- Eliminación del contexto de dispositivo creado en el paso 2. 6.- Eliminación del mapa de bits cuando se hay finalizado con él. 5.3.1.4.- Visualización de una parte de la imagen

La zona de la imagen que se desea mostrar está determinada en todo momento por las acciones que el usuario considere conveniente realizar, por lo que la navegación por la imagen es controlada por el usuario. La zona de la imagen que se desea mostrar corresponde entonces con:

las coordenadas X, Y, del origen de la zona de la imagen. el ancho y el alto de la ventana de visualización. la imagen correspondiente dentro de la pirámide de imágenes. el identificador de la imagen BMJ.

5 CHARTE, F., et al., Programación avanzada en Windows 2000, pág. 198.

Page 82: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

BENJAMÍN ARIAS PÉREZ FOTOGRAMETRÍA DIGITAL Y PROGRAMACIÓN

106

Estos valores son los que se determinan que zona de la imagen se visualiza, y estos valores son determinados en todo momento.

Conviene recordar la estructura del archivo BMJ, que por este orden tiene los siguientes elementos:

Imagen Original. Estructura BMJ. Pirámide de imágenes. Imagen Índice. Datos relativos a Orientaciones.

También conviene recordar la forma de un archivo BMP, que por orden está

formado por: Cabecera de archivo. Cabecera del mapa de bits. Paleta de colores. Mapa de bits.

Por último recordar los conceptos de scan line, número de bytes necesario para

representar una línea, e ídem del mapa de bits completo. Y sobre todo, es interesante refrescar ahora la estructura secuencial del mapa de bits.

La pregunta ahora es: ¿cómo se visualiza una zona de la imagen? La respuesta a esta cuestión es la pieza clave dentro de este trabajo. La visualización de una zona de la imagen tiene varios pasos, y éstos son los siguientes:

1.- En primer lugar, mediante el identificador de la imagen BMJ, se accede a la imagen BMJ correspondiente de las varias que es posible tener abiertas. 2.- Después, se accede a la imagen n-ésima dentro de la pirámide. 3.- Con las coordenadas X, Y del origen de la zona de la imagen, se accede dentro del mapa de bits correspondiente al primer píxel. 4.- Mediante el ancho y el alto de la zona a visualizar se leen los valores del mapa de bits correspondientes. 5.- Se siguen los pasos necesarios para mostrar un mapa de bits en pantalla.

Los tres primeros pasos son de gestión de archivos. El primer paso se trata de saber sobre que archivo hay que efectuar la lectura. El segundo y tercer paso, acceden al primer píxel a visualizar, teniendo para ello en cuenta los valores almacenados en la estructura BMJ y las coordenadas del origen.

Page 83: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

DESARROLLO DE SOFTWARE. LECTURA Y ESCRITURA DEL FORMATO PROPIO

107

La estructura BMJ es:

Public Type BitMapJerarquico '6 + nBitmap*4 bytes

Tipo As Byte '1 byte

nBitmap As Byte '1 byte

posBitmap() As Long 'nBitmap*4 bytes

posDatos As Long '4 bytes

End Type

El miembro posBitmap(n) permite, dentro del archivo BMJ, acceder a la posición de inicio de la imagen n-ésima. A continuación se accede al inicio del mapa de bits de dicha imagen mediante el miembro bfOffBits de la estructura BITMAPFILEHEADER. La siguiente acción será acceder a la píxel de inicio de la zona a visualizar mediante las coordenadas del origen. Sin embargo, debido a la configuración bottom-up del mapa de bits, por la que la imagen aparece invertida en el orden de sus filas, realmente se accede a la esquina inferior izquierda, en lugar de a la esquina superior izquierda, donde es norma común colocar el origen de coordenadas en una imagen digital. Una vez que se accede a la esquina inferior izquierda, se lee por filas sólo el ancho a visualizar, con lo que la imagen que se carga en memoria es exclusivamente la que se desea visualizar. Para aclarar esta idea conviene observar la figura bajo estas líneas. Representa la imagen completa, y los píxeles marcados con una X son los correspondientes a la zona a visualizar. Pues la estrategia se basa en que se carga en memoria sólo la zona de la imagen a visualizar, y no toda la imagen.

X X X X X X X X X X X X

Page 84: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

BENJAMÍN ARIAS PÉREZ FOTOGRAMETRÍA DIGITAL Y PROGRAMACIÓN

108

Para visualizar una zona de la pantalla, se deben asignar valores a las estructuras del formato BMP para poder pasadas a las funciones de visualización. Por lo tanto, para cada zona de la imagen que se presente en pantalla es necesario modificar los siguientes miembros de la estructura BITMAPINFOHEADER:

biWidth: es el ancho de la zona a mostrar. biHeight: es el alto de la zona a mostrar. biSizeImage: tamaño del mapa de bits en bytes. Se calcula tal y como

ya se ha explicado en el apartado 5.2.1.6. 5.3.3.- Descripción de funcionalidades En este apartado se describen de forma exhaustiva algunas de las funcionalidades del control Imagen, entendidas como propiedades, métodos y elementos que articulan las acciones del usuario hacia el control Imagen en tiempo de ejecución Las restantes funcionalidades se explican en los capítulos posteriores, pues necesitan de explicaciones adicionales Junto con la ventana que muestra la visualización en pantalla de la imagen también se han diseñado las siguientes ventanas:

Imagen Índice. Zoom. Factor de Zoom. Paleta. Histograma.

A continuación se describen estas ventanas, para qué sirven y cómo se

implementan. Sin embargo, antes se detallarán las funciones de la ventana de Visualización. 5.3.3.1.- Ventana de Visualización En esta ventana es donde se visualiza la zona de la imagen. Es la ventana principal y desde ella se puede llamar a las restantes. Presenta el aspecto que se muestra en la siguiente página.

Page 85: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

DESARROLLO DE SOFTWARE. LECTURA Y ESCRITURA DEL FORMATO PROPIO

109

La ventana muestra la zona de la imagen que se desea mostrar y además las siguientes características:

En la parte superior izquierda se muestra el número de imagen, que corresponde con el identificador de imagen en caso de que haya varias imágenes abiertas.

En la parte superior derecha se encuentran los iconos de manejo de la ventana. Efectúan tareas clásicas en Windows, que de izquierda a derecha son:

- Minimizado de la ventana. - Maximizado de la ventana. - Cerrar la ventana.

En la parte inferior y derecha de la ventana se encuentran las barras de desplazamiento horizontal y vertical respectivamente.

La acción más frecuente, además de la navegación por medio de las barras de

desplazamiento, es pulsar sobre la imagen con el botón derecho, con lo que aparece un menú emergente (popup menu), donde están todas las opciones que permiten manejar la imagen, como se puede ver en la imagen de la siguiente página.

Page 86: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

BENJAMÍN ARIAS PÉREZ FOTOGRAMETRÍA DIGITAL Y PROGRAMACIÓN

110

Las opciones que se permiten son las siguientes:

Imagen Índice: visualiza la Imagen Índice. El funcionamiento de esta imagen se explica en el apartado 5.3.3.2.

Zoom +: si en el momento de ejecutar este comando la zona de la imagen mostrada corresponde a la imagen n-ésima de la pirámide, visualiza la zona de la imagen correspondiente a la imagen inmediatamente superior en cuanto a tamaño, i.e., la imagen (n-1)-ésima. Si no hay imagen superior se muestra el siguiente mensaje, y para seguir aumentando en tamaño es necesario hacer uso del comando Hacer Zoom.

Zoom -: si en el momento de ejecutar este comando la zona de la imagen mostrada corresponde a la imagen n-ésima, visualiza la zona de la imagen correspondiente a la imagen inmediatamente inferior en cuanto a tamaño, i.e., la imagen (n+1)-ésima de la pirámide. Si no hay imagen inferior se muestra el siguiente mensaje:

Page 87: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

DESARROLLO DE SOFTWARE. LECTURA Y ESCRITURA DEL FORMATO PROPIO

111

Hacer Zoom: permite realizar un Zoom de la imagen. La utilización de este comando se explica más adelante en el apartado 5.3.3.3.

Paleta: permite modificar la tabla de colores. Ver apartado 5.3.3.4. Anaglifo: permite mostrar el anaglifo de dos imágenes. Se explica en el

capítulo 9 de esta publicación. Roaming: Permite realizar el denominado Roaming, y además de dos

formas, bien por medio de movimientos del ratón o bien por acción de la rueda superior del ratón. Se explica en el siguiente capítulo de esta publicación.

Visión Estereoscópica: permite conseguir la visión estereoscópica con la ayuda de un estereóscopo. Además, permite visualizar las marcas flotantes, moverlas de forma conjunta o independiente, y otras aplicaciones fotogramétricas. Se explica en el capítulo 9 de esta publicación.

Coordenadas Píxel: permite ver las Coordenadas Instrumentales en tiempo real. Se visualizan al lado del puntero del ratón, como se puede ver:

Page 88: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

BENJAMÍN ARIAS PÉREZ FOTOGRAMETRÍA DIGITAL Y PROGRAMACIÓN

112

Fotocoordenadas: permite ver las Fotocoordenadas en tiempo real. Se visualizan al lado del puntero del ratón, como se puede ver en la siguiente imagen:

Nivel Digital: permite ver el Nivel Digital del píxel sobre el que se sitúa el puntero del ratón, tal y como muestra la imagen:

Page 89: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

DESARROLLO DE SOFTWARE. LECTURA Y ESCRITURA DEL FORMATO PROPIO

113

Histograma: permite visualizar el histograma de la imagen. Se explica en el apartado 6.3.3.4.

Orientación Interna: permite ver, introducir y modificar los parámetros de Orientación Interna de la imagen. Se explica en el capítulo 9.

Orientación Enterna: permite ver, introducir y modificar los parámetros de Orientación Enterna de la imagen. Se explica en el capítulo 9.

Focal cámara: permite ver, introducir y modificar la distancia focal de la cámara con la que se ha obtenido la imagen. Se explica en el capítulo 9.

5.3.3.2.- Ventana de Imagen Índice La ventana de Imagen Índice nos muestra la imagen completa a modo de Overview. En todo momento muestra un rectángulo de borde blanco e interior hueco, que nos permite saber en que posición de la imagen completa se encuentra la zona visualizada en la ventana de Visualización. Presenta el siguiente aspecto:

Además, el tamaño del rectángulo blanco ayuda a hacerse una idea del tamaño de la zona visualizada con respecto a la imagen completa. A continuación se muestra una imagen en un determinado escalón, y en la página siguiente se puede ver el tamaño del rectángulo en la imagen índice:

Page 90: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

BENJAMÍN ARIAS PÉREZ FOTOGRAMETRÍA DIGITAL Y PROGRAMACIÓN

114

y si se compara con la siguiente imagen se puede ver la diferencia, tanto en la imagen visualizada como en el rectángulo de la imagen Índice:

Page 91: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

DESARROLLO DE SOFTWARE. LECTURA Y ESCRITURA DEL FORMATO PROPIO

115

También se puede navegar por la imagen a través de la imagen Índice. Si se mueve el ratón por encima de la imagen Índice, cambia el puntero del ratón a un puntero de cuatro flechas. Se puede entonces pinchar sobre la zona de la imagen Índice hacia la que se quiere ir, y se verá en la ventana de Visualización la zona de la imagen hacia la que se ha ido. Esta forma de navegar es muy útil cuando se trata de imágenes muy grandes. 5.3.3.3.- Ventana de Zoom y de Factor de Zoom Se utiliza para ampliar la visualización de la imagen, lo que se conoce como Hacer Zoom. Si se elige este comando se visualiza la siguiente ventana:

Se elige un factor de ampliación, por ejemplo 2, y se pulsa Aceptar. Entonces puede marcar sobre la ventana de visualización un rectángulo con ratón, mateniendo para ello pulsado el botón izquierdo del ratón. Al soltar el botón se visualiza la ventana de Zoom:

y en la ventana de visualización se pinta un rectángulo con la zona que ha sido ampliada, como se puede observar en la siguiente página.

Page 92: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

BENJAMÍN ARIAS PÉREZ FOTOGRAMETRÍA DIGITAL Y PROGRAMACIÓN

116

De la ventana ImagenZoom se puede obtener la siguiente información:

Coordenadas Píxel: si se han seleccionado sobre la ventana de Visualización.

Fotocoordenadas: ídem.

Page 93: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

DESARROLLO DE SOFTWARE. LECTURA Y ESCRITURA DEL FORMATO PROPIO

117

Nivel Digital: ídem.

5.3.3.4.- Ventana de Paleta Permite actuar sobre la paleta de colores del mapa de bits. Sólo está implementado un sesgo en los valores de la paleta, pero la verdadera funcionalidad de la manipulación de la paleta es que permite considerarla como una Look-Up Table (LUT) con resultados en tiempo real. Si se selecciona esta opción se visualiza la siguiente ventana:

y si se desplaza se puede ver en la imagen el resultado del desplazamiento de los valores de la paleta. La imagen sin manipulación en la paleta es:

Page 94: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

BENJAMÍN ARIAS PÉREZ FOTOGRAMETRÍA DIGITAL Y PROGRAMACIÓN

118

si manipulamos la paleta:

el aspecto de la imagen cambia en tiempo real:

5.3.3.5.- Ventana de Histograma Esta ventana muestra el histograma de la imagen Índice, no es el histograma de la imagen original. Esto es debido a que el histograma se presenta mediante un control propio de Visual Basic, MSChart, y a éste se le pasa una matriz de valores y él se encarga de representar los datos en un gráfico. Y una matriz tan grande como puede suponer un imagen de 10.000x10.000 píxeles no la acepta. Sin embargo, si acepta una matriz como mucho de 200x200 píxeles como es el caso de la imagen Índice. El histograma resultante no es el de la imagen original, por lo que sólo es orientativo.

Page 95: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

Operadores Morfológicos para Detección de Esquinas

Benjamín Arias Pérez Ingeniero Técnico en Topografía

Ingeniero en Geodesia y Cartografía Profesor Asociado.

Departamento de Ingeniería Cartográfica y del Terreno. Escuela Politécnica Superior de Ávila

Universidad de Salamanca e-mail: [email protected]

Resumen

En el presente artículo se expone un análisis acerca de la morfología matemática y su aplicación para extracción de información de una imagen. Se introducen conceptos de morfología matemática y se explican los principales operadores morfológicos, haciendo especial énfasis en su utilidad. Por último, se define un operador morfológico que permite la detección de esquinas, mostrando los resultados alcanzados mediante su empleo.

Un ejemplo de imagen binaria puede ser:

1.- Introducción

0000000000000100111000000

La morfología matemática puede ser útil en la extracción de información de las imágenes. Para ello se debe partir de la premisa inicial de que las imágenes reales pueden ser modeladas utilizando conjuntos de puntos de cualquier dimensión. En el caso de las imágenes digitales, es el espacio Euclídeo de 2 dimensiones (E2) el espacio adecuado para su aplicación, al tratarse de formas planas.

donde el conjunto de puntos que forman el objeto de imagen es:

Normalmente, la morfología matemática se emplea en imágenes binarias, y se extiende su utilización a escala de grises y a imágenes de color.

X = {(1,1), (1,2), (1,3), (2,1)}

considerando (fila, columna), y origen (0,0).

Una transformación morfológica se

define por la relación del conjunto de puntos del objeto, X, con otro conjunto de puntos, denominado elemento estructural. Éste se expresa con respecto a un origen local, denominado punto representativo. Dicho origen puede no formar parte del conjunto de puntos que conforman el elemento estructural.

2.- Morfología matemática en imágenes binarias Una imagen binaria puede representarse como un conjunto de puntos 2D. Los píxeles correspondientes a los objetos de la imagen tienen el valor 1, y forman un conjunto denominado, e.g., X. El resto de puntos de la imagen forman el conjunto complementario, XC , valen 0 y corresponden al fondo de la imagen.

La forma de aplicar una transformación morfológica es desplazando el elemento estructural por toda la imagen, y el resultado de la relación, 0 o 1, se almacena en el píxel actual de la imagen.

Cualquier punto x de una imagen X se considera un vector respecto del origen, el cual normalmente se sitúa en el punto (0,0).

Page 96: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

2.1.- Definiciones elementales 2.1.1.- Dualidad La Dualidad de operaciones morfológicas se deduce de la existencia del conjunto complementario; de modo que para cada transformación morfológica φ(X) existe una transformación dual φ*(XC) tal que:

φ*(XC) = (φ(X))C

2.1.2.- Traslación La traslación del conjunto de puntos X por el vector h se denota por Xh y se define por:

{ }Xxhxdd ∈∀+=∈= :2EXh 2.1.3.- Complemento de un conjunto El complemento de un conjunto es:

{ }XX C ∉= xx |

2.1.4.- Diferencia de dos conjuntos La diferencia de dos conjuntos X e Y es:

{ }YXYX ∉∈=− xxx ,|

2.2.- Transformaciones morfológicas cuantitativas Una transformación morfológica se denomina cuantitativa si y solo si satisface cuatro principios morfológicos básicos:

a) Compatibilidad con la traslación: sea la transformación φ que depende de la posición del origen O del sistema de coordenadas, y denotemos dicha transformación como φO. Si todos los puntos son trasladados por el vector –h se expresa como φ-h. El principio de compatibilidad con la traslación está dado por:

( ) ( )hhhO XX )(−= φφ

Si φ no depende de la posición del origen O entonces la compatibilidad con el principio de traslación se reduce a la invarianza bajo traslación:

( ) ( )hh XX )(φφ = b) Compatibilidad con el cambio de

escala: supongamos que λX es la homotecia de un conjunto de puntos X, por tanto las coordenadas de cada punto del conjunto se multiplican por alguna constante positiva λ. Esto es equivalente a cambiar la escala con respecto a algún origen. Sea φλ la transformación que depende del parámetro positivo λ (cambio de escala). La compatibilidad con el cambio de escala está dada por:

( )

= XX

λλφφλ

1

Si φ no depende de la escala λ, entonces la compatibilidad con el cambio de escala se reduce a la invarianza al cambio de escala:

( ) )(XX λφλφ = c) Conocimiento local: el principio del

conocimiento local considera la situación en la cual sólo una parte de una determinada estructura puede examinarse.Éste es siempre el caso

d) Continuidad semi-superior. 2.3.- Dilatación La transformación morfológica de la dilatación combina dos conjuntos utilizando la adición de conjuntos de Minkowski:

{ }ByXcadaparaEBXXB ∈∈+=∈=⊕= bxbxdd :2)(δ

Page 97: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

Algunas propiedades de la dilatación resultan interesantes para su implementación:

a) Conmutativa:

XBBX ⊕=⊕

b) Asociativa:

( ) ( ) DBXDBX ⊕⊕=⊕⊕

c) Invariante a la traslación:

( )hh BXBX ⊕=⊕

d) Es una transformación creciente:

BYBXentoncesYXSi ⊕⊆⊕⊆

2.4.- Erosión La transformación morfológica de la erosión combina dos conjuntos utilizando la substracción de vectores:

{ BcadaparaXEBXXB ∈∈+∈=⊗= bbdd :2)(ε }

Algunas propiedades de la erosión son:

a) Si el punto representativo es un miembro del elemento estructural, la erosión es una transformación anti-extensiva:

XBXentoncesBSi ⊆⊕∈)0,0(

b) Es invariante ante la traslación:

hh BXBX )( ⊗=⊗

c) Es una transformación creciente:

BYBXentoncesYXSi ⊗⊆⊗⊆

d) Si B y D son elementos estructurales y D está contenido en B, la erosión por B es más agresiva que por D:

DXBXentoncesBDSi ⊕⊆⊗⊆

2.5.- Relación entre dilatación y erosión La relación entre ambas propiedades se muestra en las siguientes propiedades:

a) La dilatación y la erosión son transformaciones duales:

( )}:{ YyyYdonde

YXYX CC

∈−=

⊕=⊗(

(

b) La erosión no es conmutativa,

mientras que la dilatación sí lo es:

XBBX ⊗≠⊗

c) La dilatación y la intersección no pueden intercambiarse: la dilatación de la intersección de dos imágenes está contenida en la intersección de sus dilataciones:

d) El orden de la erosión (respectivamente dilatación) puede intercambiarse con la unión de conjuntos. Este hecho permite que los elementos estructurales puedan ser descompuestos en una unión de elementos estructurales más simples:

e) La dilatación (erosión) de la imagen X primero por el elemento estructural B seguida del elemento estructural D es equivalente a la dilatación (erosión) de la imagen X por el resultado de la dilatación de B por D:

f) Las transformaciones morfológicas básicas pueden utilizarse para encontrar los contornos de los objetos. Esto puede lograrse, e.g., mediante la operación lógica XOR de la imagen original con la imagen dilatada (o erosionada).

2.6.- Apertura Se trata de una erosión seguida de una dilatación, ambas operaciones con el mismo elemento estructurante:

BBXBXXB ⊕⊗== )()( oγ

Si una imagen X permanece invariable por apertura con respecto al elemento estructural B se dice que es abierta con respecto a B.

Page 98: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

2.7.- Cierre Se trata de una dilatación seguida de una erosión, ambas considerando el mismo elemento estructurante:

BBXBXXB ⊗⊕=•= )()(ϕ

Si una imagen X permanece invariable por cierre con respecto al elemento estructural B se dice que es cerrada con respecto a B. 2.8.- Propiedades de la apertura y el cierre

a) La apertura y el cierre son invariantes a la traslación del elemento estructural.

b) Dado que la dilatación y la erosión son transformaciones crecientes, implica que la apertura y el cierre también lo son.

c) La apertura es anti-extensiva y el cierre es extensivo.

d) La apertura y el cierre son operaciones duales.

e) La apertura y el cierre utilizadas iterativamente son idempotentes, lo que implica que la reaplicación de esas transformaciones no cambia el resultado previo.

2.9.- Cierre asimétrico La apertura y el cierre pueden ser utilizados para detectar esquinas. Sin embargo, presentan los siguientes inconvenientes:

a) La apertura afecta a esquinas claras sobre fondo oscuro, mientras que la erosión detecta mejor las esquinas oscuras sobre fondo claros.

b) Estructuras de la imagen de dimensión reducida (ruido) son detectados erróneamente como esquinas.

c) No son invariantes a la rotación. Por ello se define el cierre asimétrico: una apertura de una imagen por un elemento estructurante, seguida de una erosión por otro elemento estructurante:

))(()()(, XXX +◊◊+ =◊⊗+⊕= δεϕ

El objetivo que se persigue con ello es conseguir que la dilatación y la erosión sean complementarias en términos de las esquinas que detectan (claros/oscuros). Esto se consigue utilizando una cruz en la

dilatación, y un rombo en la erosión. La presencia de esquinas en una imagen se define entonces por el siguiente operador:

)()( , XXX ◊++ −= ϕφ

Pero, con el operador anterior no se resuelve el problema de invariancia a la rotación y sensibilidad a las estructuras de dimensión reducida. Por ello, se define un nuevo operador, cuyos elementos estructurantes están girados 45º respecto del anterior:

)()( , XXX Π×× −= ϕφ

Luego una combinación de ambos operadores puede considerarse suficiente para detectar esquinas en prácticamente todas las orientaciones e insensible a estructuras de dimensión reducida:

)()()( ,,, XXX Π×◊+×+ −= ϕϕφ

Este operador, propuesto por Laganière, debe complementarse con una adecuada umbralización del resultado, con el fin de escoger las esquinas correctas. 3.- Morfología matemática en imágenes en niveles de gris Puede extenderse lo anteriormente expuesto a las imágenes en niveles de gris, considerando para ello que la imagen ahora se representa por una función discreta bimensional f(x,y), con dimensiones M y N. El elemento estructurante también es bidimensional y discreto, b(i,j), con dimensiones m y n. La dilatación en imágenes de niveles de gris se define como:

{ }),(),(max),(1010

jibjyixfyxbfnjmi

+−−=⊕−≤≤−≤≤

La erosión en imágenes de niveles de gris se define como:

{ }),(),(min),(1010

jibjyixfyxbfnjmi

+++=⊗−≤≤−≤≤

Page 99: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

4.- Aplicaciones de los operadores morfológicos El proceso iterativo finaliza cuando: 4.1.- Eliminación de ruido

1−= kK XX Este efecto se consigue realizando primero una erosión y después una dilatación por un elemento estructurante cuadrado de lado 1.

De izquierda a derecha: imagen original, erosión y dilatación de la imagen erosionada. 4.2.- Extracción de contornos Para conseguir el contorno de una región se realiza una erosión a la imagen por un elemento estructurante en forma de cuadrado de lado 1, y a continuación se halla la diferencia de dicha imagen erosionada con la original:

La imagen original está situada en la parte superior izquierda, y a su derecha se ve el resultado del algoritmo en la 1ª iteración. En la parte inferior izquierda muestra la el proceso en la iteración nº 100, y a su derecha el resultado final, en la iteración nº 218.

4.4.- Detección de esquinas

A la izquierda se muestra la imagen original, en el centro la imagen erosionada y a la derecha los contornos extraídos.

Se muestran a continuación los resultados conseguidos aplicando distintos operadores morfológicos a una imagen con diferentes formas para el estudio de los diferentes operadores morfológicos. Las posiciones que se consideran como esquinas se remarcan en color rojo.

4.3.- Rellenado de regiones Para conseguir el rellenado de regiones se precisa como requisito indispensable conocer las coordenadas de un punto del interior de la región a rellenar. Conocido éste, se entra en un proceso iterativo:

( ) CKK ABXX I⊕= −1

donde: • el subíndice K define la iteración K,

• B es el elemento estructurante, que debe ser en forma de cruz,

• A representa a la imagen original

Page 100: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

Imagen Original Apertura por una cruz

Dilatación por una Cruz Cierre por una cruz

Erosión por una cruz Dilatación por cruz y erosión por un rombo:

Page 101: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

Dilatación por un aspa y erosión por un cuadrado:

4.5.- Pruebas con una Marca Fiducial Como aplicación práctica del operador Laganière, se muestran a continuación pruebas realizadas a marcas fiduciales, para de esta forma extraer puntos que permitan automatizar la Orientación Interna.

En primer lugar, se aplica una apertura con un elemento estructurante en forma de cruz. En la parte superior se muestra la imagen original de interés, y a su derecha la imagen diferencia entre la imagen original y la apertura con una cruz, con umbral 10. En la parte inferior, idéntica prueba con umbral 26 en la izquierda, y 100 en la derecha.

Aplicando el operador propuesto por Laganière:

Como puede observarse, los resultados conseguidos son satisfactorios. Ahora bien, los resultados dependen en gran medida del documento original. A tal efecto, al realizar las mismas aperturas a una imagen con peor contraste:

Se puede observar en la última imagen la alta efectividad del operador de Laganière, en comparación con los restantes operadores morfológicos expuestos

Page 102: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

4.6.- Estrategia piramidal

La utilización de estos operadores se puede ampliar utilizando una imagen con la estructura piramidal del archivo BMJ. En la imagen que se muestra a continuación se muestra el último nivel de la pirámide, el más alto, y se pueden comparar los resultados de aplicar todos los operadores morfológicos por una cruz, y luego el operador de Laganière.

los resultados son completamente distintos. Aplicando el operador propuesto por Laganière, con umbrales 10 (superior derecha), 26 y 100 (inferior izquierda y derecha respectivamente), se obtienen los siguientes resultados:

Hay que destacar que el número de detecciones, D, en el caso de umbral 100 ha sido de 2.500, mientras que para la misma imagen pero aplicando una Apertura con una cruz D=11.025.

De izquierda a derecha y de arriba a abajo son: la imagen original y dilatación por una cruz (D=179.900), erosión por una cruz (D=106.800), apertura por una cruz (D=38.255), cierre por una cruz (D=25.600), cierre asimétrico por cruz y rombo (D=25.175), cierre asimétrico por un aspa y cuadrado (D=22.275), y operador de Laganiére (D=425).

.

Page 103: Introducción al manejo de imágenes con Visual Basic.NET …ocw.usal.es/eduCommons/ensenanzas-tecnicas/herramientas-informati... · 1.1.− Introducción al manejo de imágenes con

Las posibilidades de estos operadores son varias, en función de las aplicaciones que se deseen. Estos resultados demuestran que se pueden utilizar en estrategias piramidales de búsquedas, en toda su amplitud. En concreto, el operador propuesto por Laganière proporciona resultados altamente efectivos. Bibliografía ARIAS PÉREZ, B., Empleo de imágenes piramidales, Topografía y Cartografía, núm. 118-119, Vol. XX, Madrid, 2003. ARIAS PÉREZ, B., La programación orientada a objetos en Fotogrametría, Datum XXI, núm. 2, Año I, Madrid, 2002. PAJARES MARTINSANZ, G., DE LA CRUZ GARCÍA, J.M., Visión por computador. Imágenes digitales y aplicaciones, RA-MA Editorial, 2001, Madrid. ROCHA, A., FERREIRA, R., Mosaico de imagens, Faculdade de Engenharia da Universidade do Porto, Licenciatura em Engenharia Electrotécnica e de Computadores, 2000. SERRA, J., Curso sobre Morfología Matemática, Centre de Morphologie Mathématique, Ecole des Mines de Paris, 2000.