Descargar el proyecto en

Transcripción

Descargar el proyecto en
Desarrollo de algoritmos de
procesamiento de imágenes
con VTK
Autor: Ignacio Berzal Moreno
Tutor: Carlos Platero Dueñas
Hace unos cuantos años ya que entré en la Universidad (más de los que me
gustaría), con un propósito: llegar a ser ingeniero. En ese momento parecía una meta
muy lejana pero...¡por fin ha llegado el momento! Tras todos estos años de estudios,
este proyecto es el encargado de poner fin a esta etapa de mi vida.
Quiero dedicar este proyecto a toda la gente que me ha apoyado durante estos
años, y que ha confiado en mi, a mis padres, a mi novia Paloma (siempre estás ahí), y
a todos mis amigos (ellos saben quienes son). También quiero dedicárselo a todos los
compañeros de universidad con los que he compartido estos años de clases,
exámenes, prácticas, y agobios varios, y en especial a mis compañeros del GVA,
Nuria, Nacho, David, Laura, Isaac y Mihai, con los que más he “sufrido” este último
año. Mención especial por supuesto, para mi tutor en este proyecto Carlos Platero.
GRACIAS A TODOS!!!!!
Nacho
Resumen
Este proyecto queda englobado en el conjunto de las líneas de investigación
del Grupo de Visión Artificial (GVA) de la Escuela Universitaria de Ingeniería
Técnica Industrial de la UPM, perteneciendo a la cátedra del ELAI de dicha escuela.
El objetivo principal de este grupo es el desarrollo de aplicaciones software para el
procesamiento de imágenes biomédicas.
Mediante el uso de la informática se desarrollan aplicaciones de
procesamiento de imágenes que resuelven muchos problemas al profesional de la
salud a la hora de elaborar un diagnóstico fiable. Es en este campo donde se
desarrolla el presente proyecto, en la implementación y análisis de algoritmos de
visión que permitan procesar de forma adecuada imágenes biomédicas por
computador.
Para lograr estos objetivos se ha empleado principalmente la herramienta
software VTK, aplicada a la programación con C++. También se trata de exponer la
técnica de modelado UML, muy útil para el proceso de creación de aplicaciones.
La realización de este trabajo tuvo lugar durante los años 2003 y 2004, y
cuenta con diversas líneas que seguirán siendo fructíferas en el futuro.
Abstract
This project is included in the group of the lines of investigation of the Group
of Artificial Vision (GVA) of the Escuela Universitaria de Ingeniería Técnica
Industrial of the UPM, belonging to the class of the ELAI of this school. The main
objective of this group is the development of applications software for the processing
of biomedical images.
By means of the computer science's use applications of processing of images
are developed that solve many problems to the professional of the health when
elaborating a reliable diagnosis. It is in this field where the present project is
developed, in the implementation and analysis of algorithms of vision that allow to
process in way appropriate biomedical images for computer.
To achieve these objectives mainly the tool software VTK it has been used,
applied to the programming with C++. It is also to expose the technique of modeling
UML, very useful for the process of creation of applications.
The realization of this work took place during the years 2003 and 2004, and it
has diverse lines that will continue being fruitful in the future.
Índice
1
Introducción ...........................1
1.1 Objetivos ...............................................................................2
1.2 Sumario del proyecto ...........................................................3
2
Estado de la técnica................5
2.1 Herramientas de visualización de imágenes ......................5
2.1.1 Matlab .........................................................................................5
2.1.1.1 Procesado de imágenes con MATLAB ..........................7
2.1.2 SDC .............................................................................................7
2.1.3 VTK .............................................................................................8
2.1.3.1 Visualización con VTK ..................................................9
2.1.4 ParaView .....................................................................................9
2.1.5 ITK .............................................................................................11
2.1.6 OpenMoxis ................................................................................12
2.1.7 MPI ............................................................................................13
GVA-ELAI-UPM®PFC0081-2004
3
Funcionamiento de VTK ........15
3.1 Instalación de VTK...............................................................16
3.1.1 Instalación binaria ....................................................................16
3.1.2 Instalación del código fuente . .................................................17
3.2 Funcionamiento en C++ de VTK.........................................17
3.2.1 CMake .....................................................................................17
3.2.2 Arquitectura de VTK.................................................................18
3.2.2.1 Graphics model ...........................................................19
3.2.2.2 Visualization model ......................................................20
3.2.2.2.1 Ejecución del pipeline.....................................23
3.2.2.2.2 Procesamiento de la imagen..........................24
3.2.3 Creación de una aplicación .......................................................24
3.3 Ejemplos...............................................................................25
3.3.1 Renderización de un cilindro......................................................25
3.3.2 Renderización de un cono.........................................................27
3.3.3 Manipulación de luces................................................................30
4
Fases de la reconstrucción
3D.................................................... 37
4.1 Conversión del dominio de adquisición al mallado
(marching cubes).......................................................................38
4.2 Reducción de puntos de mallado ......................................40
GVA-ELAI-UPM®PFC0081-2004
4.3 Suavizado del mallado ........................................................41
5
Aplicaciones sobre una pila
de imágenes del confocal ............45
5.1 Desarrollo del pipeline.........................................................46
5.2 Leer los datos de la pila de imagen ...................................47
5.3 Trasladar islas .....................................................................48
5.4 Seleccionar una superficie .................................................50
5.5 Remuestreo de volumen ....................................................52
5.6 Alisar los datos de volumen ..............................................53
5.7 Generar triángulos ..............................................................55
5.8 Reducir el número de triángulos .......................................55
5.9 Alisar vértices de triángulos ..............................................57
5.10 Generar ejemplares ...........................................................58
5.11 Generar strips de triángulos ............................................60
5.12 Escribir triángulos a un fichero .......................................60
5.13 Ejecutar el pipeline ...........................................................61
5.14 Especificar parámetros para el pipeline .........................61
5.15 Ejemplo...............................................................................62
GVA-ELAI-UPM®PFC0081-2004
6
Combinación de la difusión
isotrópica y anisotrópica en el
procesamiento de imágenes ........69
6.1 Introducción al filtrado de difusión ...................................69
6.2 Difusión anisotrópica de realce de la coherencia local...71
6.3 Condiciones de difusión anisotrópica e isotrópica de CED
.....................................................................................................75
6.4 Combinación de la difusión isotrópica y anisotrópica ....76
6.4.1 Resultados de difusión isotrópica y anisotrópica.
Ejemplos............................................................................................77
7
Aplicación del filtrado de
difusión con imágenes JPG y PIC
.........................................................83
7.1 Modelado UML ....................................................................83
7.1.1 Introducción ...............................................................................83
7.1.2 Modelado visual ........................................................................85
7.1.3 ¿Qué es UML? ..........................................................................85
7.1.4 Diagramas UML ........................................................................86
7.1.5 Proceso de desarrollo ...............................................................89
GVA-ELAI-UPM®PFC0081-2004
7.2 La herramienta Rational Rose ...........................................91
7.3 Documentación de la aplicación difusión2D3D ...............91
7.3.1 Visión y alcance de la aplicación...............................................92
7.3.1.1 Requerimientos del negocio ........................................92
7.3.1.1.1 Introducción ............................................... ...92
7.3.1.1.2 Oportunidad del negocio.................................93
7.3.1.1.3 Objetivos esenciales y criterios de éxito ........93
7.3.1.1.4 Necesidades de los usuarios .........................93
7.3.1.1.5 Riesgos del negocio ......................................94
7.3.1.2 Visión de la solución ....................................................94
7.3.1.2.1 Visión global ...................................................94
7.3.1.2.2 Principales características .............................95
7.3.1.2.3 Suposiciones y dependencias.......................95
7.3.1.3 Alcance y restricciones ................................................96
7.3.1.3.1 Características principales en la primera
versión ..........................................................................96
7.3.1.3.2 Mejoras en las siguientes versiones ..............96
7.3.1.3.3 Limitaciones y Exclusiones ............................97
7.3.2 Casos de uso ............................................................................97
7.3.2.1
Caso de uso visualizar 2D ........................................97
7.3.2.1.1 Actor ...............................................................97
7.3.2.1.2 Descripción ....................................................98
7.3.2.1.3 Precondiciones .............................................98
7.3.2.1.4 Poscondiciones .............................................98
7.3.2.1.5 Curso de éxito ...............................................98
7.3.2.1.6 Curso alternativo ..........................................99
7.3.2.1.7 Excepciones .................................................99
7.3.2.1.8 Prioridad .......................................................99
7.3.2.1.9 Frecuencia de caso de uso ...........................99
GVA-ELAI-UPM®PFC0081-2004
7.3.2.1.10 Requerimientos especiales ......................100
7.3.2.1.11 Suposiciones de partida ..........................100
7.3.2.1.12
Cuadro resumen del caso de uso visualizar
2D ...............................................................................100
7.3.2.2
Caso de uso visualizar 3D ......................................101
7.3.2.2.1 Actor .............................................................101
7.3.2.2.2 Descripción ..................................................101
7.3.2.2.3 Precondiciones ...........................................101
7.3.2.2.4 Poscondiciones ...........................................101
7.3.2.2.5 Curso de éxito ..............................................102
7.3.2.2.6 Curso alternativo ........................................102
7.3.2.2.7 Excepciones ...............................................102
7.3.2.2.8 Prioridad .....................................................103
7.3.2.2.9 Frecuencia de caso de uso .........................103
7.3.2.2.10 Requerimientos especiales ......................103
7.3.2.2.11 Suposiciones de partida ..........................103
7.3.2.2.12
Cuadro resumen del caso de uso visualizar
3D ...............................................................................104
7.3.2.3
Caso de uso filtrar difusión 2D ...............................104
7.3.2.3.1 Actor ............................................................104
7.3.2.3.2 Descripción ..................................................105
7.3.2.3.3 Precondiciones ...........................................105
7.3.2.3.4 Poscondiciones ...........................................105
7.3.2.3.5 Curso de éxito ..............................................105
7.3.2.3.6 Curso alternativo ........................................106
7.3.2.3.7 Excepciones ...............................................106
7.3.2.3.8 Prioridad .....................................................106
7.3.2.3.9 Frecuencia de caso de uso .........................107
GVA-ELAI-UPM®PFC0081-2004
7.3.2.3.10 Requerimientos especiales ......................107
7.3.2.3.11 Suposiciones de partida ..........................107
7.3.2.3.12
Cuadro resumen del caso de uso filtrar
difusión 2D...................................................................107
7.3.2.4
Caso de uso filtrar difusión 3D ...............................108
7.3.2.4.1 Actor .............................................................108
7.3.2.4.2 Descripción ..................................................108
7.3.2.4.3 Precondiciones ...........................................109
7.3.2.4.4 Poscondiciones ...........................................109
7.3.2.4.5 Curso de éxito ..............................................109
7.3.2.4.6 Curso alternativo ........................................109
7.3.2.4.7 Excepciones ...............................................110
7.3.2.4.8 Prioridad .....................................................110
7.3.2.4.9 Frecuencia de caso de uso .........................110
7.3.2.4.10 Requerimientos especiales ......................111
7.3.2.4.11 Suposiciones de partida ..........................111
7.3.2.4.12
Cuadro resumen del caso de uso filtrar
difusión 3D ..................................................................111
7.4 Creación de la aplicación mediante Rational Rose .......112
7.4.1 Creación del proyecto .............................................................112
7.4.2 Creación de casos de uso ......................................................113
7.4.3 Creación del diagrama de clases del modelo de análisis ......114
7.4.4 Creación del diagrama de secuencia ......................................115
7.4.5 Creación del diagrama de clases del diseño ..........................116
7.4.6 Generación de código mediante Rational Rose ......................117
7.4.7 Ingeniería inversa ....................................................................121
7.4.7.1 Configuración de Rational Rose: Visual C++ Add-in..122
7.4.7.2 Ingeniería inversa con una aplicación .......................124
7.5 Implementación del código ..............................................128
7.5.1 Descripción de las clases empleadas en la aplicación ...........129
GVA-ELAI-UPM®PFC0081-2004
7.5.1.1 Clase visualización2D ...............................................129
7.5.1.2 Clase visualización3D ...............................................132
7.5.1.3 Clase filtradoDifusión2D ............................................138
7.5.1.4 Clase filtradoDifusión3D ............................................143
7.5.1.5 Clase vistaFiltradoDifusión2D3D ...............................150
7.5.2 Fichero principal de la aplicación ............................................155
7.5.3 Archivo CMakeLists ................................................................156
8
Conclusiones ......................157
8.1 Principales aportaciones ..................................................157
8.2 Futuras mejoras ................................................................158
9
Bibliografía .........................161
GVA-ELAI-UPM®PFC0081-2004
GVA-ELAI-UPM®PFC0081-2004
GVA-ELAI-UPM®PFC0081-2004
1
Introducción
El marco del presente proyecto se desarrolla en un campo que ha ido
ampliando horizontes en los últimos años, la Visión Artificial. La visualización se
puede definir como el proceso de explorar, transformar y mostrar datos en forma de
imágenes para comprender y apreciar adecuadamente las características de los
mismos.
Se entiende por procesamiento digital de imágenes la manipulación de las
mismas a través de un computador, de modo que la entrada y la salida del proceso
sean imágenes. Por otro lado, la elaboración de gráficos por computador envuelve la
creación de imágenes a partir de descripciones de las mismas.
La disponibilidad de hardware dedicado, hace posible en la actualidad realizar
aplicaciones tanto de visualización de superficies como de visualización volumétrica
en plataformas de relativo bajo coste.
GVA-ELAI-UPM®PFC0081-2004
1
I
n
t
r
o
d
u
c
c
i
ó
n
I
g
n
a
c
i
o
B
e
r
z
a
l
M
o
r
e
n
o
El objetivo de utilizar el procesamiento digital de imágenes, es mejorar el
aspecto visual de ciertos elementos estructurales para el analista y proveer otras
herramientas para su interpretación, inclusive generando productos que puedan ser
posteriormente sometidos a otros procesamientos.
Éste área ha generado un gran interés en las dos últimas décadas. Tanto la
evolución de la tecnología de computación, como el desarrollo de nuevos algoritmos
para tratar señales bidimensionales y tridimensionales está permitiendo una gama de
aplicaciones cada vez mayor.
Actualmente, estas técnicas de Visión Artificial están tomando un gran
impulso e importancia en el campo de la biomedicina, donde se están estableciendo
plataformas de investigación en la línea de desarrollar sistemas de visión artificial
que permitan automatizar análisis y diagnósticos de los profesionales de la
biomedicina. Son muchas las técnicas de procesamiento digital empleadas en el
campo de la medicina. Estas van desde la mejora del contraste y la detección de
contornos, hasta los más complejos sistemas de reconocimiento de patrones y
reconstrucciones tridimensionales.
Es en este campo donde se desarrolla el presente proyecto, en la
implementación y análisis de algoritmos de visión que permitan procesar de forma
adecuada imágenes biomédicas por computador.
1.1
Objetivos
Los objetivos principales sobre los que profundizaremos a la largo de los
capítulos de este proyecto son los expuestos a continuación:
Estudio de la herramienta de visualización y procesamiento de
imágenes VTK.
Análisis de las fases de la reconstrucción de imágenes 3D, poniendo
especial atención en la técnica de Marching Cubes.
Aplicación de las librerías VTK para la reconstrucción 3D de
imágenes biomédicas provenientes de una pila de imágenes 2D del
microscopio confocal.
Estudio de las técnicas de filtrado de difusión isotrópica y anisotrópica
en el procesamiento de imágenes.
2
GVA-ELAI-UPM®PFC0081-2004
I
g
n
a
c
i
o
B
e
r
z
a
l
M
o
r
e
n
o
I
n
t
r
o
d
u
c
c
i
ó
n
Desarrollo de una aplicación, implementada en C++ y usando las
librerías VTK, que permita al usuario la visualización y/o filtrado de
difusión de imágenes en dos y tres dimensiones. Esta aplicación será
creada según las técnicas del modelado UML, mediante su
herramienta software, Rational Rose.
Todos estos puntos están íntimamente ligados, unos conducen a otros, para al
final obtener el objetivo principal, la aplicación de las librerías de VTK para facilitar
la correcta visualización y procesamiento de imágenes.
1.2
Sumario del proyecto
Este proyecto consta de nueve capítulos, los cuáles expondremos brevemente
a continuación.
En el segundo capítulo se muestra una visión general de las herramientas
software de visualización de imágenes más empleadas en la actualidad, como son
MATLAB, VTK o ITK entre otras.
En el tercer capítulo profundizamos en la herramienta de visualización VTK,
tratando desde su instalación, hasta su arquitectura, viendo todas las posibilidades
que ofrecen estas librerías, y finalizando con varios ejemplos de aplicaciones en
C++.
El cuarto capítulo trata sobre las fases de la reconstrucción de imágenes 3D,
centrándose en el algoritmo de conversión del dominio de adquisición al mallado,
llamado Marching Cubes. También se tratarán las técnicas de reducción de puntos de
mallado y el suavizado del mismo. Todo ello se hará de forma teórica, pero
basándose en las librerías software VTK.
En el quinto capítulo se describe una de las principales aplicaciones de VTK
sobre las que se centra este proyecto, la reconstrucción de una imagen en tres
dimensiones a partir de una pila de imágenes en 2D obtenidas a través de un
microscopio confocal. Se mostrará un pipeline genérico, y se verá su resultado con
un ejemplo, aplicado sobre una pila de imágenes de una neurona madre.
El sexto capítulo lleva a cabo una exposición teórica sobre la combinación de
la difusión isotrópica y anisotrópica en el procesamiento de imágenes, esto es,
combinar ambos tipos de filtrado según convenga, con el objetivo de mejorar el
aspecto visual de una imagen, aplicando diferentes algoritmos.
El séptimo capítulo es el más extenso, y trata de aplicar todo lo introducido en
los capítulos anteriores en la creación de una aplicación cuyo código estará
implementado en C++ y VTK. Esta aplicación se creará siguiendo los pasos del
GVA-ELAI-UPM®PFC0081-2004
3
I
n
t
r
o
d
u
c
c
i
ó
n
I
g
n
a
c
i
o
B
e
r
z
a
l
M
o
r
e
n
o
modelado UML, mediante la herramienta software Rational Rose, por lo tanto, antes
de llevar a cabo la exposición detallada del proceso de creación de la aplicación, se
hará una introducción sobre las bases de esta filosofía de trabajo. La aplicación final
permitirá al usuario llevar a cabo la visualización y/o filtrado de difusión de
imágenes en dos y tres dimensiones con formato JPG y PIC respectivamente.
El octavo capítulo expresa las conclusiones finales, y en él se exponen las
principales aportaciones del proyecto, así como sus limitaciones y futuras mejoras.
Por último, en el noveno capítulo se incluyen las referencias bibliográficas
que se han empleado para la realización de este proyecto.
4
GVA-ELAI-UPM®PFC0081-2004
2
Estado de la técnica
2.1 Herramientas de visualización de imágenes
Existen distintas herramientas para la visualización de imágenes mediante un
soporte informático. En este capítulo trataremos con brevedad algunas de ellas.
2.1.1 Matlab
MATLAB es un lenguaje de alto nivel que incluye herramientas de cálculo
numérico y visualización de imágenes. Es un programa de Mathworks orientado para
realizar todo tipo de cálculos con vectores y matrices. También presenta la
posibilidad de realizar gráficos en dos y tres dimensiones.
MATLAB es una herramienta muy potente que realiza con gran precisión
operaciones complejas. Se emplea en todo tipo de aplicaciones donde se trabaja con
funciones matemáticas o matrices. Su entorno gráfico es simple y su aprendizaje no
requiere gran esfuerzo, lo que hace que sea uno de los lenguajes más empleados en el
ámbito científico.
GVA-ELAI-UPM®PFC0081-2004
5
E
s
t
a
d
o
d
e
l
a
t
é
c
n
i
c
a
I
g
n
a
c
i
o
B
e
r
z
a
l
M
o
r
e
n
o
Figura 2.1: Logo de MATLAB
MATLAB posee unas librerías especializadas para distintos tipos de
aplicaciones llamadas toolboxes. Estas toolboxes contienen una colección de
funciones (M-files) que extienden el dominio de MATLAB para resolver problemas
de ámbitos particulares. Existen muchas áreas de trabajo para las que hay disponibles
toolboxes específicas, como por ejemplo el procesado de señales y de imágenes, la
lógica difusa, los sistemas de control, etc. También permiten llevar a cabo
simulaciones usando diferentes parámetros, que permiten analizar el comportamiento
de diferentes sistemas.
Figura 2.2: Interfaz de MATLAB
6
GVA-ELAI-UPM®PFC0081-2004
I
g
n
a
c
i
o
B
e
r
z
a
l
M
o
r
e
n
o
E
s
t
a
d
o
d
e
l
a
t
é
c
n
i
c
a
2.1.1.1 Procesado de imágenes con MATLAB
MATLAB posee una toolbox de procesado de imágenes que proporciona un
conjunto de funciones y herramientas para el análisis y visualización de imágenes
digitales, así como para el desarrollo de algoritmos.
Esta toolbox proporciona a científicos, investigadores e ingenieros un
conjunto flexible de herramientas para resolver problemas complejos en el
tratamiento de imágenes.
Muchas de las funciones de esta toolbox están implementadas de manera
abierta, es decir podemos acceder a su código fuente y alterar los algoritmos según
nuestras necesidades, o incluso desarrollar otros nuevos. Mediante esta toolbox
podemos restaurar o degradar las imágenes, así como extraer y analizar datos de las
mismas. Estas técnicas resultan muy útiles en campos como la astronomía, el control
remoto, la industria aeroespacial, la medicina y la bioingeniería.
2.1.2 SDC
SDC Morphology Toolbox para MATLAB es un software para el análisis de
imágenes y procesamiento de señales. Está compuesto por una familia de filtros
discretos, no lineales. Éstos filtros, llamados operadores morfológicos, son muy
útiles para restauración, segmentación y análisis cuantitativo de imágenes y señales.
Figura 2.3: Logo de SDC
Las SDC Morphology Toolbox trabajan con escala de grises e imágenes
binarias (o señales). Así, la mayoría de los operadores realizan el procesamiento en
escala de grises o imagen binaria y la selección de la apropiada del algoritmo
automáticamente. Las imágenes (o señales) pueden ser representadas por los
formatos: binario, 8- báscula de bit-gris y 16-báscula de bit-gris, donde cada píxel es
representado, respectivamente, por un tipo de datos lógico uint8, un uint8 y uint16.
Los operadores morfológicos pueden ser escritos jerárquicamente a partir de dos
operadores elementales: dilatación y erosión. SDC tiene unas herramientas muy
eficientes para la dilatación y erosión. Sin embargo, para obtener más eficiencia,
varios operadores son tratados también por algoritmos rápidos especiales. Algunos
de estos operadores son de transformación de la distancia, reconstrucción,
GVA-ELAI-UPM®PFC0081-2004
7
E
s
t
a
d
o
d
e
l
a
t
é
c
n
i
c
a
I
g
n
a
c
i
o
B
e
r
z
a
l
M
o
r
e
n
o
etiquetando y apertura de áreas. Dilataciones y erosiones son parametrizadas por
imágenes particulares (o señales), llamadas elementos estructurantes.
La SDC Morphology Toolbox puede funcionar bajo 3 plataformas: Win
95/98/NT, Linux y Solaris. SDC depende de la versión de Matlab 5, o superior. No
depende de ninguna otra toolbox.
2.1.3 VTK
VTK (Visualization Toolkit) es un conjunto de librerías de código y
distribución libres destinadas a la visualización y el procesado de imágenes, basadas
en la programación orientada a objetos. Son muy amplias y complejas, pero aún así,
están diseñadas para ser sencillas de emplear con cualquier lenguaje de programación
orientado a objetos, como pueden ser C++, Java, Tcl…. Son capaces de realizar
operaciones sobre imágenes en dos y tres dimensiones y de generar modelos en las
mismas con pocas líneas de código. Debido a su gran potencia, se hacen necesarios
amplios recursos de memoria en el PC para poder aprovechar en su totalidad sus
funcionalidades.
Figura 2.4: Logo de VTK
El modelo gráfico de VTK posee un nivel de abstracción mucho mayor que el
de otras librerías de renderización de imágenes como OpenGL o PEX. Esto se
traduce en una mayor sencillez a la hora de implementar aplicaciones gráficas o de
visualización con VTK. Además, las aplicaciones creadas empleando VTK pueden
ser escritas directamente en Tcl, Java, Pitón o C++, lo que aumenta y facilita la
posibilidad de implementar aplicaciones en poco tiempo.
Por otra parte, este software es un sistema de visualización que no sólo nos
permite visualizar geometría, sino que además soporta una amplia variedad de
algoritmos de visualización, incluyendo métodos escalares, vectoriales, tensores, de
textura y volumétricos, además de otras modernas técnicas de modelado, como la
reducción poligonal, el contorneado, la técnica de marching cubes, etc.
8
GVA-ELAI-UPM®PFC0081-2004
I
g
n
a
c
i
o
B
e
r
z
2.1.3.1
a
l
M
o
r
e
n
o
E
s
t
a
d
o
d
e
l
a
t
é
c
n
i
c
a
Visualización con VTK
En VTK, el procesamiento de los datos se realiza a través de un pipeline.
Una vez los datos entran en el pipeline, pueden ser afectados por multitud de
procesos o transformaciones. Para leer los datos se debe emplear el reader (lector)
apropiado para el tipo de dato. Una vez hecho esto, pueden aplicárseles diferentes
tipos de filtros, que alteren los datos de la manera deseada, o definir el tipo de
renderización entre otras muchas cosas.
VTK es la herramienta principal empleada en la realización de este proyecto,
por lo que profundizaremos en su empleo y características en capítulos posteriores,
aunque como muestra de sus posibilidades, incluiremos a continuación un ejemplo
de imágen obtenida a partir de estas librerías:
Figura 2.5: Figura procesada con VTK
2.1.4 ParaView
ParaView es una aplicación diseñada debido a la necesidad de visualizar
archivos con gran cantidad de datos. Los objetivos del proyecto de ParaView,
incluyen lo siguiente:
• Desarrollar un código abierto para la visualización multiplataforma.
• Soportar lo modelos de programación distribuída para procesar conjuntos de datos
complejos.
• Crear una interface de usuario abierta, flexible e intuitiva.
GVA-ELAI-UPM®PFC0081-2004
9
E
s
t
a
d
o
d
e
l
a
t
é
c
n
i
c
a
I
g
n
a
c
i
o
B
e
r
z
a
l
M
o
r
e
n
o
• Desarrollar una arquitectura extensible basada en estándares abiertos.
Figura 2.6: Logo de Paraview
ParaView puede funcionar tanto en sistemas distribuidos en paralelo y de
memoria compartida como en sistemas de procesador único. Puede emplearse bajo
Windows, Linux o Unix.
ParaView utiliza VTK como base de procesamiento de datos y motor de la
renderización y visualización. Posee una interfaz escrita mediante una mezcla única
de Tcl/Tk y de C++.
Figura 2.7: Interfaz de Paraview
10
GVA-ELAI-UPM®PFC0081-2004
I
g
n
a
c
i
o
B
e
r
z
a
l
M
o
r
e
n
o
E
s
t
a
d
o
d
e
l
a
t
é
c
n
i
c
a
El objetivo principal de la creación de ParaView es el desarrollo de una
herramienta que emplee el procesamiento distribuido de memoria de manera paralela
y escalable. El proyecto incluye algoritmos de trabajo en paralelo, infraestructura de
entrada y salida, ayuda, y dispositivos de demostración. Una característica
significativa es que todo el software desarrollado está escrito en código abierto, lo
que implica que ParaView está disponible gratuitamente.
2.1.5 ITK
ITK es una herramienta software de código libre para la ejecución
del registrado y segmentación. La segmentación es el proceso de identificar y
clasificar los datos encontrados en una representación muestreada digitalmente.
Típicamente, la representación muestreada será una imagen adquirida mediante
instrumentación médica, como el CT o el escáner MRI. El registrado consiste en
alinear o desarrollar correspondencias entre los datos. Por ejemplo, en el ámbito de la
medicina, un escáner CT puede ser alineado con un MRI para combinar la
información proporcionada por ambos.
Figura 2.8: Logo de ITK
ITK está implementado en C++, y es multiplataforma gracias al empleo
de la aplicación CMake para dirigir el proceso de compilación. Además, un proceso
automático de “interpretación” genera interfaces entre C++ y otros lenguajes como
Tcl, Java, y Python. Esto permite a los programadores desarrollar aplicaciones en
cualquiera de estos lenguajes.
GVA-ELAI-UPM®PFC0081-2004
11
E
s
t
a
d
o
d
e
l
a
t
é
c
n
i
c
a
I
g
n
a
c
i
o
B
e
r
z
a
l
M
o
r
e
n
o
Figura 2.9: Ejemplo de imagen binarizada con ITK
Gracias a que ITK es un software de código libre, cualquier persona puede
contribuir a depurarlo, mantenerlo e incluso extenderlo. ITK usa un modelo de
desarrollo de software que se conoce como “programación extrema”. Este estilo de
programación cambia la metodología clásica por un proceso simultáneo e iterativo de
diseño, implementación y testeado. La clave está en la comunicación entre los
miembros de la comunidad de usuarios de ITK, que ayuda a una rápida evolución
del software. El proceso de testeado es el que hace el software estable.
2.1.6 OpenMoxis
Podríamos decir que OpenMosix se creó como una modificación de Linux, ya
que consiste en un conjunto de parches añadidos a su kernel, que permiten una
distribución automática y transparente de la carga de tareas a lo largo de las
máquinas que forman el cluster. Y todo ello sin tener que modificar el código del
programa.
Figura 2.10: Logo de OpenMoxis
12
GVA-ELAI-UPM®PFC0081-2004
I
g
n
a
c
i
o
B
e
r
z
a
l
M
o
r
e
n
o
E
s
t
a
d
o
d
e
l
a
t
é
c
n
i
c
a
Con OpenMosix se puede iniciar un proceso en una computadora y
comprobar si se ejecuta en otra, en el seno del cluster. Cada proceso tiene su único
nodo raíz (UHN, unique home node) que se corresponde con el que lo ha generado.
El concepto de migración se refiere al hecho de que un proceso se divide en
dos partes: la parte del usuario y la del sistema. La parte, o área, de usuario será
movida al nodo remoto, mientras el área de sistema espera en el nodo raíz.
OpenMosix se encargará de establecer la comunicación entre estos dos procesos,
pudiendo migrarse cualquiera proceso a cualquier nodo del cluster de forma
completamente transparente al proceso migrado (mecanismo de migración).
La idea de este modelo es que la distribución de tareas en el cluster la
determina OpenMosix de forma dinámica, conforme se van creando tareas. Cuando
un nodo está demasiado cargado, las tareas que se están ejecutando migran a
cualquier otro nodo del cluster. Así desde que se ejecuta una tarea hasta que ésta
finaliza, podrá migrar de un nodo a otro, sin que el proceso sufra mayores cambios.
El empleo de OpenMoxis tiene como ventajas el hecho de que no son
necesarias modificaciones en el código, ni la instalación de paquetes extra, aunque
también tiene varios puntos negativos, entre los que están su dependencia del kernel
(núcleo del sistema operativo), limitaciones de funcionamiento en los procesos de
migración, y ciertos problemas con la memoria compartida entre procesos.
2.1.7 MPI
MPI es un estándar creado por un amplio conjunto de expertos y usuarios con
el objetivo de definir una infraestructura común y una semántica específica de
interfaz de comunicación. De esta forma los productores de software de
procesamiento en paralelo pueden implementar su propia versión de MPI siguiendo
las especificaciones de este estándar, con lo cual múltiples implementaciones de MPI
cambiarían solamente en factores tales como la eficiencia de su implementación y
herramientas de desarrollo, pero no en sus principios básicos.
Figura 2.11: Logo de MPI
GVA-ELAI-UPM®PFC0081-2004
13
E
s
t
a
d
o
d
e
l
a
t
é
c
n
i
c
a
I
g
n
a
c
i
o
B
e
r
z
a
l
M
o
r
e
n
o
Actualmente existen diferentes implementaciones de MPI, algunas son
comerciales y otras son de libre circulación y adaptables a múltiples arquitecturas.
Una de ellas es MPICH, que es un ambiente de desarrollo y programación de MPI
orientado a arquitecturas heterogéneas de ordenadores distribuidos en una red local.
Con MPICH, tanto un "cluster" dedicado, como una simple red local de ordenadores,
pueden actuar como un ordenador multiprocesador.
Figura 2.12: Logo MPICH
14
GVA-ELAI-UPM®PFC0081-2004
3
Funcionamiento de VTK
The Visualization Toolkit (VTK) es un conjunto de librerías de código libre
basadas en la programación orientada a objetos. Están destinadas a la visualización y
el procesamiento de imágenes, así como a la creación de objetos gráficos en 2D y 3D
mediante el PC.
VTK esta constituido por dos subsistemas, una librería de clases compilada
en C++ y varios “interpretes” que permiten la manipulación de estas clases
compiladas en lenguajes Java, Tcl/Tk y Python. Por tanto las aplicaciones de VTK
pueden ser escritas directamente en cualquiera de estos lenguajes.
Esta software es un sistema de visualización que no sólo nos permite
visualizar geometría, sino que además soporta una amplia variedad de algoritmos de
visualización y otras modernas técnicas de modelado.
Debido a su gran potencia, se hacen necesarios amplios recursos de memoria
en el PC para poder aprovechar en su totalidad sus funcionalidades.
GVA-ELAI-UPM®PFC0081-2004
15
Funcionamiento de VTK
Ignacio Berzal Moreno
3.1 Instalación de VTK
Hay dos tipos de instalación bajo el entorno de Windows. La primera es una
instalación binaria, con la que podremos desarrollar aplicaciones en C++, Java, Tcl y
Python para compilar y lincar. La segunda es una instalación completa del código
fuente, que requiere la compilación del código fuente de VTK (para generar librerías
C++) y del código “envolvente” de VTK (para generar ejecutables en Java, Tcl y
Python). De los dos tipos de instalaciones, la instalación binaria es mas sencilla y por
tanto la recomendada.
3.1.1 Instalación binaria
Para instalar las librerías y ejecutables de VTK hacemos doble clic sobre el
icono setup.exe que se encuentra en el CD-ROM, comenzando el proceso de
instalación. Aparecerá la siguiente ventana:
Figura 3.1 : Instalación binaria
16
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Funcionamiento de VTK
En esta ventana tendremos que elegir las partes de VTK que necesitemos
instalar dependiendo del uso que vayamos a hacer del programa. Así mismo, el
VTK4.2 y el CMake serán instalados automáticamente.
3.1.2 Instalación del código fuente
Esta instalación es necesaria para desarrollar aplicaciones en C++, crear
nuevas librerías y extenderlas a VTK, y para alterar o mejorar las ya existentes.
Primero debemos asegurarnos de tener un compilador de C++ instalado en el
ordenador y, dependiendo de los lenguajes que vayamos a usar, compiladores para
estos lenguajes (Java, Tcl\Tk o Python). Después copiamos el código fuente
directamente de la carpeta VTK-src-windows del CD al disco duro. Finalmente,
compilaremos este código fuente con el compilador de C++, con la ayuda de la
aplicación CMake. Este proceso puede durar varias horas. Sin embargo, esta
instalación tiene como beneficio la mejora del tiempo de compilación.
Como hemos indicado, para compilar VTK es necesario instalar previamente
CMake. Para ello hacemos doble clic sobre el icono CMSetup.exe que se encuentra
dentro de la carpeta Binaries localizada en la carpeta CMake del CDROM, iniciando
el proceso de instalación.
3.2 Funcionamiento en C++ de VTK
3.2.1 CMake
Para poder ejecutar un código fuente escrito en C++ con VTK es necesario el
uso de la aplicación CMake.
El CMake es una herramienta multiplataforma de código libre empleada para
configurar y dirigir el proceso de construcción de aplicaciones. Ficheros
independientes llamados CMakeLists.txt se usan para describir el proceso de
construcción y establecer las dependencias. Cuando ejecutamos CMake, se generan
los ficheros necesarios, dependiendo del compilador y sistema operativo que estemos
utilizando. Esto sirve para compilar VTK fácilmente, y trabajar con herramientas
propias de la plataforma en la que estemos trabajando.
Para hacer funcionar el CMake hacemos doble click en el icono
CMakeSetup.exe y a continuación aparecerá el GUI que se muestra en la figura 3.2.
El CMake necesita tres datos, que deben ser indicados antes de su ejecución:
el compilador que va a ser empleado, la dirección del código fuente y la dirección
donde se generarán el código objeto, las librerías y los binarios producidos en la
compilación.
GVA-ELAI-UPM®PFC0081-2004
17
Funcionamiento de VTK
Ignacio Berzal Moreno
Figura 3.2: GUI de CMake
Una vez indicados estos datos, hacemos clic sobre configure para iniciar el
proceso. El CMake lee el fichero CMakeLists.txt de mayor nivel encontrado en la
dirección de la fuente, determina la configuración del sistema y localiza las fuentes.
Entonces producirá un fichero CMakeCache.txt en la dirección que le hallamos
indicado. Cuando termina la configuración se le comunica al usuario. Si se quieren
cambiar valores del caché, el CMake proporciona una GUI para hacerlo. Una vez
hechos los cambios requeridos, pulsamos configure de nuevo. Finalmente se
producirán los workspaces, makefiles y todo lo necesario para controlar la
construcción de los procesos por parte del compilador. Una vez hecho esto ya
podemos cargar el fichero workspace generado (.dsw) y crear nuestra aplicación.
3.2.2 Arquitectura de VTK
The Visualization Toolkit es un sistema orientado a objetos. La clave para
utilizar VTK eficientemente es tener un buen conocimiento de los modelos de
objetos fundamentales. Con esto, es mucho más fácil combinar estos objetos para
construir aplicaciones.
VTK está constituido por dos modelos de objetos: Graphics Model y
Visualization Model.
18
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Funcionamiento de VTK
3.2.2.1 Graphics model
Los objetos principales que componen el graphics model son los siguientes:
-
vtkActor, vtkActor2D, vtkVolume ( subclases de vtkProp y vtkProp3D)
vtkLight
vtkCamera
vtkProperty, vtkProperty2D
vtkMapper, vtkMapper2D (subclases de vtkAbstractMapper)
vtkTransform
vtkLookupTable, vtkColorTransferFunction (subclases de
vtkScalarsToColors)
vtkRenderer
vtkRenderWindow
vtkRenderWindowInteractor
Al combinar estos objetos creamos una “escena”.
Los “props” representan las cosas que vemos en escena. Los que son utilizados
en 3D son del tipo vtkProp3D y los representados es 2D son del tipo vtkActor2D. Los
props no representan directamente su geometría, sino que ésta es referida a
“mappers”, los cuales son responsables de la representación de datos (entre otras
cosas). Los props también se refieren a una propiedad del objeto. La propiedad del
objeto controla la apariencia del prop (color, efecto de luces, representación de la
renderización, etc).
Los “actores” y “volúmenes” tienen un objeto de transformación interna
(vtkTransform). Este objeto encapsula una matriz de transformación 4x4 que controla
la posición, orientación y escala del prop.
Las “luces” (vtkLight) se usan para representar y manipular la iluminación de la
escena. Solo se emplean en 3D.
La “cámara” (vtkCamera) controla cómo la geometría 3D es proyectada en
imagen 2D durante el proceso de renderización. Tiene varios métodos para
posicionar y orientar. Además controla la perspectiva de la proyección y la visión
estéreo. Esto no es necesario en 2D.
El “mapper” (vtkMapper) junto con el “lookup table” (vtkLookupTable) son
usados para transformar y renderizar geometría. El mapper proporciona la interfaz
entre el pipeline de visualización y el graphics model. VtkLookupTable es una
subclase de vtkScalarsToColors, también lo es vtkColorTransferFunction, la cual se
usa para renderizar volúmenes. Las subclases de vtkScalarsToColors son
responsables de “mapear” los valores de los datos a color.
GVA-ELAI-UPM®PFC0081-2004
19
Funcionamiento de VTK
Ignacio Berzal Moreno
Los “renderers” (vtkRenderer) y las “render windows” (vtkRenderWindow) se
usan para dirigir la interfaz entre la “máquina gráfica” y el sistema de ventanas del
ordenador. La render window es la ventana del ordenador donde el renderer crea el
objeto. Varios renderers pueden actuar sobre una misma ventana de renderización.
Además se pueden crear múltiples render windows.
Una vez creados los objetos en la ventana de renderización, existen varios
métodos en VTK para interactuar con los datos de la escena. Uno de ellos es el
objeto vtkRenderWindowInteractor, que es una herramienta simple para manipular la
cámara, mover objetos, etc.
Muchos de estos objetos tienen subclases que especializan el comportamiento del
objeto.
3.2.2.2 Visualization model
La función del “pipeline gráfico” consiste en transformar datos gráficos en
imágenes, y la del “pipeline de visualización” en crear esos datos gráficos a partir de
la información necesaria; es decir, el pipeline de visualización es el encargado de
construir la representación geométrica que será renderizada por el pipeline gráfico.
VTK emplea dos tipos básicos de objetos en esta tarea:
-
vtkDataObject
vtkProcessObject
Los “data objects” representan datos de varios tipos. La clase vtkDataObject
puede interpretarse como un conjunto genérico de datos. A los datos que tienen una
estructura formal se les llama “dataset” (de la clase vtkDataSet). Los objetos dataset
en VTK se muestran en la figura 3.3.
Los data objects consisten en una estructura (de puntos y celdas) geométrica y
topológica, así como en unos atributos de datos que pueden ser, por ejemplo,
escalares o vectores. Los atributos de datos pueden ser asociados con los puntos o
celdas del dataset. Las celdas son agrupaciones topológicas de puntos, que forman
las unidades del dataset y se usan para interpolar información entre puntos.
20
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Funcionamiento de VTK
Figura 3.3: Datasets empleados por VTK
Los “process objects”, también llamados filtros, operan en los data objects para
generar nuevos data objects. Representan los algoritmos del sistema. Process y data
objects se conectan para formar los pipelines de visualización. Un ejemplo de ello es
la figura 3.4, en la que las flechas representan la dirección del flujo de datos:
GVA-ELAI-UPM®PFC0081-2004
21
Funcionamiento de VTK
Ignacio Berzal Moreno
Figura 3.4: Pipeline de visualización
Existen varios tipos importantes de process objects:
Figura 3.5: Process objects
Los “fuentes” son objetos que generan datos leyendo (reader objects) o
construyendo uno o más data objects (procedural source objects).
Los “filtros” pueden tener varios data objects en la entrada, y generar uno o más
data objects en la salida.
Los “mappers” transforman los data objects en datos gráficos, los cuales son
renderizados por la máquina gráfica.
Es necesario llevar a cabo varios pasos para la construcción del pipeline de
visualización:
Primero, la topología se construye usando variaciones de los métodos que
asignan a la entrada de un filtro la salida de otro filtro. Por ejemplo, en C++ se haría
de la siguiente forma:
22
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Funcionamiento de VTK
aFilter -> SetInput ( anotherFilter -> GetOutput( ) ) ;
Segundo, debemos tener mecanismos para controlar la ejecución del pipeline.
Solo necesitaremos ejecutar las partes del pipeline necesarias para actualizar la
salida.
Tercero, el ensamblaje del pipeline requiere que sólo aquellos objetos
compatibles entre sí puedan enlazarse con los métodos SetInput() y GetOutput().
Finalmente, debemos decidir si conservar o no los data objects una vez que el
pipeline es ejecutado. Los dataset de visualización suelen ser bastante grandes, lo
que es necesario tener en cuenta para la aplicación con éxito de las herramientas de
visualización.
3.2.2.2.1 Ejecución del pipeline
El pipeline de visualización sólo se ejecuta cuando los datos son requeridos para
la computación. La ejecución del pipeline puede explicarse a partir de la siguiente
figura:
Figura 3.5: Ejecución del pipeline
Cuando el actor recibe una petición de renderización se lo comunica a su mapper,
y el método Update() es enviado automáticamente a través del pipeline de
visualización. La función del método Update() es forzar la ejecución del pipeline,
con ello fuerza al reader a ejecutar y leer los datos del fichero indicado. Es decir, el
método Render() inicia la petición de datos, la cual es comunicada a través del
pipeline. Dependiendo de que partes del pipeline no estén actualizadas, los filtros del
pipeline son reejecutados, actualizando los datos al final del pipeline, que entonces
son rederizados por el actor.
GVA-ELAI-UPM®PFC0081-2004
23
Funcionamiento de VTK
Ignacio Berzal Moreno
3.2.2.2.2 Procesamiento de la imagen
VTK tiene un extenso número de métodos para el procesamiento de imágenes y
renderización de volúmenes. Los datos de imágenes 2D y 3D vienen dados por la
clase vtkImageData. En un dataset de imagen los datos son ordenados en un vector
regular alineado con los ejes. Mapas de bits y mapas de píxeles son ejemplos de
datasets de imágenes 2D, y volúmenes (pilas de imágenes 2D) lo son de datasets de
imágenes 3D.
Los process objects en un pipeline de imagen siempre tienen como entradas y
salidas data objects de imagen. Debido a la naturaleza regular y simple de los datos,
el pipeline de imagen tiene otros rasgos importantes. La renderización de volumen se
usa para visualizar objetos 3D de la clase vtkImageData, y visores especiales de
imágenes se usan para ver objetos 2D. La mayoría de los process objets en el
pipeline de imagen están multiensamblados y son capaces de hacer fluir los datos por
partes (para hacer un uso satisfactorio del límite de memoria). Los filtros
automáticamente detectan el número disponible de procesos en el sistema y crean el
mismo número de uniones durante la ejecución; igualmente, separan
automáticamente los datos en partes que fluyen a través del pipeline.
3.2.3 Creación de una aplicación
Crear aplicaciones gráficas con VTK es un proceso que consta de dos partes
básicas:
- Primero, es necesario construir un pipeline de datos para procesar los datos
- Segundo, hay que crear los objetos gráficos necesarios para interpretar esos
datos.
Construir un pipeline quiere decir conectar fuentes (crear datos), filtros (procesar
datos) y mappers (transformar datos en gráficos). Están disponible muchos tipos
distintos de fuentes, filtros y mappers, dependiendo del tipo de datos que se estén
procesando y de la funcionalidad deseada.
Para crear objetos gráficos los pasos típicos pueden ser:
- Crear una ventada de renderización para trabajar en ella.
- Crear un render.
- Crear un interactor (que permite interactuar con los datos).
- Crear uno o más actores (cada uno de los cuales es unido a un mapper).
- Renderizar.
Además, los objetos pueden ser transformados, pueden cambiarse sus
propiedades materiales y/o pueden crearse luces, cámaras, mapas de textura, tablas
de consulta y otros objetos gráficos.
24
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Funcionamiento de VTK
3.3 Ejemplos
3.3.1 Renderización de un cilindro
Este simple ejemplo muestra cómo crea un modelo poligonal de un cilindro,
mediante un pipeline y una renderización básicas:
/*******************************************************************/
// Primero se incluyen ficheros de cabecera requeridos por las clases de VTK que
//vamos a emplear:
#include "vtkCylinderSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkProperty.h"
#include "vtkCamera.h"
// Se declara la función principal:
int main(int argc, char *argv[])
{
// Creamos un modelo poligonal de un cilindro a partir de ocho esferas:
vtkCylinderSource *cylinder = vtkCylinderSource::New();
cylinder->SetResolution(8);
// Creamos el mapper, responsable de convertir los datos geométricos en datos
//gráficos:
vtkPolyDataMapper *cylinderMapper = vtkPolyDataMapper::New();
cylinderMapper->SetInput(cylinder->GetOutput());
// Creamos un actor para representar el cilindro. El actor dirige la renderización de
//las primitivas gráficas del mapper. Además, establecemos el color, y lo rotamos
//–22.5 grados:
vtkActor *cylinderActor = vtkActor::New();
cylinderActor->SetMapper(cylinderMapper);
cylinderActor->GetProperty()->SetColor(1.0000, 0.3882, 0.2784);
cylinderActor->RotateX(30.0);
GVA-ELAI-UPM®PFC0081-2004
25
Funcionamiento de VTK
Ignacio Berzal Moreno
cylinderActor->RotateY(-45.0);
// Creamos la estructura gráfica. El renderer renderiza en la ventana de renderización.
//El render window interactor captura las directrices del ratón y muestra la cámara y
//punto de vista necesarios según sus indicaciones:
vtkRenderer *ren1 = vtkRenderer::New();
vtkRenderWindow *renWin = vtkRenderWindow::New();
renWin->AddRenderer(ren1);
vtkRenderWindowInteractor *iren =
vtkRenderWindowInteractor::New();
iren->SetRenderWindow(renWin);
// Añadimos el actor al renderer, y elegimos el color de fondo y el tamaño de la
//ventana:
ren1->AddActor(cylinderActor);
ren1->SetBackground(0.1, 0.2, 0.4);
renWin->SetSize(200, 200);
// Acercamos la cámara mediante el método “Zoom ( )”:
ren1->GetActiveCamera()->Zoom(1.5);
renWin->Render();
// Comenzamos la renderización:
iren->Start();
// Liberamos todas las instancias que hemos creado:
cylinder->Delete();
cylinderMapper->Delete();
cylinderActor->Delete();
ren1->Delete();
renWin->Delete();
iren->Delete();
return 0;
}
/*******************************************************************/
Como ya indicamos anteriormente, para poder ejecutar un código fuente
implementado en C++ es necesario emplear la aplicación CMake. En este caso, el
fichero CMakeLists.txt que deberá incluirse será el siguiente:
26
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Funcionamiento de VTK
PROJECT (Rendering)
INCLUDE (${CMAKE_ROOT}/Modules/FindVTK.cmake)
IF (USE_VTK_FILE)
INCLUDE(${USE_VTK_FILE})
ENDIF (USE_VTK_FILE)
ADD_EXECUTABLE(Cylinder Cylinder.cxx)
TARGET_LINK_LIBRARIES(Cylinder vtkRendering)
Una vez CMake ha generado los ficheros necesarios, el resultado de la
ejecución del programa será la siguiente ventana, donde el cilindro podrá girarse
moviendo el ratón con el cursor sobre el cilindro y manteniendo el botón derecho
presionado:
Figura 3.6: Renderización de un cilindro
3.3.2 Renderización de un cono
Este ejemplo crea un modelo poligonal de un cono, y posteriormente lo
renderiza en la pantalla. El cono realiza una rotación de 360 grados y la aplicación
finaliza. Sigue la estructura básica de fuente -> mapper -> actor -> renderer ->
renderwindow, típica de la mayoría de los programas en VTK:
GVA-ELAI-UPM®PFC0081-2004
27
Funcionamiento de VTK
Ignacio Berzal Moreno
/*******************************************************************/
// Primero se incluyen ficheros de cabecera requeridos por las clases de VTK que
//vamos a emplear:
#include "vtkConeSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkRenderWindow.h"
#include "vtkCamera.h"
#include "vtkActor.h"
#include "vtkRenderer.h"
// Se declara la función principal:
int main( int argc, char *argv[] )
{
// Ahora creamos un objeto de la clase vtkConeSource y fijamos algunas de sus
// propiedades. El objeto “cone” de la clase vtkConeSource creado, forma parte de un
// pipeline de visualización ( es un process object fuente); genera datos que otros
//filtros pueden procesar (su salida es del tipo vtkPolyData).
vtkConeSource *cone = vtkConeSource::New();
cone->SetHeight( 3.0 );
cone->SetRadius( 1.0 );
cone->SetResolution( 10 );
// En este ejemplo finalizamos el pipeline con un process object tipo mapper
//(pueden ser incluidos filtros intermedios entre el fuente y el mapper, como el
// vtkShrinkPolyData). Creamos un objeto de la clase vtkPolyDataMapper para
//generar primitivas gráficas a partir de datos poligonales. Conectamos la salida del
//cono fuente a la entrada del mapper.
vtkPolyDataMapper *coneMapper = vtkPolyDataMapper::New();
coneMapper->SetInput( cone->GetOutput() );
// Creamos un actor para representar el cono. El actor dirige la renderización de las
// primitivas gráficas del mapper. Un actor también puede controlar las propiedades
// mediante la clase vtkProperty, e incluye una matriz de transformación interna.
// Seleccionamos como mapper de este actor al coneMapper creado anteriormente.
vtkActor *coneActor = vtkActor::New();
coneActor->SetMapper( coneMapper );
// Creamos el Renderer y le asignamos los actores. Un renderer es como un portal de
28
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Funcionamiento de VTK
// visualización. Es toda o parte de una ventana creada en la pantalla, y se encarga de
// representar los actores que posee. Aquí también seleccionamos el color de fondo.
vtkRenderer *ren1= vtkRenderer::New();
ren1->AddActor( coneActor );
ren1->SetBackground( 0.1, 0.2, 0.4 );
// Finalmente creamos la ventana de renderización que aparecerá en la pantalla.
//Colocamos el renderer en la render window usando AddRenderer. También
// seleccionamos el tamaño de la ventana, que será de 300 x 300 píxeles.
vtkRenderWindow *renWin = vtkRenderWindow::New();
renWin->AddRenderer( ren1 );
renWin->SetSize( 300, 300 );
// Ahora giramos el cono 360 grados y lo renderizamos al mismo tiempo:
int i;
for (i = 0; i < 360; ++i)
{
// Renderización de la imagen:
renWin->Render();
// Rotamos la cámara 1 grado:
ren1->GetActiveCamera()->Azimuth( 1 );
}
// Liberamos todos los objetos creados. Todos son borrados usando el método
Delete( ).
cone->Delete();
coneMapper->Delete();
coneActor->Delete();
ren1->Delete();
renWin->Delete();
return 0;
}
/*******************************************************************/
El fichero CMakeLists.txt necesario para la ejecución de CMake será el siguiente:
PROJECT (Cone)
GVA-ELAI-UPM®PFC0081-2004
29
Funcionamiento de VTK
Ignacio Berzal Moreno
INCLUDE (${CMAKE_ROOT}/Modules/FindVTK.cmake)
IF (USE_VTK_FILE)
INCLUDE(${USE_VTK_FILE})
ENDIF (USE_VTK_FILE)
ADD_EXECUTABLE(Cone Cone.cpp)
TARGET_LINK_LIBRARIES(Cone vtkRendering)
Una vez CMake ha generado los ficheros necesarios, el resultado de la ejecución
del programa será la siguiente ventana (el cono girará 360 grados, y después se
cerrará la ventana):
Figura 3.7: Renderización de un cono
3.3.3 Manipulación de luces
En VTK se pueden manipular luces, cámaras, texturas, transparencias así como
muchos otros efectos de visualización. Este ejemplo demuestra el efecto de la luz
especular sobre un conjunto de esferas:
/*******************************************************************/
// Primero se incluyen los ficheros de cabecera requeridos por las clases de VTK que
//vamos a emplear:
30
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Funcionamiento de VTK
#include "vtkSphereSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkProperty.h"
#include "vtkCamera.h"
#include "vtkLight.h"
int main(int argc, char *argv[])
{
// Creamos una esfera representada por polígonos:
vtkSphereSource *sphere = vtkSphereSource::New();
sphere->SetThetaResolution(100);
sphere->SetPhiResolution(50);
// El mapper es responsable de mapear los datos de entrada a la librería gráfica.
// También puede mapear colores si se han definido escalares u otros atributos
vtkPolyDataMapper *sphereMapper = vtkPolyDataMapper::New();
sphereMapper->SetInput(sphere->GetOutput());
// El actor dirige la renderización de los gráficos creados por el mapper. Además
//puede controlar las propiedades y el mapa de textura. En este ejemplo creamos
//ocho esferas distintas (dos filas de cuatro esferas) y establecemos los coeficientes
//de la luz especular.
vtkActor *sphere1 = vtkActor::New();
sphere1->SetMapper(sphereMapper);
sphere1->GetProperty()->SetColor(1,0,0);
sphere1->GetProperty()->SetAmbient(0.3);
sphere1->GetProperty()->SetDiffuse(0.0);
sphere1->GetProperty()->SetSpecular(1.0);
sphere1->GetProperty()->SetSpecularPower(5.0);
vtkActor *sphere2 = vtkActor::New();
sphere2->SetMapper(sphereMapper);
sphere2->GetProperty()->SetColor(1,0,0);
sphere2->GetProperty()->SetAmbient(0.3);
sphere2->GetProperty()->SetDiffuse(0.0);
sphere2->GetProperty()->SetSpecular(1.0);
sphere2->GetProperty()->SetSpecularPower(10.0);
sphere2->AddPosition(1.25,0,0);
GVA-ELAI-UPM®PFC0081-2004
31
Funcionamiento de VTK
Ignacio Berzal Moreno
vtkActor *sphere3 = vtkActor::New();
sphere3->SetMapper(sphereMapper);
sphere3->GetProperty()->SetColor(1,0,0);
sphere3->GetProperty()->SetAmbient(0.3);
sphere3->GetProperty()->SetDiffuse(0.0);
sphere3->GetProperty()->SetSpecular(1.0);
sphere3->GetProperty()->SetSpecularPower(20.0);
sphere3->AddPosition(2.5,0,0);
sphere4->SetMapper(sphereMapper);
sphere4->GetProperty()->SetColor(1,0,0);
sphere4->GetProperty()->SetAmbient(0.3);
sphere4->GetProperty()->SetDiffuse(0.0);
sphere4->GetProperty()->SetSpecular(1.0);
vtkActor *sphere4 = vtkActor::New();
sphere4->GetProperty()->SetSpecularPower(40.0);
sphere4->AddPosition(3.75,0,0);
vtkActor *sphere5 = vtkActor::New();
sphere5->SetMapper(sphereMapper);
sphere5->GetProperty()->SetColor(1,0,0);
sphere5->GetProperty()->SetAmbient(0.3);
sphere5->GetProperty()->SetDiffuse(0.0);
sphere5->GetProperty()->SetSpecular(0.5);
sphere5->GetProperty()->SetSpecularPower(5.0);
sphere5->AddPosition(0.0,1.25,0);
vtkActor *sphere6 = vtkActor::New();
sphere6->SetMapper(sphereMapper);
sphere6->GetProperty()->SetColor(1,0,0);
sphere6->GetProperty()->SetAmbient(0.3);
sphere6->GetProperty()->SetDiffuse(0.0);
sphere6->GetProperty()->SetSpecular(0.5);
sphere6->GetProperty()->SetSpecularPower(10.0);
sphere6->AddPosition(1.25,1.25,0);
vtkActor *sphere7 = vtkActor::New();
sphere7->SetMapper(sphereMapper);
sphere7->GetProperty()->SetColor(1,0,0);
sphere7->GetProperty()->SetAmbient(0.3);
sphere7->GetProperty()->SetDiffuse(0.0);
sphere7->GetProperty()->SetSpecular(0.5);
sphere7->GetProperty()->SetSpecularPower(20.0);
sphere7->AddPosition(2.5,1.25,0);
vtkActor *sphere8 = vtkActor::New();
32
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Funcionamiento de VTK
sphere8->SetMapper(sphereMapper);
sphere8->GetProperty()->SetColor(1,0,0);
sphere8->GetProperty()->SetAmbient(0.3);
sphere8->GetProperty()->SetDiffuse(0.0);
sphere8->GetProperty()->SetSpecular(0.5);
sphere8->GetProperty()->SetSpecularPower(40.0);
sphere8->AddPosition(3.75,1.25,0);
// Creamos la estructura gráfica. El renderer renderiza en la ventana de
//renderización. El interactor de la ventana de renderización captura las órdenes del
//ratón y manipula la cámara y el actor según dichas órdenes
vtkRenderer *ren1 = vtkRenderer::New();
vtkRenderWindow *renWin = vtkRenderWindow::New();
renWin->AddRenderer(ren1);
vtkRenderWindowInteractor *iren =
vtkRenderWindowInteractor::New();
iren->SetRenderWindow(renWin);
// Añadimos los actores al renderer, seleccionamos el fondo de pantalla y el tamaño:
ren1->AddActor(sphere1);
ren1->AddActor(sphere2);
ren1->AddActor(sphere3);
ren1->AddActor(sphere4);
ren1->AddActor(sphere5);
ren1->AddActor(sphere6);
ren1->AddActor(sphere7);
ren1->AddActor(sphere8);
ren1->SetBackground(0.1, 0.2, 0.4);
renWin->SetSize(400, 200);
// Configuramos la iluminación :
vtkLight *light = vtkLight::New();
light->SetFocalPoint(1.875,0.6125,0);
light->SetPosition(0.875,1.6125,1);
ren1->AddLight(light);
// Queremos eliminar los efectos de la perspectiva en la iluminación.
// Usamos una proyección de cámara paralela. Para usar el zoom en el modo de
//proyección paralela configuramos el ParallelScale:
ren1->GetActiveCamera()->SetFocalPoint(0,0,0);
ren1->GetActiveCamera()->SetPosition(0,0,1);
ren1->GetActiveCamera()->SetViewUp(0,1,0);
ren1->GetActiveCamera()->ParallelProjectionOn();
GVA-ELAI-UPM®PFC0081-2004
33
Funcionamiento de VTK
Ignacio Berzal Moreno
ren1->ResetCamera();
ren1->GetActiveCamera()->SetParallelScale(1.5);
// Inicializamos la opción de giro y comenzamos la renderización:
iren->Initialize();
iren->Start();
// Para finalizar, borramos todos los objetos creados:
sphere->Delete();
sphereMapper->Delete();
sphere1->Delete();
sphere2->Delete();
sphere3->Delete();
sphere4->Delete();
sphere5->Delete();
sphere6->Delete();
sphere7->Delete();
sphere8->Delete();
ren1->Delete();
renWin->Delete();
iren->Delete();
return 0;
}
/**************************************************************************************/
El fichero CMakeLists.txt necesario para la ejecución de CMake será el siguiente:
PROJECT (SpecularSpheres)
INCLUDE (${CMAKE_ROOT}/Modules/FindVTK.cmake)
IF (USE_VTK_FILE)
INCLUDE(${USE_VTK_FILE})
ENDIF (USE_VTK_FILE)
ADD_EXECUTABLE(SpecularSpheres SpecularSpheres.cxx)
TARGET_LINK_LIBRARIES(SpecularSpheres vtkRendering)
34
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Funcionamiento de VTK
Una vez CMake ha generado los ficheros necesarios, el resultado de la ejecución
del programa será la siguiente ventana ( las esferas podrán girarse en conjunto
moviendo el ratón mientras se mantiene el botón izquierdo pulsado):
Figura 3.8: Manipulación de luces
GVA-ELAI-UPM®PFC0081-2004
35
Funcionamiento de VTK
36
Ignacio Berzal Moreno
GVA-ELAI-UPM®PFC0081-2004
4
Fases de la reconstrucción 3D
La base de la visualización de datos está en el uso de algoritmos que transformen
estos datos. Existen varios tipos de algoritmos, que se pueden clasificar dependiendo
de la estructura y del tipo de transformación. Por estructura entendemos los efectos
que la transformación tiene en la topología y geometría del dataset. Y por tipo, el tipo
de dataset sobre el que operan los algoritmos.
Dependiendo de la estructura tenemos los siguientes algoritmos:
transformaciones geométricas, topológicas, de atributos, o combinaciones.
Dependiendo del tipo de datos sobre los que operan tenemos: algoritmos
escalares, vectoriales, tensores o de modelado.
Nosotros vamos a tratar los algoritmos escalares. Y en particular, nos
centraremos en la técnica de contorneado.
Cuando vemos una superficie coloreada con valores de datos, el ojo a menudo
separa las áreas de colores similares en distintas regiones. Cuando contorneamos los
datos, estamos construyendo los límites entre esas regiones. Estos límites
corresponden a líneas de contorno (en 2D) y superficies (en 3D) de valores escalares
GVA-ELAI-UPM®PFC0081-2004
37
Fases de la reconstrucción 3D
Ignacio Berzal Moreno
constantes. Los contornos tridimensionales se llaman isosuperficies, como por
ejemplo las superficies de presión y temperatura constante de un fluido.
4.1
Conversión del dominio de adquisición al mallado
(marching cubes)
Considerando una estructura de mallado, cada punto que define la malla tiene
asociado un valor escalar. El contorneado siempre comienza por seleccionar un valor
escalar, o valor de contorno, que se corresponda con la línea o superficie de contorno
generada. Para generar los contornos debe usarse alguna forma de interpolación. Esto
se debe a que tenemos valores escalares en un conjunto finito de puntos en el dataset,
y nuestro valor de contorno puede estar entre los valores de los puntos. La técnica de
interpolación más común es la lineal; generamos puntos en la superficie de contorno
por interpolación lineal a lo largo de las aristas.
Figura 4.1: Contorneo de una malla 2D estructurada con
valor línea de contorno de valor 5.
Una vez los puntos extremos de las celdas son generados, podemos conectar
estos puntos para crear contornos usando diferentes técnicas. Una de ellas actúa de
la siguiente manera: detecta una intersección de arista ( por ejemplo, el contorno pasa
a través de una arista ) y entonces “rastrea” ese contorno moviéndose a lo largo de
los límites de la celda. Sabemos que si el extremo de un contorno entra en una celda,
debe salir de la misma. El contorno es “rastreado” hasta que se cierra sobre sí mismo,
o abandona los límites del dataset. Si es sabido que sólo existe un contorno simple, el
38
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Fases de la reconstrucción 3D
proceso finaliza. De otra manera, todos los extremos en el dataset
comprobados para asegurar si existen otras líneas de contorno.
deben ser
Otra técnica es la llamada Marching Squares ,en 2D, o Marching Cubes, en 3D,
que trata las celdas independientemente. La suposición básica de esta técnica es la de
que un contorno sólo puede atravesar una celda de un número finito de maneras. Se
elabora una tabla de casos, que enumera todos los estados topológicos posibles de
una celda, dadas las combinaciones de valores escalares en los puntos de la celda. El
número de estados topológicos depende del número de vértices de la celda, y del
número de relaciones de entrada/salida que puede tener cada vértice con respecto a
los valores de contorno. Se considera que un vértice se encuentra dentro de un
contorno si su valor escalar es mayor que el valor escalar de la línea de contorno. Los
vértices con valor escalar menor que el valor de contorno se consideran fuera del
contorno. Por ejemplo, si una celda tiene cuatro vértices, y cada vértice puede estar
dentro o fuera del contorno, existen 2 4 = 16 maneras posibles de que el contorno
atraviese la celda. En la tabla de casos no nos interesa por que punto atraviesa el
contorno a la celda, sino la manera en que lo hace.
La siguiente figura muestra las 16 combinaciones posibles en una celda cuadrada.
Los vértices en negro indican que el valor escalar está por encima del de contorno:
Figura 4.2: Combinaciones posibles en que un contorno atraviesa una celda
cuadrada
En 3 dimensiones, para una celda cúbica, existen 256 combinaciones
diferentes de valores escalares dadas por los estados de los 8 distintos vértices de un
cubo (2 8 = 256 ). La figura 4.3 muestra estas combinaciones, que se pueden reducir
a 15 casos, usando argumentos de simetría. Podemos usar combinaciones de
rotaciones y simetrías para producir casos topológicamente independientes.
Los índices de la tabla de casos pueden ser computados codificando el estado de
cada vértice como un dígito binario. Para la representación de datos 2D en un malla
rectangular, podemos representar los 16 casos con índices de 4 bits; en 3D, con un
mallado cúbico, necesitaremos 8 bits para representar los 256 casos posibles. Una
GVA-ELAI-UPM®PFC0081-2004
39
Fases de la reconstrucción 3D
Ignacio Berzal Moreno
vez el caso particular es seleccionado, la localización de la intersección entre la línea
de contorno y la arista de la celda puede ser calculado por interpolación. El
algoritmo procesa una celda, y luego pasa a la siguiente. El contorno estará completo
después de que todas las celdas sean procesadas.
Figura 4.3: Combinaciones posibles en que un contorno atraviesa una celda cúbica
En resumen, los algoritmos de marching squares y marching cubes siguen los
siguientes pasos:
1- Selección de una celda.
2- Cálculo del estado interior o exterior de cada vértice de la celda.
3- Creación de un índice que almacena el estado binario de cada vértice en un
bit separado.
4- Uso del índice para buscar el estado topológico de la celda en una tabla de
casos.
5- Cálculo de la localización del contorno (por interpolación) para cada arista en
la tabla de casos.
40
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Fases de la reconstrucción 3D
4.2 Reducción de puntos de mallado
Los procedimientos de marching squares y marching cubes construyen primitivas
geométricas independientes en cada celda. En los límites de las celdas pueden crearse
vértices y aristas duplicados. Estos duplicados pueden ser eliminados empleando una
operación especial de fusión de puntos coincidentes. Hay que tener en cuenta que la
interpolación a lo largo de cada arista debe realizarse siempre en la misma dirección.
Si esto no se cumple, pueden generarse puntos que no coincidan exactamente, debido
al redondeado numérico, y no serán fusionados correctamente.
Existen ventajas y desventajas entre la técnica del “rastreo de aristas” y la de
marching cubes. El algoritmo de marching squares es fácil de implementar. Esto es
particularmente importante cuando aplicamos la técnica en tres dimensiones, donde
el “rastreo” de isosuperficies se torna mucho más complicado. Por otra parte, el
algoritmo crea puntos y segmentos desconectados, y la operación de fusionado
necesaria requiere recursos de computación extras. El algoritmo de “rastreo” puede
ser implementado para generar una polilínea simple por línea de contorno,
evitándose la necesidad de fusionar los puntos coincidentes.
4.3 Suavizado del mallado
Con el uso de estas técnicas se nos plantea el problema de la “ambigüedad de
contorneo”. Al estudiar con detenimiento algunas de las combinaciones posibles de
celdas de marching squares (casos 5 y 10), y marching cubes (casos 3, 6, 7, 10, 12,
13), podemos observar que pueden ser contorneadas de más de una forma. La
“ambigüedad de contorneo” aparece en las celdas cuadradas en 2D, o en las caras de
las celdas cúbicas en 3D, cuando los vértices de una misma arista tienen estados
distintos, pero sus opuestos diagonalmente poseen estados idénticos.
La “ambigüedad de contorneo” puede tratarse de manera simple en 2D: para
cada caso ambiguo implementamos una de las dos posibles soluciones. Para cada
caso particular la elección se lleva a cabo de manera independiente. Dependiendo de
la elección, el contorneo prolongará o cortará el contorno en proceso de formación,
como se muestra en la siguiente figura:
Figura 4.4: Ambigüedad de contorneo
GVA-ELAI-UPM®PFC0081-2004
41
Fases de la reconstrucción 3D
Ignacio Berzal Moreno
Cualquier elección es aceptable mientras que la línea de contorno resultante sea
continua y cerrada (o termine en los límites del dataset).
El problema es más complejo en tres dimensiones. Ahora no podemos elegir uno
de los casos ambiguos sin tener en cuenta todos los demás. En la siguiente figura
podemos apreciar lo que puede ocurrir si implementamos dos casos ambiguos
independientemente uno del otro:
Figura 4.5: Implementación de dos casos ambiguos de manera independiente
Tenemos el caso de celda cúbica 3 y un caso complementario del 6, el 6c, en los
que se ha elegido uno de los casos ambiguos, Al conectar los dos cubos observamos
que aparece una zona hueca en la isosuperficie.
Se han desarrollado distintas técnicas para solventar este problema:
- Marching tetrahedra: Esta técnica consiste en descomponer las celdas cúbicas en
tetraedros. Al hacer esto, los casos ambiguos desaparecen. Las desventajas son que
el algoritmo de marching tetrahedra genera isosuperficies formadas por más
triángulos, y que la descomposición de un cubo en tetraedros requiere hacer una
elección con respecto a la orientación de los mismos. Esta elección puede resultar en
la aparición de "protuberancias" artificiales en la isosuperficie debido a la
interpolación a lo largo de las diagonales de cara, como muestra la siguiente figura:
42
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Fases de la reconstrucción 3D
Figura 4.6: Marching tetrahedra
- Asymptotic decider: Esta técnica, desarrollada por Nielson y Hamann, consiste en
evaluar el comportamiento asintótico de la superficie, y decidir después los casos en
los que unir o romper el contorno. Se basa en el análisis de la variación de la
variable escalar a lo largo de una cara ambigua. El análisis determina cómo deben
ser conectados los bordes de los polígonos de la isosuperficie.
- Casos complementarios: Ésta es una técnica simple pero efectiva, consistente en
añadir casos adicionales complementarios a los 15 casos originales de marching
cubes. Estos casos son diseñados para ser compatibles con los casos cercanos y
prevenir la aparición de "huecos" en la isosuperficie. Se necesitan seis casos
complementarios, que se corresponden con los casos originales 3, 6, 7, 10, 12 y 13,
como se puede apreciar en la figura:
Figura 4.7: Casos complementarios de marching cubes
GVA-ELAI-UPM®PFC0081-2004
43
Fases de la reconstrucción 3D
Ignacio Berzal Moreno
La técnica general de marching squares y marching cubes puede extenderse a
otros tipos topológicos. En VTK se emplean marching lines, marching triangles y
marching tetrahedra para contorneo de celdas de esos mismos tipos (líneas,
triángulos y tetraedros), o celdas compuestas por combinaciones de los mismos.
Además, aunque hablamos de tipos de celdas regulares, como cuadrados y cubos, el
algoritmo de marching cubes puede aplicarse a cualquier tipo de celda
topológicamente equivalente a un cubo.
44
GVA-ELAI-UPM®PFC0081-2004
5
Aplicaciones sobre una pila
de imágenes del confocal
Podemos crear imágenes de cuerpos tridimensionales a partir de imágenes
bidimensionales de cortes transversales obtenidas mediante un microscopio confocal.
Esto nos sirve para sintetizar imágenes mostrando atributos que no son visibles
aparentemente en las imágenes originales por separado, como la profundidad. Es el
caso de imágenes biomédicas, por ejemplo en las que hay superposición de
intensidades y texturas cuando vemos una imagen de resonancia magnética. Para
resolver este problema aplicamos un método llamado segmentación, mediante el cual
identificamos las diferentes superficies que componen el cuerpo de nuestra imagen.
Para nuestro propósito debemos de tener identificado cada píxel en cada corte de
un volumen de datos con un identificador de superficie. Este identificador es un
número entero que describe la clase de superficie a la que pertenece cada píxel.
Debemos desarrollar una estrategia para poder crear un programa que extraiga las
diferentes superficies que compongan el cuerpo y poder visualizarlas por separado o
conjuntamente. En el caso de tener un elevado número de superficies, tendremos que
operar con un elevado número de parámetros y de filtros de imágenes. Nuestro
objetivo será desarrollar un pipeline general que nos servirá para todos los casos.
GVA-ELAI-UPM®PFC0081-2004
45
Aplicaciones sobre una pila de imagen del confocal
Ignacio Berzal Moreno
También debemos designar el programa en el que trabajaremos con un
conjunto de parámetros de uso específico para el control de los elementos del
pipeline. Trabajando en C++, debemos designar el formato del fichero y escribir el
código para interpretar las declaraciones. La forma de generar modelos será la
siguiente. Primero ejecutamos un fichero de VTK para cada superficie. Este fichero
generará un fichero .vtk que contendrá la representación poligonal de cada superficie.
Después renderizaremos los modelos por separado.
5.1 Desarrollo del pipeline
Es necesaria la construcción de un pipeline genérico que podamos utilizar para
diferentes casos de construcción de modelos en los que nos encontremos con un
número diferente, en algunos casos elevado, de superficies o tejidos. En la siguiente
figura se muestra un pipeline genérico que puede ser empleado para este fin. Este
pipeline genera modelos razonables de dataset segmentados. El volumen pasa a
través del pipeline antes de la extracción de la isosuperficie.
Figura 5.1: pipeline genérico
46
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones sobre una pila de imagen del confocal
5.2 Leer los datos de la pila de imagen
Debemos suponer que todas las imágenes que van a ser procesadas son
adquiridas fijando una marca central constante. En VTK, el origen de los datos se
aplica en la parte izquierda inferior de la imagen. El centro x,y del volumen será el
punto (0,0). La clase DataSpacing describe el valor de cada píxel y la distancia entre
los cortes. La clase DataVOI selecciona un volumen de interés, esto es, selecciona
las áreas de interés, eliminando estructuras extrañas si es necesario.
El método SetTransform() define como disponer el dato en memoria. Este filtro
transforma los vértices de los triángulos de modo que los modelos resultantes se
podrán ver todos de frente, y con una vista respecto a la posición de los ejes de
(0,-1,0). La correspondencia derecha-izquierda será mantenida. Esto significa que la
izquierda del cuerpo siempre será la izquierda del modelo generado.
El pipeline solo será ejecutado una vez. Para conservar memoria, invocamos el
método ReleaseDataFlagOn(). Éste permite que el pipeline libere datos una vez que
han sido procesados por un filtro. En dataset de imágenes médicas de gran tamaño,
esto puede ser la diferencia entre poder llevar a cabo el procesamiento de un dataset
o no.
originx = ((COLUMNS / 2.0) * PÍXEL_SIZE * -1.0);
originy = ((ROWS / 2.0) * PÍXEL_SIZE * -1.0);
vtkPNMReader *reader = vtkPNMReader::New();
reader-> SetFilePrefix(STUDY);
reader-> SetDataSpacing(PIXEL_SIZE, PIXEL_SIZE, SPACING);
reader-> SetDataOrigin(originx, originy);
START_SLICE * SLICE_ORDER
reader-> SetDataVOI(VOI);
reader-> SetTransform(SLICE_ORDER);
reader-> GetOutput()-> ReleaseDataFlagOn();
GVA-ELAI-UPM®PFC0081-2004
47
Aplicaciones sobre una pila de imagen del confocal
Ignacio Berzal Moreno
Figura 5.2: Diagrama de herencia de la clase vtkPNMReader
5.3 Trasladar islas
Algunas técnicas de segmentación pueden generar islas de vóxeles sin clasificar.
Un vóxel es un pequeño elemento de volumen, se puede definir como una celda
primaria tridimensional con seis caras. Este filtro conecta píxeles con la etiqueta
ISLAND_REPLACE, y si el número de píxeles es menor que ISLAND_AREA, los
reemplaza por la etiqueta TISSUE. Este filtro solo es ejecutado si
ISLAND_REPLACE es positivo.
48
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones sobre una pila de imagen del confocal
lastConnection = reader;
if { ISLAND_REPLACE >=0 } {
vtkImageIslandRemoval2D*islandRemover=
vtkImageIslandRemoval2D::New();
islandRemover-> SetAreaThreshold(ISLAND_AREA);
islandRemover-> SetIslandValue(ISLAND_REPLACE);
islandRemover-> SetReplaceValue(TISSUE);
islandRemover-> SetInput( lastConnection-> GetOutput());
lastConnection = islandRemover;
}
Figura 5.3: Diagrama de colaboración de la clase vtkImageIslandRemoval2D
GVA-ELAI-UPM®PFC0081-2004
49
Aplicaciones sobre una pila de imagen del confocal
Ignacio Berzal Moreno
Figura 5.4: Diagrama de herencia de la clase vtkImageIslandRemoval2D
5.4 Seleccionar una superficie
El resto del pipeline requiere datos en escala de grises. Para convertir el volumen
que contiene todas las etiquetas de las superficies a un volumen de escala de gris que
contenga solo una superficie, usamos el filtro threshold para colocar todos los píxeles
con el valor TISSUE a 255 y todos los otros píxeles a 0. La elección de 255 es
arbitraria.
vtkImageThreshold *selectTissue = vtkImageThreshold::New();
selectTissue-> ThresholdBetween(TISSUE, TISSUE);
selectTissue-> SetInValue(255);
selectTissue-> SetOutValue(0);
selectTissue-> SetInput(lastConnection-> GetOutput());
50
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones sobre una pila de imagen del confocal
Figura 5.5: Diagrama de herencia de la clase vtkImageThreshold
Figura 5.6: Diagrama de colaboración de la clase vtkImageThreshold
GVA-ELAI-UPM®PFC0081-2004
51
Aplicaciones sobre una pila de imagen del confocal
Ignacio Berzal Moreno
5.5 Remuestreo de volumen
Reducir la resolución de volúmenes produce menos polígonos. Por
experimentación, a menudo reducimos la resolución del dato con este filtro. Sin
embargo, los detalles pueden perderse durante el proceso. Se pueden crear nuevos
píxeles en el volumen remuestreado mediante un promedio de los píxeles vecinos. Si
el promedio es desactivado, cada píxel SAMPLE_RATE será llevado a la salida.
vtkImageShrink3D *shrinker = vtkImageShrink3D::New();
shrinker-> SetInput(selectTissue-> GetOutput());
shrinker-> SetShrinkFactors(SAMPLE_RATE);
shrinker-> AveragingOn();
Figura 5.7: Diagrama de herencia de la clase vtkImageShrink3D
52
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones sobre una pila de imagen del confocal
Figura 5.7: Diagrama de colaboración de la clase vtkImageShrink3D
5.6 Alisar los datos de volumen
En este punto, el volumen es etiquetado con un valor de 255 en los píxeles de la
superficie seleccionada y 0 en cualquier otra. Este volumen binario produciría
superficies rugosas si no lo difuminamos. El núcleo Gaussiano especificado en este
filtro lleva a cabo el alisado que nosotros requerimos para extraer superficies. El
nivel de alisado es controlado por GAUSSIAN_STANDARD_DEVIATION que
puede ser especificado independientemente por cada eje del dato de volumen. Sólo
ejecutaremos este filtro si se requiere algún tipo de alisado.
lastConnection = shrinker;
if {GAUSSIAN_STANDARD_DEVIATION ¡= “0 0 0”} {
vtkImageGaussianSmooth *gaussian =
vtkImageGaussianSmooth::New();
gaussian-> SetDimensionality(3);
gaussian->
SetStandardDeviation(GAUSSIAN_STANDARD_DEVIATION);
gaussian-> SetRadiusFactor(1);
lastConnection = gaussian;}
GVA-ELAI-UPM®PFC0081-2004
53
Aplicaciones sobre una pila de imagen del confocal
Ignacio Berzal Moreno
Figura 5.8: Diagrama de herencia de la clase vtkImageGaussianSmooth
Figura 5.9: Diagrama de colaboración de la clase vtkImageGaussianSmooth
54
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones sobre una pila de imagen del confocal
5.7 Generar triángulos
Podemos procesar el volumen con el método marching cubes como si
hubiéramos obtenido un dato en escala de grises mediante un escáner. El filtro se
ejecuta más rápido si desactivamos el gradiente y los cálculos normales. El marching
cubes normalmente calcula puntos normales a partir del gradiente del dato de
volumen. En nuestro pipeline hemos confeccionado una representación en escala de
grises y seguidamente diezmaremos la malla del triángulo y alisaremos los vértices
resultantes. Este proceso invalida los normales que son calculados por marching
cubes.
vtkMarchingCubes *mcubes = vtkMarchingCubes::New();
mcubes-> SetInput(toStructuredPoints-> GetOutput());
mcubes-> ComputeScalarsOff();
mcubes-> ComputeGradientsOff();
mcubes-> ComputeNormalsOff();
mcubes-> SetValue(0, VALUE);
mcubes-> GetOutput(ReleaseDataFlagOn);
Figura 5.10: Diagrama de herencia de la clase vtkMarchingCubes
5.8 Reducir el número de triángulos
A menudo hay muchos más triángulos generados por el algoritmo de
isosuperfície de los que necesitamos para la renderización. Aquí reducimos la
GVA-ELAI-UPM®PFC0081-2004
55
Aplicaciones sobre una pila de imagen del confocal
Ignacio Berzal Moreno
cantidad de triángulos, eliminando los vértices de los triángulos que se encuentran
dentro de una distancia especificada por el usuario al plano formado por los vértices
cercanos. Preservamos algunas esquinas de triángulos que son consideradas
distintivas.
vtkDecimate *decimator = vtkDecimate::New();
decimator-> SetInput(mcubes-> GetOutput());
decimator-> SetInitialFeatureAngle(DECIMATE_ANGLE);
decimator-> SetMaximumIterations(DECIMATE_ITERATIONS);
decimator-> SetMaximumIterations(0);
decimator-> PreserveEdgesOn();
decimator-> SetMaximuError(1);
decimator-> SetTargetReduction(DECIMATE_REDUCTION);
decimator-> SetInitialError(DECIMATE_ERROR);
decimator-> SetErrorIncrement(DECIMATE_ERROR_INCREMENT);
decimator-> GetOutput(ReleaseDataFlagOn);
Figura 5.11: Diagrama de herencia de la clase vtkDecimate
56
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones sobre una pila de imagen del confocal
Figura 5.12: Diagrama de colaboración de la clase vtkDecimate
5.9 Alisar vértices de triángulos
Este filtro usa un Laplaciano para ajustar vértices de triángulos como un
promedio de extremos de vértices. El mecanismo será menor que un vóxel. Nosotros
tenemos que alisar el dato de imagen con un núcleo Gaussiano así que esto no dará
mucha perfección, sin embargo, los modelos que son diezmados en gran cantidad
pueden ser algunas veces perfeccionados con un alisado poligonal adicional.
vtkSmoothPolyDataFilter *smoother = vtkSmoothPolyDataFilter::New();
smoother-> SetInput(decimator-> GetOutput());
smoother-> SetNumberOfIterations(SMOOTH_ITERATIONS);
smoother-> SetRelaxationFactor(SMOOTH_FACTOR);
smoother-> SetFeatureAngle(SMOOTH_ANGLE);
smoother-> BoundarySmoothingOff();
smoother-> SetConvergence(0);
smoother-> GetOutput(ReleaseDataFlagOn);
GVA-ELAI-UPM®PFC0081-2004
57
Aplicaciones sobre una pila de imagen del confocal
Ignacio Berzal Moreno
Figura 5.13: Diagrama de herencia de la clase vtkSmoothPolyDataFilter
5.10 Generar ejemplares
Para generar modelos sombreados alisados durante la renderización, necesitamos
ejemplares de cada vertex. Se pueden remarcar las esquinas ajustando el ángulo
distintivo.
vtkPolyDataNormals *normals = vtkPolyDataNormals::New();
normals-> SetInput(smoother-> GetOutput());
normals-> SetFeatureAngle(REATURE_ANGLE);
normals-> GetOutput(ReleaseDataFlagOn);
58
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones sobre una pila de imagen del confocal
Figura 5.14: Diagrama de herencia de la clase vtkPolyDataNormals
Figura 5.15: Diagrama de colaboración de la clase vtkPolyDataNormals
GVA-ELAI-UPM®PFC0081-2004
59
Aplicaciones sobre una pila de imagen del confocal
Ignacio Berzal Moreno
5.11 Generar strips de triángulos
Los strips de triángulos son una representación compacta de un gran número de
triángulos. Este filtro procesa nuestros triángulos independientes antes de que los
escribamos a un fichero.
VtkStripper *stripper = vtkStripper::New();
stripper-> SetInput(normals-> GetOutput());
stripper-> GetOutput(ReleaseDAtaFlagOn());
Figura 5.16: Diagrama de herencia de la clase vtkStripper
5.12 Escribir triángulos en un fichero
Finalmente, el último componente del pipeline es escribir strips de triángulos en
un fichero.
vtkPolyDataWriter *writer = vtkPolyDataWriter::New();
writer-> SetInput(stripper-> GetOutput());
writer-> SetFileName(NAME.vtk);
60
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones sobre una pila de imagen del confocal
Figura 5.17: Diagrama de herencia de la clase vtkPolyDataWriter
5.13 Ejecutar el pipeline
VTK usa una arquitectura pipeline para conducir la petición, pero de momento no
ha habido ninguna. Hasta ahora hemos especificado la topología del pipeline y los
parámetros para cada elemento.
writer Update;
Esto hace que se ejecute el pipeline.
5.14 Especificar parámetros para el pipeline
Todas las variables mencionadas anteriormente deben ser definidas para cada
superficie que vaya a ser procesada. Los parámetros se dividen en dos categorías
generales. Algunas son especificadas para cada estudio particular mientras que otras
son especificada para cada superficie.
GVA-ELAI-UPM®PFC0081-2004
61
Aplicaciones sobre una pila de imagen del confocal
Ignacio Berzal Moreno
Hay un fichero específico para cada tipo de superficie. Este fichero específico lee
en el fichero donde están especificados los parámetros, obtiene estos parámetros y
lee el pipeline.
Una vez que los modelos son generados, pueden ser renderizados. Primero
creamos un procedimiento para automatizar la creación de actores de los ficheros de
los modelos. Todos los elementos del pipeline son nombrados constantemente con el
nombre de la parte siguiente por el nombre del elemento del pipeline. Esto facilita
que el usuario identifique el objeto en cualquier sofisticado interfaz que este usando.
Después de un código para crear la renderización requerida de los objetos, creamos
un actor que podamos añadir al renderer.
5.15 Ejemplo
Como ejemplo de creación de imágenes de cuerpos tridimensionales a partir
de imágenes bidimensionales de cortes transversales obtenidas mediante un
microscopio confocal, vamos a mostrar el código necesario ( implementado en C++ )
para la reconstrucción 3D de una neurona madre:
/*******************************************************************
//Como primer paso, incluimos las librerías necesarias para nuestra aplicación:
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkImageReader.h"
#include "vtkContourFilter.h"
#include "vtkSmoothPolyDataFilter.h"
#include "vtkPolyDataNormals.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkOutlineFilter.h"
#include "vtkCamera.h"
#include "vtkProperty.h"
#include "vtkMergePoints.h"
#include <fstream.h>
#include <stdio.h>
// Llevamos a cabo las definiciones de la longitud de la cabecera del archivo
//(BIORAD_HEADER_LENGTH ), y de la macro que transforma datos tipo byte a
//word
#define BIORAD_HEADER_LENGTH 76
62
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones sobre una pila de imagen del confocal
#define BYTE_TO_WORD(lsb,msb) (((unsigned char) lsb) + (((unsigned
char) msb) << 8))
// Creamos la función “main”:
int main( )
{
//Creamos el renderer, renderwindow y rederwindowinteractor para poder visualizar
//la imagen 3D resultado en una ventana de renderización:
vtkRenderer *aRenderer = vtkRenderer::New();
vtkRenderWindow *renWin = vtkRenderWindow::New();
renWin->AddRenderer(aRenderer);
vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
iren->SetRenderWindow(renWin);
// El programa accede al nombre del fichero .pic, y al número de rodajas de que está
//compuesta la imagen a través de ficheros de texto .txt, y luego almacena los datos
//en variables:
int fd2, fd4, nx, ny, nz;
unsigned char *head2 = new unsigned char[76];
fstream fd1;
fd1.open("VTKFirstSlice.txt", ios::in);
fd1 >> fd2;
cout << " FirstSlice " << fd2;
fd1.close();
fstream fd3;
fd3.open("VTKLastSlice.txt", ios::in);
fd3 >> fd4;
cout << " LastSlice " << fd4;
fd3.close();
fstream file1;
file1.open("VTKFilename.txt", ios::in);
file1.getline(file2, '\0');
cout << " Filename " << file2;
file1.close();
//Abrimos el archivo de la imagen, comprobando antes que el nombre indicado por la
//variable “file2” es realmente un fichero .pic
FILE *head1;
head1 = fopen(file2,"rb");
GVA-ELAI-UPM®PFC0081-2004
63
Aplicaciones sobre una pila de imagen del confocal
Ignacio Berzal Moreno
if (head1 == NULL)
std::cout <<” Error en la apertura del fichero"<<std::endl;
return 0;
//Leemos la cabecera del fichero PIC BIORAD
fread(head2,sizeof(unsigned char),BIORAD_HEADER_LENGTH,head1);
nx = BYTE_TO_WORD(head2[0], head2[1]);
ny = BYTE_TO_WORD(head2[2], head2[3]);
nz = BYTE_TO_WORD(head2[4], head2[5]);
fclose(head1);
//Verificamos si el numero de columnas, filas y rodajas del fichero son los correctos:
if ( nx <= 0 )
std::cout << "Numero de columnas incorreto, " << nx << std::endl;
return 0;
if ( ny <= 0 )
std::cout << "Numero de filas incorreto, " << ny << std::endl;
return 0;
if ( nz <= 0 )
std::cout << "Numero de rodajas de imágenes incorrecto, " << nz
<<std:: endl;
return 0;
nx = nx -1;
ny = ny -1;
nz = nz -1;
//Creamos el ImageReader, objeto encargado de la lectura de la imagen, y
establecemos sus parámetros:
vtkImageReader *reader = vtkImageReader::New();
reader->SetFileName(nombreFich);
reader->SetFileDimensionality(3);
reader->SetDataExtent(0, nx, 0, ny, 0, nz);
reader->SetDataVOI (0, nx, 0, ny, fd2, fd4);
reader->SetDataOrigin(0, 0, 0);
reader->SetDataScalarTypeToUnsignedChar();
reader->SetDataSpacing(1.0, 1.0, 0.2);
reader->SetHeaderSize(76);
// Aplicamos varios filtros a la imagen: primero el vtkContourFilter para la
//superficie, y después usamos el vtkPolyDataNormals para generar ejemplares que
//serán alisados por el vtkSmoothPolyDataFilter durante la renderización.
64
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones sobre una pila de imagen del confocal
vtkContourFilter *skinExtractor = vtkContourFilter::New();
skinExtractor->SetInput((vtkDataSet *) reader->GetOutput());
skinExtractor->SetValue(0, 254);
vtkSmoothPolyDataFilter *smooth = vtkSmoothPolyDataFilter::New();
smooth->SetInput(skinExtractor->GetOutput());
smooth->SetNumberOfIterations(50);
smooth->BoundarySmoothingOn();
smooth->SetFeatureAngle(120);
smooth->SetEdgeAngle(90);
smooth->SetRelaxationFactor(.025);
vtkPolyDataNormals *skinNormals = vtkPolyDataNormals::New();
skinNormals->SetInput(smooth->GetOutput());
skinNormals->SetFeatureAngle(60.0);
// Creamos los actores y mappers necesarios para llevar a cabo la enderización:
vtkPolyDataMapper *skinMapper = vtkPolyDataMapper::New();
skinMapper->SetInput(skinNormals->GetOutput());
skinMapper->ScalarVisibilityOff();
vtkActor *skin = vtkActor::New();
skin->SetMapper(skinMapper);
vtkOutlineFilter *outlineData = vtkOutlineFilter::New();
outlineData->SetInput((vtkDataSet *) reader->GetOutput());
vtkPolyDataMapper *mapOutline = vtkPolyDataMapper::New();
mapOutline->SetInput(outlineData->GetOutput());
vtkActor *outline = vtkActor::New();
outline->SetMapper(mapOutline);
outline->GetProperty()->SetColor(0,0,0);
// Añadimos el objeto camera que nos permite posicionar el punto de vista a la hora
//de la visualización por pantalla:
vtkCamera *aCamera = vtkCamera::New();
aCamera->SetViewUp (0, 0, -1);
aCamera->SetPosition (0, 1, 0);
aCamera->SetFocalPoint (0, 0, 0);
aCamera->ComputeViewPlaneNormal();
// Añadimos los actores al renderer creado anteriormente:
GVA-ELAI-UPM®PFC0081-2004
65
Aplicaciones sobre una pila de imagen del confocal
Ignacio Berzal Moreno
aRenderer->AddActor(outline);
aRenderer->AddActor(skin);
aRenderer->SetActiveCamera(aCamera);
aRenderer->ResetCamera ();
aCamera->Dolly(1.5);
// Seleccionamos el color de fondo de la ventana de renderización y su tamaño:
aRenderer->SetBackground(1,1,1);
renWin->SetSize(512, 512);
aRenderer->ResetCameraClippingRange ();
// Iniciamos la renderización:
iren->Initialize();
iren->Start();
// Liberamos todos los objetos creados con el método Delete ( ):
smooth->Delete();
skinExtractor->Delete();
skinNormals->Delete();
skinMapper->Delete();
skin->Delete();
outlineData->Delete();
mapOutline->Delete();
outline->Delete();
aCamera->Delete();
iren->Delete();
renWin->Delete();
aRenderer->Delete();
return 0;
}
*******************************************************************/
El fichero CMakeLists.txt necesario para la ejecución de CMake será el siguiente:
PROJECT ($eje_neuro)
INCLUDE (${CMAKE_ROOT}/Modules/FindVTK.cmake)
IF (USE_VTK_FILE)
66
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones sobre una pila de imagen del confocal
INCLUDE(${USE_VTK_FILE})
ENDIF (USE_VTK_FILE)
ADD_EXECUTABLE(neuro_Cont2 neuro_Cont2.cpp)
TARGET_LINK_LIBRARIES(neuro_Cont2 vtkRendering)
A continuación podemos ver la reconstrucción de la imagen 3D de la neurona
madre, obtenida a partir de 32 cortes en 2D contenidos en un fichero .pic:
Figura 5.16: Imagen de una neurona madre obtenida tras su reconstrucción 3D a
partir de 32 cortes en 2D, generada con VTK
GVA-ELAI-UPM®PFC0081-2004
67
Aplicaciones sobre una pila de imagen del confocal
68
Ignacio Berzal Moreno
GVA-ELAI-UPM®PFC0081-2004
6
Combinación de la difusión
isotrópica y anisotrópica en el
procesamiento de imágenes
6.1
Introducción al filtrado de difusión
Por lo general, las etapas de procesamiento de imágenes se emplean en
aplicaciones que pretenden conseguir la eliminación de ruido o la regularización de
las imágenes, intentando preservar la estructura de éstas en ambos casos. Para esta
finalidad se suele emplear el filtrado lineal, debido a su bajo coste computacional.
Sin embargo, tiene como inconveniente la falta de realimentación entre la zona
concreta de la imagen que se está procesando y el filtrado al que está sometida.
Regiones homogéneas, son procesadas de igual manera. Una solución a este
problema surgida en los últimos años es la aplicación de PDEs (‘Partial Differential
Equations’) sobre el procesamiento de imágenes. Mediante su empleo es posible
aplicar un filtrado dependiente de las características del área a procesar.
Entre las PDE la más empleada es la ecuación de la difusión. Según la
analogía entre el campo escalar de las temperaturas en un proceso de difusión y el
GVA-ELAI-UPM®PFC0081-2004
69
Combinación de la difusión isotrópica y anisotrópica en el
procesamiento de imágenes
Ignacio Berzal Moreno
campo escalar del nivel de gris de una imagen en un filtrado de suavizado, las
dinámicas de ambos procesos se rigen por la expresión:
∂ t u = div(∇u )
donde u es el potencial del campo escalar y la ecuación expresa la dinámica de un
proceso de difusión homogénea. La expresión es idéntica a una convolución de la
imagen con una máscara de Gauss, cuya varianza está dada por:
σ 2 = 2t
Este resultado tiene una interpretación física. El nivel de gris, es en la
analogía, un nivel de temperatura y tiende a homogenizarse en el tiempo, t. Por tanto,
el suavizado de la imagen depende del tiempo transcurrido y desde el punto de vista
de la implementación con el valor de la varianza de la máscara de Gauss. El gran
avance lo darán Perona y Malik al realizar por primera vez un filtrado de difusión
isotrópica. La finalidad de este filtrado es acentuar el proceso de difusión en las
zonas homogéneas y preservar los bordes:
((
2
) )
∂ t u = div g ∇u ∇u
siendo g(.) una función de g : ℜ m → ℜ (m es la dimensión del campo escalar, u),
decreciente con la magnitud del módulo del gradiente. Su valor es prácticamente
nulo en los bordes y próximo a 1 en regiones con valores similares de potencial. La
función g(.) recibe el nombre de difusividad, y un proceso de difusión con una
difusividad de tipo escalar se llama difusión isotrópica.
Pero esta formulación implica que en algunos puntos se dé un proceso de
difusión inversa, provocando el realce puntual del ruido. Para resolver ésto, Weickert
realizó un estudio de la difusión tomando la difusividad como un tensor de difusión
en lugar de cómo un escalar:
∂ t u = div(D∇u )
donde D es una matriz de dimensión mxm, simétrica y definida semi-positiva. El
tensor D estará determinado por los autovectores y autovalores del tipo concreto de
tensor:
D = RCRT
70
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Combinación de la difusión isotrópica y anisotrópica en el
procesamiento de imágenes
R es la matriz de rotación y C es la matriz diagonal, cuyos elementos
corresponden a los coeficientes de difusión en cada una de las componentes
principales, de modo que al proyectarse el gradiente sobre el tensor, en la ecuación
de la difusión, se potencie el proceso de difusión en las direcciones de menor
variabilidad, esto es, en direcciones perpendiculares a la componente principal de
mayor autovalor. A este tipo de difusión, donde la difusividad es un tensor y no un
escalar, se la denomina anisotrópica.
Esta formulación es extensible a cualquier dimensión de la imagen, y
además, se puede también generalizar a imágenes de valores de tipo vector,por lo que
puede aplicarse al filtrado de imágenes en color. Para una imagen de vector u=(u1, u2,
..., un)T, la difusión isotropica quedará definida como:
  n
 
T

∂ t u = div g  ∑ ∇u j ∇u j ∇u 
 j =1

 
 
Y la anisotrópica como:
  n
 
T


∂ t u = div D ∑ ∇u j ∇u j ∇u 


j
=
1




En el caso de la difusión anisotrópica, el tensor emplea la propuesta de Di Zenzo
para matrices con valores de vectores.
6.2
Difusión anisotrópica del realce de la coherencia local
En función de la aplicación en concreto se definirán distintos tipos de tensor.
Por ejemplo, en aplicaciones donde se pretende recuperar la coherencia local de la
estructura de la imagen, perturbada generalmente por los sistemas de adquisición,
Weickert y Schnörr han propuesto el uso del tensor de difusión de realce de la
coherencia local (CED - Coherence Enhancing Filtering). La estructura del tensor se
basa en el producto del descriptor gradiente suavizado con su transpuesta y
convolucionado con la máscara de Gauss Kρ:
GVA-ELAI-UPM®PFC0081-2004
71
Combinación de la difusión isotrópica y anisotrópica en el
procesamiento de imágenes
(
S = K ρ * ∇uσ ∇uσT
Ignacio Berzal Moreno
)
∇u σ = K σ * ∇u
Kσ =
1
(2πσ )m / 2
 u2 

exp −
2
 2σ 


donde S es una matriz que es invariante ante los cambios de signo de la dirección del
gradiente, pero dependiente de su magnitud. El valor de la desviación típica σ
depende de la escala del ruido y el valor de ρ depende de la orientación local. Los
autovectores de S, para ρ = 0, son paralelos y ortogonales a ∇uσ . Con la última
convolución, con ρ, se ha pasado de la dirección puntual del gradiente a la
orientación prominente estimada de la estructura local. A S se la conoce como tensor
de estructura, operador de interés o matriz de segundo momento.
Para realzar los patrones locales se propone que los coeficientes la matriz
diagonal C sean dados por:
ci = α
i = 2,..., m
y
k =0
α


c1 = α + (1 − α ) exp − C 



 k
Habiendo ordenado las componentes de menor a mayor autovalor. Por tanto, la
primera componente, estará indicando la dirección de máxima homogeneidad local
en el nivel de irradiación, esto es, de mínima variabilidad en esa dirección de esta
componente principal. El valor de C es un umbral que se compara con el nivel de
coherencia local y α es un parámetro de difusividad que está en el intervalo (0,1),
para garantizar el suavizado del tensor de difusión. Para medir si un entorno de
vecindad es homogéneo o no, se introduce la medida de coherencia local:
k = ∑∑ (µ i − µ j )
m
2
i =1 i ≠ j
siendo µi el autovector de la componente principal i de S(.). De forma que si los
autovalores son similares, el índice de coherencia, k, será pequeño y los coeficientes
72
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Combinación de la difusión isotrópica y anisotrópica en el
procesamiento de imágenes
de difusión serán similares, dándose un proceso de difusión cuasi-isotrópica. Para el
caso de discrepancias en los autovalores, indicará un entorno con componentes
principales destacadas respecto de las otras, provocando un proceso de difusión
anisotrópica en la dirección de menor variabilidad.
Para imágenes 2D están extendidas las expresiones analíticas del tensor CED.
Los autovalores de la matriz de segundo momento, S, valen:
1
(s11 + s12 − γ )
2
1
µ 2 = (s11 + s12 + γ )
2
µ1 =
γ =
(s11 − s 22 )2 − 4s122
Y el tensor de difusión CED está definido por la matriz diagonal C y los autovalores
de S:
d11 =
(c − c )(s − s ) 
1
 c1 + c 2 + 2 1 11 22 
γ
2

d 22 =
(c − c )(s − s ) 
1
 c1 + c 2 − 2 1 11 22 
γ
2

d12 =
(c1 − c 2 )s12
γ
Sin embargo, para el caso 3D se suele recurrir a métodos numéricos,
implementado distintas variantes del método numérico de Jacobi. Como alternativa,
se pueden encontrar soluciones exactas mediante la teoría matemática de los
invariantes (funciones escalares de la matriz que como el determinante no cambian al
cambiar de base). El cálculo de los autovalores de un tensor simétrico de orden 3
requiere introducir los siguiente invariantes de la matriz de segundo momento:
GVA-ELAI-UPM®PFC0081-2004
73
Combinación de la difusión isotrópica y anisotrópica en el
procesamiento de imágenes
I 1 = tr (S )
(( )
1
2
tr S 2 − tr (S )
2
I 3 = det (S )
I2 =
Ignacio Berzal Moreno
)
que sirven para calcular los invariantes de la componente desviadora de S,
~
1
S = S − I1 I
3
:
((
) ( )) (
)
1
~
~2 1
tr S 2 − tr S = I 12 + 3I 2
3
2
~
1
2 I 13 + 9 I 1 I 2 + 27 I 3
J 3 = det S =
27
J2 =
()
(
)
que a su vez permite calcular el ángulo de Lode:
cos(3θ ) =
3 3 J3
2 J 23 / 2
0 ≤θ ≤
π
3
Y se puede demostrar que los autovalores del tensor S ordenados de menor a mayor
son:
µ1 = I1 + 2
1
3
J2
2π 

cosθ +

3
3


1
3
J2
2π 

cosθ −

3
3 

1
3
J2
cos(θ )
3
µ 2 = I1 + 2
µ 3 = I1 + 2
El cálculo de los elementos del tensor será función de la matriz de segundo
momento, de los coeficientes de difusividad en cada componente y de los
autovalores. El tensor de difusión D se reconstruye a partir de la matriz de rotación R
y de una matriz diagonal C de difusión, según:
74
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Combinación de la difusión isotrópica y anisotrópica en el
procesamiento de imágenes
C = RDR t , por tanto:
Dij = c1 R1i R1 j + c2 R2i R2 j + c3 R3i R3 j
y se obtiene:
%
ck (S%
i3 + si3µk )(Sj3 + sj3µk )
Dij = ∑
si i, j =1,2
2
2
2 2
%
%
%
S
s
S
s
S
s
s
(
)
(
)
(
(
)
)
µ
µ
µ
µ
+
+
+
+
+
+
−
k=1 i3
j3 k
j3
j3 k
k
33
11
22 k
k
2
%
ck (S%
i3 + si3µk )(S33 +(s11 + s22 )µk − µk )
Di3 = ∑
si i =1,2
2
2
2 2
%
%
%
k=1 (Si3 + sj3µk ) +(Sj3 + sj3µk ) + (S33 +(s11 + s22 )µk − µk )
k
2 2
ck (S%
33 +(s11 + s22 )µk − µk )
D33 = ∑
2
2
2 2
%
%
%
k =1 (Si3 + sj3µk ) +(Sj3 + sj3µk ) +(S33 +(s11 + s22)µk − µk )
k
siendo S%
ij el adjunto ij de la matriz S.
Esta forma de calcular el tensor de difusión en 3D agiliza el tiempo de
cómputo, respecto a los métodos numéricos, casi en un orden de magnitud.
6.3
Condiciones de difusión anisotrópica e isotrópica de
CED
Para el caso del tensor CED se observa que cuando los autovalores de la
matriz de segundo momento son muy similares, todas las componentes tienen
aproximados coeficientes de difusividad, en este caso, el tensor se convierte en una
matriz diagonal ponderada por el parámetro de difusión α. La decisión en un píxel
determinado de realizar difusión isotrópica o anisotropica depende del nivel de
umbral, C, y de la medida de coherencia local, k. Según la ecuación,
α
k =0


c1 = α + (1 − α ) exp − C 



 k
vista anteriormente, la difusión será anisotrópica cuando la medida de coherencia
local sea mayor a cero, pero si se relaja la condición con una aportación significativa
del valor de α , ello permitirá definir el nivel de umbral, C, a partir de la información
GVA-ELAI-UPM®PFC0081-2004
75
Combinación de la difusión isotrópica y anisotrópica en el
procesamiento de imágenes
Ignacio Berzal Moreno
de la imagen. Así, una vez obtenido el índice de coherencia local, k, en cada píxel de
la imagen a procesar, se tendrá su rango dinámico, pudiendo definir el valor de C
como:
α 1 

C = −k * ⋅ log
 f 1−α 
Siendo f la fracción de α que se considere significativa para pasar de difusión
isotrópica a anisotrópica, y k* el nivel de medida de coherencia local en la que se va
a empezar a aplicar la difusión anisotrópica. Por tanto, para valores de medida de
coherencia local mayor a k* se tendrá difusión anisotrópica y en caso contrario, será
difusión isotrópica. De esta forma será posible definir el valor del umbral, C,
mediante una visualización previa del índice de coherencia en cada uno de los
píxeles.
Esta propiedad, además, puede ser aprovechada para agilizar los tiempos de
computación, ya que si la medida de coherencia local, k, está por debajo de k*, no se
calculará el tensor y se sustituirá por la matriz diagonal Iα. En caso contrario, se
procederá a determinar el tensor. El valor de k depende de si se procesan imágenes
2D o 3D. Para el caso 2D, la medida local de coherencia coincide con γ2 y en 3D con
el invariante J2:
k = ∑∑ (µ i − µ j ) = γ 2
2
2
i =1 i ≠ j
k = ∑∑ (µ i − µ j ) = 6 J 2
3
i =1 i ≠ j
2
(2 D )
(3D )
Aprovechando esta propiedad, las reducciones de tiempo de computación
dependerán de la naturaleza de la imagen a procesar. En el caso 2D, por cada píxel
de similares autovalores, el ahorro es de 15 sumas, 3 multiplicaciones, 7 divisiones y
2 potencias. Más significativo es el caso de 3D, donde se ahorraría 232 sumas, 211
multiplicaciones, 68 potencias y 4 operaciones trigonométricas.
6.4
Combinación de la difusión isotrópica y anisotrópica
En imágenes con mucho ruido, el nivel de coherencia local, k, se ve muy
afectado, alterándose por una pérdida de las verdaderas componentes principales. En
estos casos puede resultar interesante realizar una búsqueda de patrones dentro del
propio ruido, por ejemplo realzando el flujo o tendencias existente dentro de la
propia imagen ruidosa. Pero cuando se pretende determinar la estructura de los
76
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Combinación de la difusión isotrópica y anisotrópica en el
procesamiento de imágenes
cuerpos presentes en la imagen y suponga la preservación de los bordes, los
resultados de la difusión anisotrópica fallan. Esto se debe en gran medida, a que la
intención del CED es buscar y realzar los patrones de la imagen y no la eliminación
del ruido. Cuando éste aparece, el nivel de coherencia local disminuye y CED tiende
a tener un comportamiento isotrópico. La difusividad se ha convertido en un escalar,
α. Pero esta constante, ni siquiera depende de la magnitud del módulo del gradiente.
Debido a ésto, resulta más interesante eliminar previamente el ruido a partir de una
difusión isotrópica. Luego, una vez preprocesada, la imagen está preparada para
poder realzar los patrones existentes.
6.4.1 Resultados de difusión isotrópica y anisotrópica. Ejemplos
Comenzaremos con un ejemplo de difusión en 2D. En la serie de figuras 6.1,
tenemos una imagen sintética cuyos bordes se han desvirtuado tras ser sometida a
ruido gausiano. La imagen 6.1.a muestra la fuente. A la 6.1.b se le ha aplicado un
filtrado tipo CED. El resultado es que el propio ruido ha generada marcas de patrones
aleatorios.
Figura 6.1.a: Imagen sintética con ruido blanco
Figura 6.1.b: Imagen procesada
con CED
En la figura 6.1.c podemos ver la misma imagen tras la aplicación de un
filtrado de difusión isotrópico. Tiene un buen comportamiento en la eliminación del
ruido, pero éste no es efectivo en la conservación del borde, ya que carece de la
información local de la estructura. Por último, como vemos en la figura 6.1.d, si al
resultado del filtrado isotrópico se sigue con otra etapa de difusión CED, el resultado
del procesado resulta óptimo. Se ha eliminado el ruido y se han conservado los
bordes sintéticos.
GVA-ELAI-UPM®PFC0081-2004
77
Combinación de la difusión isotrópica y anisotrópica en el
procesamiento de imágenes
Figura 6.1.c: Imagen procesada con
difusión isotrópica
Ignacio Berzal Moreno
Figura 6.1.d: Imagen
procesada con difusión
isotrópica y difusión CED
El siguiente ejemplo muestra una aplicación de difusión 3D para la
reconstrucción 3D de una neurona madre empleando microscopia confocal. Podemos
ver las diferentes etapas en la serie de figuras 6.2:
La primera figura (6.2.a) muestra la fuente, que posee cierto grado de ruido tras etapa
de adquisición. Tras aplicarle un filtrado de difusión isotrópica (figura 6.2.b),
presenta buenos resultados en la eliminación del ruido, sin embargo, no es capaz de
preservar la estructura del cuerpo biológico.
Figura 6.2.a: Rodaja de una pila de imágenes
proveniente de un confocal sobre una neurona
madre
Figura 6.2.b: Imagen procesada
con CED
En la figura 6.2.c podemos observar el resultado tras la aplicación de CED.
Ésta hace aparecer terminaciones de la neurona que son falsas, debido al realce de
78
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Combinación de la difusión isotrópica y anisotrópica en el
procesamiento de imágenes
patrones que están fuera del campo de visión. Finalmente, obtenemos los resultados
óptimos con una combinación de difusión isotrópica y anisotropica, como muestra la
figura 6.2.d.
Figura 6.2.c: Imagen procesada con difusión Figura 6.2.d: Imagen procesada
isotrópica
con difusión isotrópica y difusión
CED
Finalmente, comparando las figura 6.3.a y b, podemos apreciar los efectos de
una combinación apropiada de difusión isotrópica y difusión CED tras llevar a
cabo la reconstrucción 3D de la neurona madre.
Figura 6.3.a: Reconstrucción 3D de una pila de imágenes proveniente de un
confocal sobre una neurona madre
GVA-ELAI-UPM®PFC0081-2004
79
Combinación de la difusión isotrópica y anisotrópica en el
procesamiento de imágenes
Ignacio Berzal Moreno
Figura 6.3.b: Reconstrucción 3D con filtrado combinado de
disusión isotrópica y anisotrópica
Como último ejemplo, en las figuras de la serie 6.4, podemos comprobar
como las técnicas de difusión también son válidas para el filtrado de imágenes en
color. La primera imagen ( figura 6.4.a ), muestra una aplicación de procesado de
imágenes de espermatozoides. El objetivo es facilitar la segmentación de los
nucleoides y de los halos de los espermatozoides. La imagen 6.4.b ha sido tratada
con un filtrado de difusión isotrópica. Podemos apreciar como ésta desdibuja los
nucleoides de los halos, pero elimina eficazmente el ruido de fondo.
Figura 6.4.a: Imágenes de espermatozoides
con fragmentación del ADN
80
Figura 6.4.b: Imagen procesada
con difusión isotrópica
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Combinación de la difusión isotrópica y anisotrópica en el
procesamiento de imágenes
La figura 6.4.c corresponde al resultado de una difusión CED en color. Con
ella se realzan los patrones de los halos y los nucleoides, pero persiste el ruido.
Finalmente, podemos apreciar de nuevo como los mejores resultados se dan con la
combinación de ambos procesos de difusión ( figura 6.4.d ).
Figura 6.4.c: Imagen procesada con difusión
CED
Figura 6.4.d: Combinación de
difusión isotropica y anisotropica
Por último, en la siguiente tabla tenemos una comparativa entre los tiempos
de cómputo del cálculo del tensor CED empleando métodos numéricos y con las
expresiones analíticas presentadas. Estas diferencias de tiempos llegan casi a dos
órdenes de magnitud en el caso 2D y un orden de magnitud en 3D.
Tamaño
Numérico
Simbólico
Ratio
64x64
187,5ms
3,1ms
60,48
128x128
781,4ms
13,7ms
57,03
256x256
3.760,9ms
57,6ms
65,29
512x512
19.907,9ms
206,3ms
96,49
32x32x32
2.987,4 ms
365.4ms
8.71
64x64x64
25.370,6ms
4.020,1ms
6.31
Figura 6.5: Tiempos de cómputo del tensor CED en un P-IV a 2.40GHz
GVA-ELAI-UPM®PFC0081-2004
81
Combinación de la difusión isotrópica y anisotrópica en el
procesamiento de imágenes
Ignacio Berzal Moreno
Con la determinación de las expresiones analíticas de los tensores 3D, en
función de la matriz de segundo momento y de los coeficientes de difusión, se ha
conseguido reducciones del tiempo de computación, casi en un orden de magnitud
respecto a los métodos numéricos.
82
GVA-ELAI-UPM®PFC0081-2004
7
Aplicación del filtrado de
difusión con imágenes JPG y PIC
En este capítulo vamos a describir el proceso de creación de una aplicación que
emplea las herramientas de visualización de imágenes en dos y tres dimensiones que
nos proporcionan las librerías de VTK , así como las de filtrado de difusión
isotrópica y anisotrópica, todo ello implementado en C++. Para llevar a cabo su
desarrollo se ha utilizado el modelo UML y la aplicación Rational Rose.
7.1 Modelado UML
7.1.1 Introducción
El paradigma orientado a objetos enfatiza la creación de clases que
encapsulan tanto los datos, como los algoritmos que se utilizan para manejar los
datos. Si se diseñan y desarrollan adecuadamente las clases orientadas a objetos,
éstas pueden reutilizarse en diferentes aplicaciones y arquitecturas de sistemas
basados en computadoras.
GVA-ELAI-UPM®PFC0081-2004
83
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
El modelo de proceso basado en componentes es un enfoque incremental,
iterativo, que permite configurar aplicaciones desde componentes preparados de
software, llamados clases.
La actividad se inicia con la identificación de las clases candidatas,
examinando los datos que se van a manejar por parte de la aplicación y los
algoritmos que se requieren para obtener la funcionalidad especificada como
requerimiento. Los datos y algoritmos correspondientes se empaquetan en clases. Las
clases creadas se almacenan en una biblioteca de clases o diccionario de datos.
Cuando se realiza una nueva aplicación y ya se han identificado las clases
candidatas, se examina si existen en la biblioteca para su uso, o bien si no existen se
crean. De esta forma se desarrolla la primera iteración de la aplicación mediante las
clases extraídas de la biblioteca y las clases nuevas construidas para cumplir con las
necesidades específicas del proyecto. El flujo del proceso vuelve a la espiral
incremental para añadir funcionalidad al proyecto y volver a introducir la iteración
de nuevos componentes al sistema.
Este modelo basado en componentes conduce a la reutilización de software,
brindando importantes beneficios al grupo desarrollador.
Para definir los componentes que se utilizarán para construir el sistema y sus
interfaces, se propuso utilizar el Lenguaje Unificado de Modelado (UML) [Booch,
1999], que conjunta las mejores características de los métodos de análisis y diseño
orientados a objetos y hoy en día se ha convertido en el método más utilizado en la
industria.
A finales de la década de 1990, Grady Booch, James Rambaugh e Ivar
Jacobson colaboraron para combinar y recopilar las mejores características de sus
métodos, adoptando los siguientes objetivos:
• Representar sistemas completos, en lugar de solamente la parte de software, usando
conceptos orientados a objetos.
• Establecer una relación explícita entre conceptos y código ejecutable.
• Crear un lenguaje de modelado que pudiera ser usado por humanos y máquinas.
El resultado fue un método unificado, denominado UML ( Unified Modeling
Language, o Lenguaje de Modelado Unificado ), que con bastante aceptación y éxito
se ha empleado por número importante de desarrolladores de software para las
labores de análisis y diseño de sistemas orientados a objetos.
UML presenta las ventajas de poder utilizarse como un lenguaje estándar,
principalmente gráfico, para visualizar, especificar, construir y documentar los
productos de un sistema de software. Se puede emplear con todos los procesos, a lo
84
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
largo del ciclo de vida de desarrollo y a través de diferentes tecnologías de
implementación.
7.1.2 Modelado visual
Tal como indica su nombre, UML es un lenguaje de modelado. Un modelo es
una simplificación de la realidad. El objetivo del modelado de un sistema es capturar
las partes esenciales del sistema. Para facilitar este modelado, se realiza una
abstracción y se plasma en una notación gráfica. Esto se conoce como modelado
visual.
El modelado visual permite manejar la complejidad de los sistemas a analizar
o diseñar. De la misma forma que para construir una choza no hace falta un modelo,
cuando se intenta construir un sistema complejo como un rascacielos, es necesario
abstraer la complejidad en modelos que el ser humano pueda entender.
UML sirve para el modelado completo de sistemas complejos, tanto en el
diseño de los sistemas software como para la arquitectura hardware donde se
ejecuten.
Otro objetivo de este modelado visual es que sea independiente del lenguaje
de implementación, de tal forma que los diseños realizados usando UML se pueda
implementar en cualquier lenguaje que soporte las posibilidades de UML
(principalmente lenguajes orientados a objetos).
UML es además un método formal de modelado. Esto aporta las siguientes
ventajas:
• Mayor rigor en la especificación.
• Permite realizar una verificación y validación del modelo realizado.
• Se pueden automatizar determinados procesos y permite generar código a partir de
los modelos y a la inversa (a partir del código fuente generar los modelos). Esto
permite que el modelo y el código estén actualizados, con lo que siempre se puede
mantener la visión en el diseño, de más alto nivel, de la estructura de un proyecto.
7.1.3 ¿Qué es UML?
UML es ante todo un lenguaje. Un lenguaje proporciona un vocabulario y una
reglas para permitir una comunicación. En este caso, este lenguaje se centra en la
representación gráfica de un sistema.
Este lenguaje nos indica cómo crear y leer los modelos, pero no dice cómo
crearlos. Esto último es el objetivo de las metodologías de desarrollo.
GVA-ELAI-UPM®PFC0081-2004
85
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
Los objetivos de UML son muchos, pero se pueden sintetizar sus funciones:
• Visualizar: UML permite expresar de una forma gráfica un sistema de forma que
otro lo puede entender.
• Especificar: UML permite especificar cuáles son las características de un sistema
antes de su construcción.
• Construir: A partir de los modelos especificados se pueden construir los sistemas
diseñados.
• Documentar: Los propios elementos gráficos sirven como documentación del
sistema desarrollado que pueden servir para su futura revisión.
Aunque UML está pensado para modelar sistemas complejos con gran
cantidad de software, el lenguaje es los suficientemente expresivo como para
modelar sistemas que no son informáticos, como flujos de trabajo (workflow ) en una
empresa, diseño de la estructura de una organización y por supuesto, en el diseño de
hardware.
Un modelo UML esta compuesto por tres clases de bloques de contrucción:
• Elementos: Los elementos son abstracciones de cosas reales o ficticias (objetos,
acciones, etc.)
• Relaciones: relacionan los elementos entre sí.
• Diagramas: Son colecciones de elementos con sus relaciones.
7.1.4 Diagramas UML
Un diagrama es la representación gráfica de un conjunto de elementos con sus
relaciones. En concreto, un diagrama ofrece una vista del sistema a modelar. Para
poder representar correctamente un sistema, UML ofrece una amplia variedad de
diagramas para visualizar el sistema desde varias perspectivas. UML incluye los
siguientes diagramas:
• Diagrama de casos de uso.
• Diagrama de clases.
• Diagrama de objetos.
• Diagrama de secuencia.
86
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
• Diagrama de colaboración.
• Diagrama de estados.
• Diagrama de actividades.
• Diagrama de componentes.
• Diagrama de despliegue.
Los diagramas más interesantes (y los más usados) son los de casos de uso,
clases y secuencia, por lo que nos centraremos en éstos. Para ello, se utilizará
ejemplos de un sistema de venta de entradas de cine por Internet.
El diagrama de casos de usos representa gráficamente los casos de uso que
tiene un sistema. Se define un caso de uso como cada interacción supuesta con el
sistema a desarrollar, donde se representan los requisitos funcionales. Es decir, se
está diciendo lo que tiene que hacer un sistema y cómo. En la figura 7.1 se muestra
un ejemplo de casos de uso, donde se muestran tres actores (los clientes, los
taquilleros y los jefes de taquilla) y las operaciones que pueden realizar (sus roles).
Figura 7.1: Diagrama de casos de uso
El diagrama de clases muestra un conjunto de clases, interfaces y sus
relaciones. Éste es el diagrama más común a la hora de describir el diseño de los
GVA-ELAI-UPM®PFC0081-2004
87
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
sistemas orientados a objetos. En la figura 7.2 se muestran las clases globales, sus
atributos y las relaciones de una posible solución al problema de la venta de entradas.
Figura 7.2: Diagrama de clases
En el diagrama de secuencia se muestra la interacción de los objetos que
componen un sistema de forma temporal. Siguiendo el ejemplo de venta de entradas,
la figura 7.3 muestra la interacción de crear una nueva sala para un espectáculo.
El resto de diagramas muestran distintos aspectos del sistema a modelar. Para
modelar el comportamiento dinámico del sistema están los de interacción,
colaboración, estados y actividades. Los diagramas de componentes y despliegue
están enfocados a la implementación del sistema.
88
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Figura 7.3: Diagrama de secuencia
7.1.5 Proceso de desarrollo
Aunque UML es bastante independiente del proceso de desarrollo que se siga,
los mismos creadores de UML han propuesto su propia metodología de desarrollo,
denominada el Proceso Unificado de Desarrollo.
El Proceso Unificado está basado en componentes, lo cual quiere decir que el
sistema software en construcción está formado por componentes software
interconectados a través de interfaces bien definidos. Además, el Proceso Unificado
utiliza el UML para expresar gráficamente todos los esquemas de un sistema
software. Pero, realmente, los aspectos que definen este Proceso Unificado son tres:
es iterativo e incremental, dirigido por casos de uso y centrado en la arquitectura:
• Dirigido por casos de uso: Basándose en los casos de uso, los desarrolladores crean
una serie de modelos de diseño e implementación que los llevan a cabo. Además,
estos modelos se validan para que sean conformes a los casos de uso. Finalmente, los
casos de uso también sirven para realizar las pruebas sobre los componentes
desarrollados.
GVA-ELAI-UPM®PFC0081-2004
89
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
• Centrado en la arquitectura: En la arquitectura de la construcción, antes de
construir un edificio éste se contempla desde varios puntos de vista: estructura,
conducciones eléctricas, fontanería, etc. Cada uno de estos aspectos está representado
por un gráfico con su notación correspondiente. Siguiendo este ejemplo, el concepto
de arquitectura software incluye los aspectos estáticos y dinámicos más significativos
del sistema.
• Iterativo e incremental: Todo sistema informático complejo supone un gran
esfuerzo que puede durar desde varios meses hasta años. Por lo tanto, lo más práctico
es dividir un proyecto en varias fases. Actualmente se suele hablar de ciclos de vida
en los que se realizan varios recorridos por todas las fases. Cada recorrido por las
fases se denomina iteración en el proyecto en la que se realizan varios tipos de
trabajo (denominados flujos). Además, cada iteración parte de la anterior
incrementado o revisando la funcionalidad implementada. Se suele denominar
proceso.
Figura 7.4: Proceso iterativo e incremental
Resumiendo, el Proceso Unificado es un modelo complejo con mucha
terminología propia, pensado principalmente para el desarrollo de grandes proyectos.
Es un proceso que puede adaptarse y extenderse en función de las necesidades de
cada empresa.
90
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
7.2 La herramienta Rational Rose
Rational Rose es una herramienta CASE software para el modelado visual,
mediante UML, de sistemas software. Permite especificar, analizar y diseñar el
sistema antes de codificarlo, manteniendo la consistencia de los modelos del sistema
software. Utilizando la sintaxis del modelado UML, permite la generación de
documentación automáticamente, y la generación de código a partir de los modelos
(en varios lenguajes de programación como Java o C++), así como la aplicación de
ingeniería inversa (crear modelos a partir de código).
Figura 7.5: Logo de Rational
Integrando los ambientes de modelado y desarrollo, y utilizando el Unified
Modeling Language (UML), Rational Rose permite que todos los miembros de
equipo desarrollen individualmente, se comuniquen colaborativamente y produzcan
mejor software.
Con la capacidad de crear arquitecturas basadas en componentes flexibles,
Rational Rose permite que los procesos de software evolucionen en forma
controlada, administrada e identificable, reduciendo los costos y acelerando los
tiempos de entrega.
Por todos estos motivos, la herramienta Rational Rose ha sido la elegida para
desarrollar nuestra aplicación de visualización y filtrado de imágenes.
7.3 Documentación de la aplicación difusión2D3D
El programa “difusión2D3D” es el resultado práctico del desarrollo de una
aplicación mediante las técnicas de modelado UML y la herramienta Rational Rose.
Para llevar a cabo su elaboración según el modelo UML, antes de
implementar el código del programa es necesario completar una serie de documentos
que nos permitirán una rápida y fácil asimilación de los objetivos y el
funcionamiento de la aplicación, así como su viabilidad, alcance y restricciones.
GVA-ELAI-UPM®PFC0081-2004
91
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
7.3.1 Visión y alcance de la aplicación
El primero de los documentos a rellenar es el de "visión y alcance", ya que en
él se reflejarán las características más importantes del proyecto. Este documento
pone de acuerdo a clientes y desarrolladores. Además de una visión global del
sistema, también incluye su justificación de mercado y sus limitaciones.
El documento de visión y alcance se divide en varias categorías, y a su vez
éstas se descomponen en distintos apartados, los cuáles se exponen a continuación.
7.3.1.1 Requerimientos del negocio
<Los requisitos del negocio proporcionan el origen y la referencia para todo
el desarrollo de los requisitos detallados. Se puede recolectar requisitos del
negocio del cliente desde un patrocinador ejecutivo, un visionario del
proyecto, gerencia de producto, el departamento de la comercialización, u
otros individuos que tienen un sentido claro de porqué se está emprendiendo
el proyecto y el último valor que proporcionará, al negocio y a los clientes.>
7.3.1.1.1 Introducción
<Esta sección resume el análisis razonado para el nuevo producto. Proporcione
una descripción general de la historia o situación que haya decidido la construcción
de este producto.>
Se pretende realizar una plataforma para el análisis de imágenes 2D y 3D
empleando técnicas de difusión isotrópica y anisotrópica. Las imágenes serán en
niveles de grises y en color para 2D y en 3D, sólo en niveles de grises. En esta
plataforma se cubrirá los siguientes aspectos:
- Visualización de imágenes 2D dentro de un GUI
- Visualización de imágenes 3D dentro de un GUI con toda facilidad del procesos
de reconstrucción 3D: conversión del dominio de la imagen al dominio
geométrico (marching cubes,...), reducción de puntos, suavizado, etc
- Filtrados isotrópicos y anisotrópicos
- Aperturas de ficheros de imágenes 3D de tipo PIC
- Procesamiento distribuido
92
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
7.3.1.1.2 Oportunidad del negocio
<En esta sección se describe la oportunidad del mercado que existe o el
problema que se pretende solucionar. Describe el mercado en el cual el producto
comercial competirá o el ambiente en el cual el sistema de información será
utilizado. Esto puede incluir una breve evaluación comparativa de productos
existentes y de soluciones potenciales, indicando porqué el producto propuesto es
atractivo.>
Será una plataforma abierta para la investigación de las técnicas de difusión
isotrópicas y anisotrópicas de imágenes 2D y 3D, capaces de realizar visualización
de los resultados y procesamientos distribuido.
7.3.1.1.3 Objetivos esenciales y criterios de éxito
<En este apartado se describen los objetivos de negocio importantes del
producto en una manera que sea cuantitativa y medible. El valor proporcionado a
los clientes se describe en la sección 1.4, en esta sección tan sólo debe centrarse en
el valor proporcionado al negocio. Esto podía incluir estimaciones de los ahorros de
coste, vuelta en análisis de inversión, o fechas del lanzamiento del producto.
Determínese cómo el éxito será definido y medido en este proyecto, y describa los
factores que son probables para tener el más grande de los impactos en la
realización con éxito del proyecto. Incluya las cosas dentro del control directo de la
organización, así como factores externos. Establezca los criterios medibles para
determinar si se han resuelto los objetivos de negocio.>
1. Visualización de las imágenes 2D y 3D: Se podrán visualizar las imágenes de
entrada, contenidas en un fichero, y también las generadas del proceso de
filtrado
2. Se implementarán los filtros 2D y 3D de difusión isotrópica y anisotrópica
3. El procesamiento podrá ser elegido de tipo distribuido
7.3.1.1.4 Necesidades de los usuarios
<Esta sección describe las necesidades de los clientes típicos o de segmentos
de mercado, incluyendo las necesidades que todavía no son satisfechas por el
mercado o por los sistemas existentes. Se pueden describir los problemas que los
clientes encuentran actualmente y cómo el producto sería utilizado por los futuros
clientes. Hay que identificar el ambiente del hardware y del software del cliente en el
cual el producto debe funcionar. Se debe definir en un alto nivel cualquier requisito
crítico sabido de interfaz o de funcionamiento. Hay que evitar incluir cualquier
detalle del diseño o de la puesta en práctica. Los requisitos se presentan en una lista
GVA-ELAI-UPM®PFC0081-2004
93
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
numerada para poder cumplir los objetivos del usuario, también llamados,
requisitos funcionales.>
1. Tener una plataforma abierta para poder investigar nuevos algoritmos de visión
para el procesamiento de imágenes 2D y 3D. Esta plataforma deberá ser bancada
para las nuevas librerías de análisis de imágenes, tales como VTK e ITK.
7.3.1.1.5 Riesgos del negocio
<Aquí se sumarizan los mayores riesgos del negocio asociado con el desarrollo
de este producto, tales como la competencia en el Mercado, los tiempos de
realización, la aceptación de los usurarios, los tipos de implementación o posibles
impactos negativos sobre el negocio. Hay que estimar la diversidad de los riesgos y
cómo se podrían mitigar.>
Esta plataforma será un framework de futuros proyectos y de nuevos trabajos de
investigación. Deberá ser abierta y con capacidad para poder cambias de nuevas
librerías de servicio, por ejemplo, sustituir las VTK por otras. Los riesgos que se
tienen son:
1. Que la plataforma sea difícil de mantener y de aumentar
2. Que este ligado los aspectos de visualización con los de procesamiento
3. La documentación debe ser abundante
4. No está claro cómo se realizarán las técnicas de análisis de imágenes con un
procesamiento distribuido en la red
7.3.1.2 Visión de la solución
<Esta sección establece una visión a largo plazo para que el sistema sea
construido cumpliendo los objetivos de negocio. Esta visión proporcionará el
contexto para tomar decisiones a través del curso del ciclo vital del desarrollo de
producto. La visión no debe incluir requisitos o la información funcionales
detallados del planeamiento del proyecto.>
7.3.1.2.1 Visión global
<Aquí se presenta una declaración sucinta de la visión que resuma el
propósito y el intento del producto nuevo y describa cuáles será el mundo cuando se
incluye el producto. La declaración de la visión debe reflejar una visión equilibrada
que satisfaga las necesidades de clientes diversos así como de la organización
94
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
posible del proyecto. Puede ser algo idealista, pero debe ser puesto a tierra en las
realidades de los mercados existentes o de los anticipados cliente, arquitecturas de
las empresa, direcciones estratégicas de organización, y limitaciones del coste y del
recurso.>
El programa "difusion2D3D" permitirá visualizar imágenes en dos y tres
dimensiones, así como sus respectivos filtrados de difusión. Se necesitará la imagen
inicial a filtrar. El programa generará un archivo de imagen con el resultao del
filtrado.
7.3.1.2.2 Principales características
<Este apartado incluye una lista numerada de las características principales del
producto nuevo, acentuando aquellas características que lo distinguen de anterior
versiones o de productos de competencia. Las exigencias del consumidor específicas
y los requisitos funcionales se pueden retomar de nuevo a estas características.>
1. Análisis de las imágenes:
a) Visualización de imágenes 2D provenientes de ficheros o del resultado
final de la etapa de procesamiento
b) Procesamiento de imágenes 2D con filtrados de difusión isotrópico y
anisotrópico, tanto en imágenes en niveles de grises como en color
c) Procesamiento de imágenes 3D con filtrados de difusión isotrópico y
anisotrópico ( sólo en niveles de grises )
d) Reconstrucción 3D siguiendo el proceso VTK
2. Procesamiento distribuido de las etapas de filtrado
3. Realización de GUI independientes de la plataforma
7.3.1.2.3 Suposiciones y dependencias
<Esta sección registra cualquier hipótesis que fuera hecha al concebir el
proyecto y al escribir este documento de visión y del alcance. Hay que observar
cualquier dependencia importante que el proyecto deba confiar para el éxito, por
ejemplo tecnologías específicas, vendedores de tercera persona, socios del
desarrollo, u otras relaciones del negocio.>
- El formato de las imágenes serán las soportadas por las VTK, añadiendo las
imágenes tipo PICs
GVA-ELAI-UPM®PFC0081-2004
95
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
7.3.1.3 Alcance y restricciones
<El alcance del proyecto define el concepto y la gama de soluciones
propuestas. Es también importante definir qué no será incluida en el producto.
Clarificar el alcance y las limitaciones para establecer expectativas realistas de las
distintas soluciones. También proporciona un marco de la referencia para nuevas
características propuestas y los cambios de los requisitos que puedan ser evaluados.
Los requisitos propuestos que están fuera de alcance del producto previsto se deben
rechazar, a menos que sean tan beneficiosos que su repercusión sean muy
importante>
7.3.1.3.1 Características principales en la primera versión
<En esta sección se describen las características principales previstas que
serán incluidas en el lanzamiento inicial del producto. Hay que considerar las
ventajas que el producto se piensa puede atraer a las varias comunidades del
cliente, y describir generalmente las características de producto y las características
de la calidad que le permitirán proporcionar esas ventajas. Evitar la tentación de
incluir cada característica posible que cualquier categoría potencial del cliente
pudo concebir en un cierto día. Hay que centrarse en esas características y
características del producto que proporcionen la mayoría del valor, en el coste más
aceptable del desarrollo, y de mayor interés a la comunidad más amplia.>
1. Visualización de imágenes 2D y 3D
2. GUI independientes de la plataforma
3. Filtrados de difusión isotrópicos y anisotrópicos
4. Procesamiento distribuido de las tareas de filtrado
7.3.1.3.2 Mejoras en las siguientes versiones
< Aquí se indica qué características importantes se podrán dar en versiones
posteriores.>
1. Escenarios AOS
2. Nuevas propuestas de filtros de difusión isotrópica y anisotrópica
3. Procesamiento distribuido inteligente (p. Ej. Marching cubes, ...)
96
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
7.3.1.3.3 Limitaciones y Exclusiones
<En este apartado se identifica cualesquier característica del producto que
se pudiera anticipar, pero que no se planean para ser incluidas en el proyecto.>
- El tiempo de procesamiento no estará limitado.
7.3.2 Casos de uso
Los siguientes documentos a rellenar son los de los "casos de uso". En ellos
se describen los distintos requisitos funcionales de la aplicación. Para cada caso de
uso, se indican, entre otras cosas, los actores que intervienen, su curso de éxito, las
precondiciones y postcondiciones o las excepciones al curso de éxito.
En la aplicación "difusión2D3D" se han desarrollado cuatro casos de uso:
- Visualizar 2D
- Visualizar 3D
- Filtrar difusión 2D
- Filtrar difusión 3D
A continuación se incluye la descripción de cada uno de ellos que, al igual
que en el documento de visión y alcance, se subdividen en distintas secciones y
apartados.
7.3.2.1
Caso de uso visualizar 2D
7.3.2.1.1 Actor
<Un actor es la persona o entidad externa al sistema de software que trabaja
con el sistema y realiza casos del uso para lograr tareas. Diversos agentes
corresponden a menudo a diversas clases del usuario, o papeles, definiendo la
comunidad del cliente que utilizará el producto. Nombre del actor(s) que realizará
este caso del uso.>
Usuario
GVA-ELAI-UPM®PFC0081-2004
97
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
7.3.2.1.2 Descripción
<Este apartado proporciona una breve descripción de la razón y del
resultado de este caso del uso, o una descripción de alto nivel de la secuencia de
acciones y del resultado al ejecutar el caso del uso>
El usuario indica el nombre de una imagen 2D en escalas de grises o en color
con extensión JPG. El sistema leerá y abrirá el fichero permitiendo su visualización.
7.3.2.1.3 Precondiciones
<Aquí se enumera cualquier actividad que deba ocurrir, o cualquier
condición que deban ser verdaderas, antes de que el caso del uso pueda ser
comenzado. Se numera cada condición previa.>
1. Las imágenes son 2D y tienen el formato JPG.
7.3.2.1.4 Poscondiciones
<Se describe el estado del sistema en la conclusión de la ejecución del caso del uso.
Se numera cada postcondition.>
1. Al indicar el nombre de la imagen, aparece una pantalla en la que se visualiza
dicha imagen.
7.3.2.1.5 Curso de éxito
<En este apartado se hace una descripción detallada de cómo actúa el
sistema ante este caso de uso, en su curso de éxito o normal, evitando las
bifurcaciones. Esta descripción se realizará a modo de estados en el que evoluciona
el sistema en la realización del caso de uso. La enumeración será con “X.0”, donde
“X” es el ID del uso de caso.>
1.0 El usuario abre un browser para buscar las imágenes JPG.
2.0 El usuario busca y elige la imagen a visualizar.
3.0 El nombre de esta imagen y su localización se carga en el programa.
4.0 Se abre una ventana en que se visualiza la imagen elegida.
98
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
7.3.2.1.6 Curso alternativo
<Cursos alternativos y legítimos del uso que pueden ocurrir dentro de este
caso de uso. Se indica el curso alternativo, y se describe cualquier diferencia en la
secuencia de los pasos que ocurren. Se numera cada curso alternativo en la forma
"X.Y ", donde "X" identifica el caso de uso y la “Y” es un número de serie para la
alternativa. Por ejemplo, "5.3" indicarían el tercer curso alternativo para el caso
número 5 del caso de uso.>
1.1 El usuario carga directamente el nombre de la imagen.
7.3.2.1.7 Excepciones
<En este apartado se describe cualquier condición de error anticipada que
podría ocurrir durante la ejecución del caso de uso, y se define cómo el sistema es
capaz de responder a estas condiciones. También, se describe cómo el sistema
responde si la ejecución del caso de uso falla por una cierta razón inesperada. Se
numera cada curso alternativo en la forma "X.Y.E.Z ", donde "X" identifica el caso
del uso, Y indica (0) normal o el curso alternativo (>0) durante los cuales esta
excepción podría ocurrir, "E" indica una excepción, y "Z" es un número de serie
para las excepciones. Por ejemplo "5.0.E.2 "indicaría la segunda excepción para el
curso normal para el caso número 5 del uso.>
2.0.E1 La imagen elegida no es del tipo JPG. Se le comunicará al usuario con una
ventana de aviso y tendrá que volver a elegir otra imagen.
1.1.E1
El nombre de la imagen dada no es del tipo JPG. Se le comunicará al
usuario con una ventana de aviso y tendrá que dar otro nombre o elegir la imagen
mediante el browser.
7.3.2.1.8 Prioridad
<Indica la prioridad relativa de poner en ejecución este caso de uso. El
esquema de la prioridad usado debe ser igual que el especificado en los requisitos
del software.>
Muy alta
7.3.2.1.9 Frecuencia de caso de uso
<Aquí se estima el número de veces que este caso de uso será realizado por
los actores por una cierta unidad de tiempo apropiada.>
GVA-ELAI-UPM®PFC0081-2004
99
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
Muy a menudo
7.3.2.1.10 Requerimientos especiales
<En esta sección se identifica cualquier requisito adicional, por ejemplo
requisitos no funcionales, para el caso del uso que puede necesitar ser tratado
durante diseño o la puesta en práctica. Éstos pueden incluir requisitos de
funcionamiento u otras cualidades referente a la calidad.>
1. Internacionalización del lenguaje de texto que se muestra.
2. Aplicación sobre cualquier sistema operativo ( multiplataforma )
7.3.2.1.11 Suposiciones de partida
<Aquí se numera cualquier suposición de partida que fuera hecha en el
análisis que condujo a aceptar este caso del uso en la descripción del producto >
1. Las imágenes serán 2D y estarán en formato JPG.
7.3.2.1.12
Cuadro resumen del caso de uso visualizar 2D
Actores: Usuario
Descripción: El usuario busca o da el nombre de una imagen 2D en color
con extensión JPG. El sistema leerá y abrirá el fichero
permitiendo su visualización
Precondiciones: Las imágenes son 2D y tienen el formato JPG
Poscondiciones: Aparece una pantalla en la que se visualiza la imagen
Curso normal: El usuario abre un browser para buscar las imágenes JPG. El
usuario busca y elige la imagen a visualizar. El nombre de
esta imagen y su localización se carga en el programa. Se
abre una ventana en que se visualiza la imagen elegida
Curso alternativo: El usuario carga directamente el nombre de la imagen.
Excepciones: La imagen elegida no es del tipo JPG. El nombre de la
imagen dada no es del tipo JPG
Inclusiones:
Prioridad: Muy alta
Frecuencia de uso: Muy a menudo
Reglas de negocio:
Requerimientos Internacionalización del lenguaje de texto que se muestra.
100
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
especiales: Aplicación sobre sistemas operativos de Microsoft.
Suposiciones de partida: Las imágenes serán de 2D y estarán en formato JPG.
Notas y documentos:
7.3.2.2 Caso de uso visualizar 3D
7.3.2.2.1 Actor
<Un actor es la persona o entidad externa al sistema de software que trabaja
con el sistema y realiza casos del uso para lograr tareas. Diversos agentes
corresponden a menudo a diversas clases del usuario, o papeles, definiendo la
comunidad del cliente que utilizará el producto. Nombre del actor(s) que realizará
este caso del uso.>
Usuario
7.3.2.2.2 Descripción
<Este apartado proporciona una breve descripción de la razón y del
resultado de este caso del uso, o una descripción de alto nivel de la secuencia de
acciones y del resultado al ejecutar el caso del uso>
El usuario busca o da el nombre de una imagen 3D en escala de grises con
extensión PIC. El sistema leerá y abrirá el fichero permitiendo su visualización.
7.3.2.2.3 Precondiciones
<Aquí se enumera cualquier actividad que deba ocurrir, o cualquier
condición que deban ser verdaderas, antes de que el caso del uso pueda ser
comenzado. Se numera cada condición previa.>
1. Las imágenes son 3D y tienen el formato PIC.
7.3.2.2.4 Poscondiciones
<Se describe el estado del sistema en la conclusión de la ejecución del caso del uso.
Se numera cada postcondition.>
1. Al indicar el nombre de la imagen, aparece una pantalla en la que se visualiza
dicha imagen.
GVA-ELAI-UPM®PFC0081-2004
101
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
7.3.2.2.5 Curso de éxito
<En este apartado se hace una descripción detallada de cómo actúa el
sistema ante este caso de uso, en su curso de éxito o normal, evitando las
bifurcaciones. Esta descripción se realizará a modo de estados en el que evoluciona
el sistema en la realización del caso de uso. La enumeración será con “X.0”, donde
“X” es el ID del uso de caso.>
1.0 El usuario abre un browser para buscar las imágenes PIC.
2.0 El usuario busca y elige la imagen a visualizar.
3.0 El nombre de esta imagen y su localización se carga en el programa.
4.0 Se abre una ventana en que se visualiza la imagen elegida.
7.3.2.2.6 Curso alternativo
<Cursos alternativos y legítimos del uso que pueden ocurrir dentro de este
caso de uso. Se indica el curso alternativo, y se describe cualquier diferencia en la
secuencia de los pasos que ocurren. Se numera cada curso alternativo en la forma
"X.Y ", donde "X" identifica el caso de uso y la “Y” es un número de serie para la
alternativa. Por ejemplo, "5.3" indicarían el tercer curso alternativo para el caso
número 5 del caso de uso.>
1.1 El usuario carga directamente el nombre de la imagen.
7.3.2.2.7 Excepciones
<En este apartado se describe cualquier condición de error anticipada que
podría ocurrir durante la ejecución del caso de uso, y se define cómo el sistema es
capaz de responder a estas condiciones. También, se describe cómo el sistema
responde si la ejecución del caso de uso falla por una cierta razón inesperada. Se
numera cada curso alternativo en la forma "X.Y.E.Z ", donde "X" identifica el caso
del uso, Y indica (0) normal o el curso alternativo (>0) durante los cuales esta
excepción podría ocurrir, "E" indica una excepción, y "Z" es un número de serie
para las excepciones. Por ejemplo "5.0.E.2 "indicaría la segunda excepción para el
curso normal para el caso número 5 del uso.>
2.0.E1 La imagen elegida no es del tipo PIC. Se le comunicará al usuario con una
ventana de aviso y tendrá que volver a elegir otra imagen.
102
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
1.1.E1 El nombre de la imagen dada no es del tipo PIC. Se le comunicará al usuario
con una ventana de aviso y tendrá dar otro nombre o elegirla imagen mediante el
browser.
3.0.E1 La imagen no están en escala de grises. Se producirá un error en el
procesamiento de la imagen y se le comunicará al usuario.
7.3.2.2.8 Prioridad
<Indica la prioridad relativa de poner en ejecución este caso de uso. El
esquema de la prioridad usado debe ser igual que el especificado en los requisitos
del software.>
Muy alta
7.3.2.2.9 Frecuencia de caso de uso
<Aquí se estima el número de veces que este caso de uso será realizado por
los actores por una cierta unidad de tiempo apropiada.>
Muy a menudo
7.3.2.2.10 Requerimientos especiales
<En esta sección se identifica cualquier requisito adicional, por ejemplo
requisitos no funcionales, para el caso del uso que puede necesitar ser tratado
durante diseño o la puesta en práctica. Éstos pueden incluir requisitos de
funcionamiento u otras cualidades referente a la calidad.>
1. Internacionalización del lenguaje de texto que se muestra.
2. Aplicación sobre cualquier sistema operativo ( multiplataforma )
7.3.2.2.11 Suposiciones de partida
<Aquí se numera cualquier suposición de partida que fuera hecha en el
análisis que condujo a aceptar este caso del uso en la descripción del producto >
1. Las imágenes serán de 3D en escala de grises y estarán en formato PIC.
GVA-ELAI-UPM®PFC0081-2004
103
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
7.3.2.2.12
Ignacio Berzal Moreno
Cuadro resumen del caso de uso visualizar 3D
Actores: Usuario
Descripción: El usuario busca o da el nombre de una imagen 3D en escala de
grises con extensión PIC. El sistema leerá y abrirá el fichero
permitiendo su visualización.
Precondiciones: Las imágenes son 3D y tienen el formato PIC.
Poscondiciones: Aparece una pantalla en la que se visualiza la imagen
Curso normal: El usuario abre un browser para buscar las imágenes JPG. El
usuario busca y elige la imagen a visualizar. El nombre de
esta imagen y su localización se carga en el programa. Se
abre una ventana en que se visualiza la imagen elegida
Curso alternativo: El usuario carga directamente el nombre de la imagen.
Excepciones: La imagen elegida no es del tipo PIC. El nombre de la imagen
dada no es del tipo PIC. La imagen no están en escala de
grises. Se producirá un error en el procesamiento de la
imagen y se le comunicará al usuario.
Inclusiones:
Prioridad: Muy alta
Frecuencia de uso: Muy a menudo
Reglas de negocio:
Requerimientos Internacionalización del lenguaje de texto que se muestra.
especiales: Aplicación sobre sistemas operativos de Microsoft.
Suposiciones de partida: Las imágenes serán de 3D en escala de grises y estarán en
formato PIC
Notas y documentos:
7.3.2.3 Caso de uso filtrar difusión 2D
7.3.2.3.1 Actor
<Un actor es la persona o entidad externa al sistema de software que trabaja
con el sistema y realiza casos del uso para lograr tareas. Diversos agentes
corresponden a menudo a diversas clases del usuario, o papeles, definiendo la
comunidad del cliente que utilizará el producto. Nombre del actor(s) que realizará
este caso del uso.>
Usuario
104
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
7.3.2.3.2 Descripción
<Este apartado proporciona una breve descripción de la razón y del
resultado de este caso del uso, o una descripción de alto nivel de la secuencia de
acciones y del resultado al ejecutar el caso del uso>
El usuario busca o da el nombre de una imagen 2D en color o en niveles de
grises, con extensión JPG. El sistema, tras procesar la imagen mediante filtrados de
difusión isotrópica y anisotrópica, genera una imagen filtrada como resultado.
7.3.2.3.3 Precondiciones
<Aquí se enumera cualquier actividad que deba ocurrir, o cualquier
condición que deban ser verdaderas, antes de que el caso del uso pueda ser
comenzado. Se numera cada condición previa.>
1. Las imágenes son 2D y tienen el formato JPG.
7.3.2.3.4 Poscondiciones
<Se describe el estado del sistema en la conclusión de la ejecución del caso del uso.
Se numera cada postcondition.>
1. Al analizar las imágenes, este caso de uso generará imágenes filtradas mediante
difusión isotrópica y anisotrópica que podrán ser visualizadas.
7.3.2.3.5 Curso de éxito
<En este apartado se hace una descripción detallada de cómo actúa el
sistema ante este caso de uso, en su curso de éxito o normal, evitando las
bifurcaciones. Esta descripción se realizará a modo de estados en el que evoluciona
el sistema en la realización del caso de uso. La enumeración será con “X.0”, donde
“X” es el ID del uso de caso.>
1.0
El usuario carga las imágenes en un directorio.
2.0
El usuario inicializa la aplicación y entrega al Sistema, mediante el GUI, el
directorio donde se encuentra la imagen a analizar.
El usuario introduce el nombre del fichero donde desea que se guarden los
resultados del filtrado.
3.0
GVA-ELAI-UPM®PFC0081-2004
105
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
4.0
El Sistema procesa las imágenes.
5.0
El usuario espera a que el sistema procese las imágenes.
Ignacio Berzal Moreno
7.3.2.3.6 Curso alternativo
<Cursos alternativos y legítimos del uso que pueden ocurrir dentro de este
caso de uso. Se indica el curso alternativo, y se describe cualquier diferencia en la
secuencia de los pasos que ocurren. Se numera cada curso alternativo en la forma
"X.Y ", donde "X" identifica el caso de uso y la “Y” es un número de serie para la
alternativa. Por ejemplo, "5.3" indicarían el tercer curso alternativo para el caso
número 5 del caso de uso.>
1.1 El usuario indica si desea llevar a cabo el filtrado de las imágenes
mediante procesamiento distribuído
7.3.2.3.7 Excepciones
<En este apartado se describe cualquier condición de error anticipada que
podría ocurrir durante la ejecución del caso de uso, y se define cómo el sistema es
capaz de responder a estas condiciones. También, se describe cómo el sistema
responde si la ejecución del caso de uso falla por una cierta razón inesperada. Se
numera cada curso alternativo en la forma "X.Y.E.Z ", donde "X" identifica el caso
del uso, Y indica (0) normal o el curso alternativo (>0) durante los cuales esta
excepción podría ocurrir, "E" indica una excepción, y "Z" es un número de serie
para las excepciones. Por ejemplo "5.0.E.2 "indicaría la segunda excepción para el
curso normal para el caso número 5 del uso.>
2.0.E.1 En el directorio de las imágenes que indica el Usuario no tiene ninguna
imagen. Se le mandará mensaje de que el directorio está vacío y no se dejará
continuar hasta que elija un directorio con imágenes JPG.
2.1.E.1 El procesamiento distribuído no puede llevarse a cabo. El Usuario recibirá un
mensaje indicándole lo ocurrido, y se le permitirá cambiar esta opción antes de
continuar.
4.0.E.1. No se pasará al procesamiento de las imágenes hasta que no esté el
directorio de las imágenes y el nombre de fichero de ubicación de resultados, ambos
verificados y correctos.
106
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
7.3.2.3.8 Prioridad
<Indica la prioridad relativa de poner en ejecución este caso de uso. El
esquema de la prioridad usado debe ser igual que el especificado en los requisitos
del software.>
Alta
7.3.2.3.9 Frecuencia de caso de uso
<Aquí se estima el número de veces que este caso de uso será realizado por
los actores por una cierta unidad de tiempo apropiada.>
A menudo
7.3.2.3.10 Requerimientos especiales
<En esta sección se identifica cualquier requisito adicional, por ejemplo
requisitos no funcionales, para el caso del uso que puede necesitar ser tratado
durante diseño o la puesta en práctica. Éstos pueden incluir requisitos de
funcionamiento u otras cualidades referente a la calidad.>
1. Internacionalización del lenguaje de texto que se muestra.
2. Aplicación sobre cualquier sistema operativo ( multiplataforma ).
3. El tiempo de procesamiento no estará limitado.
7.3.2.3.11 Suposiciones de partida
<Aquí se numera cualquier suposición de partida que fuera hecha en el
análisis que condujo a aceptar este caso del uso en la descripción del producto >
1. Las imágenes serán de 2D en escala de grises o en color, y estarán en formato
JPG.
7.3.2.3.12
Cuadro resumen del caso de uso filtrar difusión 2D
Actores: Usuario
Descripción: Procesar las imágenes mediante filtrados de difusión
isotrópica y anisotrópica, generando una imagen filtrada
como resultado
GVA-ELAI-UPM®PFC0081-2004
107
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
Precondiciones: Las imágenes son 2D y tienen el formato JPG
Poscondiciones: Generará imágenes filtradas mediante difusión
Curso normal: El usuario carga las imágenes en un directorio, inicializa la
aplicación y entrega al Sistema, mediante el GUI, el
directorio donde se encuentra la imagen a analizar y el
nombre del fichero donde desea que se guarden los resultados
del filtrado. El Sistema procesa las imágenes. El Usuario
espera a que el sistema procese las imágenes.
Curso alternativo: El usuario tiene la opción de llevar a cabo el filtrado de las
imágenes mediante procesamiento distribuído
Excepciones: En el directorio de las imágenes que indica el Usuario no
tiene ninguna imagen. El procesamiento distribuído no puede
llevarse a cabo.
Inclusiones:
Prioridad: Alta. Es una de las funcionalidades principales del programa
Frecuencia de uso: A menudo
Reglas de negocio:
Requerimientos El tiempo de procesamiento no estará limitado.
especiales:
Suposiciones de partida: Las imágenes serán de 2D en escala de grises o en color, y
estarán en formato JPG.
Notas y documentos:
7.3.2.4 Caso de uso filtrar difusión 3D
7.3.2.4.1 Actor
<Un actor es la persona o entidad externa al sistema de software que trabaja
con el sistema y realiza casos del uso para lograr tareas. Diversos agentes
corresponden a menudo a diversas clases del usuario, o papeles, definiendo la
comunidad del cliente que utilizará el producto. Nombre del actor(s) que realizará
este caso del uso.>
Usuario
7.3.2.4.2 Descripción
<Este apartado proporciona una breve descripción de la razón y del
resultado de este caso del uso, o una descripción de alto nivel de la secuencia de
acciones y del resultado al ejecutar el caso del uso>
108
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
El usuario busca o da el nombre de una imagen 3D en niveles de grises, con
extensión PIC. El sistema, tras procesar la imagen mediante filtrados de difusión
isotrópica y anisotrópica, genera una imagen filtrada como resultado.
7.3.2.4.3 Precondiciones
<Aquí se enumera cualquier actividad que deba ocurrir, o cualquier
condición que deban ser verdaderas, antes de que el caso del uso pueda ser
comenzado. Se numera cada condición previa.>
1. Las imágenes son 3D en escala de grises y tienen el formato PIC.
7.3.2.4.4 Poscondiciones
<Se describe el estado del sistema en la conclusión de la ejecución del caso del uso.
Se numera cada postcondition.>
1. Al analizar las imágenes, este caso de uso generará imágenes filtradas mediante
difusión isotrópica y anisotrópica que podrán ser visualizadas.
7.3.2.4.5 Curso de éxito
<En este apartado se hace una descripción detallada de cómo actúa el
sistema ante este caso de uso, en su curso de éxito o normal, evitando las
bifurcaciones. Esta descripción se realizará a modo de estados en el que evoluciona
el sistema en la realización del caso de uso. La enumeración será con “X.0”, donde
“X” es el ID del uso de caso.>
1.0
El usuario carga las imágenes en un directorio.
2.0
El usuario inicializa la aplicación y entrega al Sistema, mediante el GUI, el
directorio donde se encuentra la imagen a analizar.
3.0
El usuario introduce el nombre del fichero donde desea que se guarden los
resultados del filtrado.
4.0
El Sistema procesa las imágenes.
5.0
El usuario espera a que el sistema procese las imágenes.
7.3.2.4.6 Curso alternativo
<Cursos alternativos y legítimos del uso que pueden ocurrir dentro de este
caso de uso. Se indica el curso alternativo, y se describe cualquier diferencia en la
GVA-ELAI-UPM®PFC0081-2004
109
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
secuencia de los pasos que ocurren. Se numera cada curso alternativo en la forma
"X.Y ", donde "X" identifica el caso de uso y la “Y” es un número de serie para la
alternativa. Por ejemplo, "5.3" indicarían el tercer curso alternativo para el caso
número 5 del caso de uso.>
1.1 El usuario indica si desea llevar a cabo el filtrado de las imágenes
mediante procesamiento distribuído
7.3.2.4.7 Excepciones
<En este apartado se describe cualquier condición de error anticipada que
podría ocurrir durante la ejecución del caso de uso, y se define cómo el sistema es
capaz de responder a estas condiciones. También, se describe cómo el sistema
responde si la ejecución del caso de uso falla por una cierta razón inesperada. Se
numera cada curso alternativo en la forma "X.Y.E.Z ", donde "X" identifica el caso
del uso, Y indica (0) normal o el curso alternativo (>0) durante los cuales esta
excepción podría ocurrir, "E" indica una excepción, y "Z" es un número de serie
para las excepciones. Por ejemplo "5.0.E.2 "indicaría la segunda excepción para el
curso normal para el caso número 5 del uso.>
2.0.E.1 En el directorio de las imágenes que indica el Usuario no tiene ninguna
imagen. Se le mandará mensaje de que el directorio está vacío y no se dejará
continuar hasta que elija un directorio con imágenes PIC.
2.1.E.1 El procesamiento distribuído no puede llevarse a cabo. El Usuario recibirá un
mensaje indicándole lo ocurrido, y se le permitirá cambiar esta opción antes de
continuar.
4.0.E.1. No se pasará al procesamiento de las imágenes hasta que no esté el
directorio de las imágenes y el nombre de fichero de ubicación de resultados, ambos
verificados y correctos.
7.3.2.4.8 Prioridad
<Indica la prioridad relativa de poner en ejecución este caso de uso. El
esquema de la prioridad usado debe ser igual que el especificado en los requisitos
del software.>
Alta
7.3.2.4.9 Frecuencia de caso de uso
<Aquí se estima el número de veces que este caso de uso será realizado por
los actores por una cierta unidad de tiempo apropiada.>
110
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
A menudo
7.3.2.4.10 Requerimientos especiales
<En esta sección se identifica cualquier requisito adicional, por ejemplo
requisitos no funcionales, para el caso del uso que puede necesitar ser tratado
durante diseño o la puesta en práctica. Éstos pueden incluir requisitos de
funcionamiento u otras cualidades referente a la calidad.>
1. Internacionalización del lenguaje de texto que se muestra.
2. Aplicación sobre cualquier sistema operativo ( multiplataforma ).
3. El tiempo de procesamiento no estará limitado.
7.3.2.4.11 Suposiciones de partida
<Aquí se numera cualquier suposición de partida que fuera hecha en el
análisis que condujo a aceptar este caso del uso en la descripción del producto >
1. Las imágenes serán de 3D en escala de grises, y estarán en formato PIC.
7.3.2.4.12
Cuadro resumen del caso de uso filtrar difusión 3D
Actores: Usuario
Descripción: Procesar las imágenes mediante filtrados de difusión
isotrópica y anisotrópica, generando una imagen filtrada
como resultado
Precondiciones: Las imágenes son 3D en escala de grises y tienen el formato
PIC
Poscondiciones: Generará imágenes filtradas mediante difusión
Curso normal: El usuario carga la imagen en un directorio, inicializa la
aplicación y entrega al Sistema, mediante el GUI, el
directorio donde se encuentran la imagen a analizar y el
nombre del fichero donde desea que se guarden los resultados
del filtrado. El Sistema procesa la imagen. El Usuario espera
a que el sistema procese la imagen.
Curso alternativo: El usuario tiene la opción de llevar a cabo el filtrado de las
GVA-ELAI-UPM®PFC0081-2004
111
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
imágenes mediante procesamiento distribuído
Excepciones: En el directorio de las imágenes que indica el Usuario no
tiene ninguna imagen. El procesamiento distribuído no puede
llevarse a cabo.
Inclusiones:
Prioridad: Alta. Es una de las funcionalidades principales del programa
Frecuencia de uso: Alta
Reglas de negocio:
Requerimientos El tiempo de procesamiento no estará limitado.
especiales:
Suposiciones de partida: Las imágenes serán 3D en niveles de grises, y estarán en
formato JPG
Notas y documentos:
7.4 Creación de la aplicación mediante Rational Rose
Una vez completados todos los documentos necesarios para llevar a cabo la
descripción y planificación de nuestro proyecto, pero antes de implementar el código
propiamente dicho, crearemos un modelo de la aplicación mediante Rational Rose.
La herramienta Rational Rose nos permite plasmar visualmente todas las
especificaciones de nuestra aplicación siguiendo el ciclo de desarrollo del Proceso
Unificado (UP). De esta manera, crearemos todos los diagramas necesarios
especificados dentro del modelado UML, como los diagramas de clases, de
secuencia, de colaboración, etc. También definiremos los elementos que componen
la aplicación (objetos), así como las relaciones entre ellos. Después de esto, Rational
Rose nos permite incluso generar la base del código de nuestra aplicación a partir del
modelo creado. En ese momento ya estaremos listos para pasar al desarrollo de ese
código en el lenguaje de programación más adecuado a nuestras necesidades (en este
caso C++).
7.4.1 Creación del proyecto
De ahora en adelante, se tiene como objetivo mostrar los pasos a seguir,
dentro de la ingeniería del software, para la creación de nuestra aplicación mediante
Rational Rose.
Lo primero que hacemos es ejecutar el Rational Rose y abrir un nuevo
proyecto siguiendo los pasos del proceso unificado:
1. Abrimos Rational Rose 2000, y empleamos el navegador de proyectos.
2. Leer los detalle de cada uno de ellos.
112
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
3. Seleccionamos un proyecto de UP.
4. Salvamos el proyecto como “difusion2D3D.mdl”.
5. Para cualquier duda, utilizamos la tecla F1 .
Figura 7.6 : Seleccionar nuevo proyecto
7.4.2 Creación de casos de uso
Observamos que ha aparecido en el margen izquierdo el esquema típico del
UP (casos de uso, vista lógica, vista de componente y vista de desarrollo).
Desplegamos el diagrama principal de casos de uso y entramos dentro del paquete de
casos de uso del modelo. Rellenamos los casos de uso empleados en nuestra
aplicación siguiendo los siguientes pasos:
6. Empleamos las herramientas que aparecen en el margen izquierdo.
7. Hacemos lo mismo con la notación del caso de uso y de la asociación.
8. Trabajamos con el menú de contexto (botón derecho del ratón).
9. Documentamos, brevemente, las características principales del caso de uso y
el rol del actor.
GVA-ELAI-UPM®PFC0081-2004
113
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
Figura 7.7 : Creación de casos de uso
7.4.3 Creación del diagrama de clases del modelo de análisis
El siguiente paso se dará en la vista lógica. Desplegamos la carpeta de
análisis del modelo. Generamos un diagrama de clases de modelo de análisis:
9. "Vista lógica -> Modelo del Análisis".
10. Menú contexto, crear un diagrama de clases.
Empleando los artefacto de generación del modelo de análisis, rellenamos el
diagrama de clases de objetos del dominio. Hay que tener en cuenta que éstas son
clases conceptuales, no son, de momento, clases software.
11. Insertamos las clases conceptuales del dominio.
12. Creamos clases nuevas como “FiltradoDifusion2D” o “Visualizacion2D”.
13. Emplear los menús de contexto para dotarles de sus atributos y operaciones.
114
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Figura 7.8 : Modelo de análisis
7.4.4 Creación del diagrama de secuencia
El siguiente paso será desplegar la vista de diseño. Sobre esta carpeta creamos
un diagrama de secuencia al que llamaremos "SecuenciaDifusion2D3D". Empleando
las herramientas insertamos objetos y mensajes. Deben ser instancias, con nombre o
sin ella, de las clases conceptuales, anteriormente definida en el diagrama de clases
de la etapa de análisis, y de los actores definidos en el caso de uso.
14. En la carpeta de diseño del modelo insertamos ( new ) un diagrama de
secuencia. Lo nombramos como "SecuenciaDifusion2D3D".
15. En la pizarra incluimos el actor "Usuario" y las clases conceptuales
“FiltradoDifusion2D", "Visualizar2D", etc. Para tal fin, insertamos un objeto
y con el menú de contexto entramos en las especificaciones ( también
podemos hacer doble clic ). Posteriormente seleccionamos el tipo de clase y
el nombre que damos a la instancia.
16. Añadimos los mensajes, que son funciones miembros de la clase que recibe el
mensaje. Los nombres de los mensajes ya se definieron en las clases
conceptuales. Bien empleando el menú de contexto o con doble clic,
aparecerá las propuestas de nombres de mensajes definido en la etapa de
análisis.
GVA-ELAI-UPM®PFC0081-2004
115
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
Figura 7.9 : Diagrama de secuencia
En el procedimiento UP no se es tan lineal como aquí se está presentado el
proceso de AOO/D. Existen realimentaciones entre el modelo de las clases
conceptuales con el diagrama de secuencias.
7.4.5 Creación del diagrama de clases del diseño
El siguiente paso es la construcción del diagrama de clases del diseño. Las
primeras candidatas serán las clases conceptuales que pueden ser propuestas a ser
clases software.
Creamos un diagrama de clases desde la carpeta de diseño del modelo. Con los
iconos existentes en el margen izquierdo de la pizarra, colocamos las clases
anteriormente definidas, convirtiéndolas de conceptuales a software.
17. En la carpeta de diseño del modelo insertar ( new ) un diagrama de
clases.Lo nombramos como "ClasesDifusion2D3D".
18. En la pizarra incluimos las clases conceptuales creadas anteriormente.
19. Establecemos asociaciones entre las clases de entre las distintas que
ofrece UML.
116
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Figura 7.10 : Diagrama de clases
7.4.6 Generación de código mediante Rational Rose
Alcanzado este nivel ya es posible pasar a código. Primero verificamos que el
modelo generado es correcto. En el menú principal desplegamos herramientas y
seleccionamos verificar modelo. Esta acción provoca que el Rational Rose analice la
integridad del modelo y genere un archivo log que reporta los fallos encontrados, si
los hubiera.
Una vez testeado el modelo pasamos a la conversión a código C++ con
plataforma Visual C++. Entramos en el menú principal y seleccionamos "Visual
C++ -> herramienta de selección de componentes". Añadimos un nuevo
componente y seleccionamos un proyecto de Visual C++:
20. Verificamos el modelo: "Tools - > Check Model".
21. Generamos el proyecto de Visual C++: "Tools
Component Assigment Tool".
-> Visual C++ ->
22. Seleccionamos VC++.
23. En la vista de componentes creamos un nuevo componente Visual C++.
GVA-ELAI-UPM®PFC0081-2004
117
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
24. Hacemos doble clic sobre el icono de proyecto. Aparecerá el wizard de
Visual C++.
25. Seleccionamos un proyecto de consola de 32bits y le nombramos como
"Difusion2D3D.dsw".
26. Hemos vinculado el modelo de Rational Rose con el proyecto
"Difusion2D3D.dsw".
Figura 7.11 : Generación del proyecto de Visual C++
118
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Figura 7.12 : Selección del tipo de proyecto
Creado el proyecto añadimos las clases creadas anteriormente. Desde el menú
principal seleccionamos "Visual C++ -> actualizar código" y seleccionamos el
proyecto.
27. Seleccionamos el proyecto definido de Visual C++: "Tools > Visual C++
> Update Code".
28. Seleccionamos la componente del proyecto.
29. Seleccionamos las clases para el proyecto creadas anteriormente.
30. Validamos las clases asignadas al proyecto.
31. Al finalizar, Rational Rose nos da un informe de los errores y avisos en la
conversión.
GVA-ELAI-UPM®PFC0081-2004
119
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
Figura 7.13 : Selección de clases para el proyecto
Figura 7.14 : Validación de clases
120
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Figura 7.15 :Informe de errores y avisos en la conversión
Para
terminar,
añadimos
al
proyecto
el
fichero
fuente
"vistaPrincipalDifusion2D3D.cpp". Ahora podemos pasar a rellenar el código de las
funciones miembros de las clases creadas
7.4.7 Ingeniería inversa
Una vez se ha llevado a cabo la generación de código mediante Rational
Rose, pasaríamos a implementar el código en si mismo. Durante este proceso, las
clases creadas a priori en Rational Rose pueden verse modificadas, alteradas, o
incluso pueden aparecer clases nuevas, según nuestras necesidades. Aquí es donde
entra en escena la ingeniería inversa. Ésta se emplea para actualizar el modelo UML
creado en Rational Rose cuando ha quedado desfasado como consecuencia de la
implementación del código de nuestra aplicación.
Primero se configurará el Rational Rose y luego se realizará la ingeniería
inversa sobre la aplicación ya existente.
GVA-ELAI-UPM®PFC0081-2004
121
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
7.4.7.1 Configuración de Rational Rose: Visual C++ Add-in
Para configurar Rational Rose con vistas a su empleo como herramienta de
ingeniería inversa debemos sguir los siguientes pasos:
1. Abrimos Rational Rose 2000, sin utilizar el navegador de proyectos
(pulsamos el botón "cancelar").
2. Si Visual C++ no está disponible, lo seleccionamos en el menú de "Addin".
Figura 7.16 : Menú Add-in Manager
3. Seleccionamos el menú de "Tools -> Options -> Notation".
4. En el campo "Default Language" seleccionamos VC++.
5. Hacemos click el botón "Apply" para que haga efecto.
122
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Figura 7.17 : Menú Tools -> Options -> Notation
6. Seleccionar el menu de "Tools -> Options -> Diagram"
7. Seleccionar "Label" en el campo "Stereotype Display field".
8. No seleccionar "Focus of control".
GVA-ELAI-UPM®PFC0081-2004
123
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
Figura 7.18 : Menú Tools -> Options -> Diagram
7.4.7.2 Ingeniería inversa con una aplicación
Una vez configurado, podemos llevar a cabo la ingeniería inversa con
Rational Rose. Para ello, inicializamos la aplicación en el Rational Rose y seguiumos
los siguientes pasos:
1. Creamos un nuevo modelo de Rational Rose, sin emplear el wizard de
proyecto.
2. Seleccionamos la herramienta "Tools -> Visual C++ -> Update Model
from Code".
124
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
3. Activamos la opción "Add a VC++ Component".
Figura 7.19 : Creación de un nuevo modelo
4. Seleccionamos la pestaña "Existing".
5. Navegamos hasta encontrar la carpeta del proyecto de Visual C++, donde
se ubica el fichero *.dsw y el código.
6. Seleccionamos el fichero del proyecto (*.dsw)
7. Aceptamos el nombre del proyecto existente.
8. Pulsamos fin.
GVA-ELAI-UPM®PFC0081-2004
125
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
Figura 7.20 : Selección del fichero del proyecto
126
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Figura 7.21 : Finalización del proceso
9. Pulsamos cerrar para acabar la conversión de C++ a UML.
Figura 7.22 : Conversión finalizada
GVA-ELAI-UPM®PFC0081-2004
127
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
Rational Rose añade las clases a un paquete que llama ingeniería inversa
(Reverse Engineered). El diagrama de clases de la vista lógica habrá cambiado.
10. Al pulsar + en la carpeta de la vista lógica aparecerá el árbol del paquete.
11. Continuando con la expansión de la carpeta de ingeniería inversa,
aparecerá la carpeta del proyecto.
12. Se han creado las clases y el diagrama de clases.
Figura 7.23 : Nuevo diagrama de clases
7.5 Implementación del código
En este punto ya estamos listos para llevar a cabo el desarrollo del código de
nuestra aplicación. Este código se implementará en C++ con ayuda de las librerías de
VTK.
128
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
7.5.1 Descripción de las clases empleadas en la aplicación
Mediante el estudio de la visión y alcance, los casos de uso, etc, del proyecto,
y gracias a la herramienta Rational Rose, hemos establecido las clases del programa
“difusión 2D3D”.
El programa ha quedado dividido en cinco clases, como vemos en la figura
7.24 :
Figura 7.24: Clases de difusión2D3D
7.5.1.1 Clase visualización2D
La clase “visualización2D”, como su nombre indica, es la encargada de llevar
a cabo la visualización de imágenes en dos dimensiones a partir de archivos con
formato JPG. Esta clase consta de tres operaciones y un atributo:
Figura 7.25: Clase visualización2D
Las funciones “setNombreFich(const char file2)” y “getNombreFich( )”
sirven para indicar y obtener respectivamente, el nombre del archivo de imagen JPG
que se quiere visualizar ( el atributo “nombreFich”). Cuando se desea llevar a cabo la
visualización se utiliza la función “visualizar2D(const char*)”.
GVA-ELAI-UPM®PFC0081-2004
129
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
El fichero de cabecera de esta clase, cuya base fue creada con Rational Rose,
es el siguiente (“visualizacion2D.h”):
/******************************************************************/
// Copyright (C) 1991 - 1999 Rational Software Corporation
#if defined (_MSC_VER) && (_MSC_VER >= 1000)
#pragma once
#endif
#ifndef _INC_VISUALIZACION2D_408681C30196_INCLUDED
#define _INC_VISUALIZACION2D_408681C30196_INCLUDED
//##ModelId=416F9F9C0203
class visualizacion2D
{
//##ModelId=416F9F9C0204
const char* nombreFich;
public:
//##ModelId=416F9F9C0209
int visualizar2D(const char*);
//##ModelId=416F9F9C0207
void setNombreFich(const char*file2)
{
nombreFich = file2;
}
//##ModelId=416F9F9C0205
const char* getNombreFich(void)
{
return (nombreFich);
}
};
#endif /* _INC_VISUALIZAR2D_408681C30196_INCLUDED */
/*******************************************************************/
El fichero fuente también se incluye a continuación (“visualizacion2D.cpp”):
/******************************************************************/
// Copyright (C) 1991 - 1999 Rational Software Corporation
//#include "stdafx.h"
130
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
#include "visualizacion2D.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkJPEGReader.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkImageMapper.h"
#include "vtkActor2D.h"
#include "vtkImageData.h"
#define ERROR_APERTURA_JPG
-1
//##ModelId=408682020399
visualizacion2D::visualizar2D(const char*nombreFich)
{
//Creamos el renderizador, la ventana de renderización y el interactor con la ventana:
vtkRenderer *aRenderer = vtkRenderer::New();
vtkRenderWindow *renWin = vtkRenderWindow::New();
renWin->AddRenderer(aRenderer);
vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
iren->SetRenderWindow(renWin);
//Creamos el JPEGReader y comprobamos que nombreFich es el nombre de un
//fichero .jpg :
vtkJPEGReader *reader = vtkJPEGReader::New();
if (!reader->CanReadFile(nombreFich))
return (ERROR_APERTURA_JPG);
reader->SetFileName(nombreFich);
reader->Update();
//Hallamos la dimensión en pixels de la imagen:
int dim[2];
reader-> GetOutput()->GetDimensions(dim);
//Creamos el mapper y conectamos su entrada con la salida del reader:
vtkImageMapper *mapper = vtkImageMapper::New();
GVA-ELAI-UPM®PFC0081-2004
131
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
mapper->SetInput(reader->GetOutput());
mapper->SetColorWindow(256);
mapper->SetColorLevel(128);
//Creamos el actor y le asignamos el mapper:
vtkActor2D *actor = vtkActor2D::New();
actor->SetMapper(mapper);
//Asignamos el actor al renderer:
aRenderer->AddActor(actor);
//Establecemos parámetros de la visualización:
aRenderer->SetBackground(1,1,1);
renWin->SetSize(dim[0]+1,dim[1]+1);
//Comenzamos la renderización:
iren->Initialize();
iren->Start();
//Liberamos los objetos creados:
iren->Delete();
mapper->Delete();
actor->Delete();
renWin->Delete();
aRenderer->Delete();
return (0);
}
/*******************************************************************/
7.5.1.2 Clase visualización3D
La clase “visualización3D”, como su nombre indica, es la encargada de llevar
a cabo la visualización de imágenes en tres dimensiones a partir de archivos con
formato PIC. Esta clase consta de siete operaciones y tres atributos:
132
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Figura 7.25: Clase visualización3D
Las funciones “setNombreFich(const char *file2)” y “getNombreFich( )”
sirven para indicar y obtener respectivamente, el nombre del archivo de imagen PIC
que se quiere visualizar ( el atributo “nombreFich”). En este caso también es
necesario indicar el número de rodajas 2D que deseamos que el programa utilice para
crear la imagen 3D. Esto se hace mediante las funciones “setPrimerCorte(int prim)”,
“getPrimerCorte( )”, setUltimoCorte(int ult)” y getUltimoCorte( )”. Finalmente,
cuando se desea llevar a cabo la visualización se utiliza la función
“visualizar3D(const char*, int, int)”.
El fichero de cabecera de esta clase, cuya base fue creada con Rational Rose,
resulta el siguiente (“visualizacion3D.h”):
/*******************************************************************/
// Copyright (C) 1991 - 1999 Rational Software Corporation
#if defined (_MSC_VER) && (_MSC_VER >= 1000)
#pragma once
#endif
#ifndef _INC_VISUALIZACION3D_4086837102DE_INCLUDED
#define _INC_VISUALIZACION3D_4086837102DE_INCLUDED
//##ModelId=416F9F9C01A7
class visualizacion3D
{
//##ModelId=416F9F9C01C5
const char* nombreFich;
int primerCorte, ultimoCorte;
public:
GVA-ELAI-UPM®PFC0081-2004
133
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
//##ModelId=416F9F9C01EB
int visualizar3D(const char*,int,int);
//##ModelId=416F9F9C01E9
void setNombreFich(const char*file2)
{
nombreFich = file2;
}
//##ModelId=416F9F9C01E7
const char* getNombreFich(void)
{
return (nombreFich);
}
//##ModelId=416F9F9C01E5
void setPrimerCorte(int prim)
{
primerCorte = prim;
}
//##ModelId=416F9F9C01D7
void setUltimoCorte(int ult)
{
ultimoCorte = ult;
}
//##ModelId=416F9F9C01D5
int getPrimerCorte(void)
{
return (primerCorte);
}
//##ModelId=416F9F9C01C6
int getUltimoCorte(void)
{
return (ultimoCorte);
}
};
#endif /* _INC_VISUALIZAR3D_4086837102DE_INCLUDED */
/*******************************************************************/
El fichero fuente
(“visualizacion3D.cpp”):
134
de
esta
clase
es
el
incluído
a
continuación
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
/******************************************************************/
// Copyright (C) 1991 - 1999 Rational Software Corporation
//#include "stdafx.h"
#include "visualizacion3D.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkImageReader.h"
#include "vtkContourFilter.h"
#include "vtkSmoothPolyDataFilter.h"
#include "vtkPolyDataNormals.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkOutlineFilter.h"
#include "vtkCamera.h"
#include "vtkProperty.h"
#include "vtkMergePoints.h"
#define BIORAD_HEADER_LENGTH 76
#define BYTE_TO_WORD(lsb,msb) (((unsigned char) lsb) + (((unsigned
char) msb) << 8))
#define ERROR_APERTURA_PIC
-1
#define ERROR_NUMERO_COLUMNAS -2
#define ERROR_NUMERO_FILAS -3
#define ERROR_NUMERO_CORTES -4
//##ModelId=4086838B0242
visualizacion3D::visualizar3D(const char* nombreFich,int primerCorte,int
ultimoCorte)
{
//Creamos el renderer, renderwindow y rederwindowinteractor:
vtkRenderer *aRenderer = vtkRenderer::New();
vtkRenderWindow *renWin = vtkRenderWindow::New();
renWin->AddRenderer(aRenderer);
vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
iren->SetRenderWindow(renWin);
int nx, ny, nz;
unsigned char *head2 = new unsigned char[76];
GVA-ELAI-UPM®PFC0081-2004
135
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
//Apertura del fichero.pic y comprobación de que nombreFich contiene el nombre de
//un fichero .pic
FILE *head1;
head1 = fopen(nombreFich,"rb");
if (head1 == NULL)
return (ERROR_APERTURA_PIC);
//Lectura de la cabecera del fichero PIC BIORAD
fread(head2,sizeof(unsigned char),BIORAD_HEADER_LENGTH,head1);
nx = BYTE_TO_WORD(head2[0], head2[1]);
ny = BYTE_TO_WORD(head2[2], head2[3]);
nz = BYTE_TO_WORD(head2[4], head2[5]);
fclose(head1);
//Verificaciones
if ( nx <= 0 )
return (ERROR_NUMERO_COLUMNAS);
if ( ny <= 0 )
return (ERROR_NUMERO_FILAS);
if ( nz <= 0 )
return (-4);
nx = nx -1;
ny = ny -1;
nz = nz -1;
//Creamos el ImageReader:
vtkImageReader *reader = vtkImageReader::New();
reader->SetFileName(nombreFich);
reader->SetFileDimensionality(3);
reader->SetDataExtent(0, nx, 0, ny, 0, nz);
reader->SetDataVOI(0, nx, 0, ny, primerCorte, ultimoCorte);
reader->SetDataOrigin(0, 0, 0);
reader->SetDataScalarTypeToUnsignedChar();
reader->SetDataSpacing(1.0, 1.0, 0.2);
reader->SetHeaderSize(76);
136
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
//Aplicamos los filtros, mappers y actores necesarios:
vtkContourFilter *skinExtractor = vtkContourFilter::New();
skinExtractor->SetInput((vtkDataSet *) reader->GetOutput());
skinExtractor->SetValue(0, 254);
vtkSmoothPolyDataFilter *smooth = vtkSmoothPolyDataFilter::New();
smooth->SetInput(skinExtractor->GetOutput());
smooth->SetNumberOfIterations(50);
smooth->BoundarySmoothingOn();
smooth->SetFeatureAngle(120);
smooth->SetEdgeAngle(90);
smooth->SetRelaxationFactor(.025);
vtkPolyDataNormals *skinNormals = vtkPolyDataNormals::New();
skinNormals->SetInput(smooth->GetOutput());
skinNormals->SetFeatureAngle(60.0);
vtkPolyDataMapper *skinMapper = vtkPolyDataMapper::New();
skinMapper->SetInput(skinNormals->GetOutput());
skinMapper->ScalarVisibilityOff();
vtkActor *skin = vtkActor::New();
skin->SetMapper(skinMapper);
vtkOutlineFilter *outlineData = vtkOutlineFilter::New();
outlineData->SetInput((vtkDataSet *) reader->GetOutput());
vtkPolyDataMapper *mapOutline = vtkPolyDataMapper::New();
mapOutline->SetInput(outlineData->GetOutput());
vtkActor *outline = vtkActor::New();
outline->SetMapper(mapOutline);
outline->GetProperty()->SetColor(0,0,0);
//Creamos la cámara y establecemos sus parámetros:
vtkCamera *aCamera = vtkCamera::New();
aCamera->SetViewUp (0, 0, -1);
aCamera->SetPosition (0, 1, 0);
aCamera->SetFocalPoint (0, 0, 0);
aCamera->ComputeViewPlaneNormal();
//Establecemos los parámetros del renderer:
aRenderer->AddActor(outline);
aRenderer->AddActor(skin);
GVA-ELAI-UPM®PFC0081-2004
137
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
aRenderer->SetActiveCamera(aCamera);
aRenderer->ResetCamera ();
aCamera->Dolly(1.5);
aRenderer->SetBackground(1,1,1);
renWin->SetSize(512, 512);
aRenderer->ResetCameraClippingRange ();
// Comenzamos la renderización:
iren->Initialize();
iren->Start();
//Liberamos los objetos creados:
smooth->Delete();
skinExtractor->Delete();
skinNormals->Delete();
skinMapper->Delete();
skin->Delete();
outlineData->Delete();
mapOutline->Delete();
outline->Delete();
aCamera->Delete();
iren->Delete();
renWin->Delete();
aRenderer->Delete();
return 0;
}
/******************************************************************/
7.5.1.3 Clase filtradoDifusión2D
La clase “filtradoDifusión2D”, como su nombre indica, es la encargada de
llevar a cabo el filtrado de difusión y la posterior visualización de imágenes en dos
dimensiones a partir de archivos con formato JPG. Esta clase consta de nueve
operaciones y un cuatro atributos:
138
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Figura 7.26: Clase filtradodifusión2D
Esta clase incluye las mismas funciones que la clase “visualización2D” para
obtener el nombre del archivo que contiene la imagen JPG en dos dimensiones.
Además, incluye las funciones necesarias para proporcionar al programa los
parámetros necesarios para llevar a cabo el filtrado de difusión. Estos parámetros son
factor de difusión, número de iteraciones y umbral de difusión. Para llevar a cabo el
filtrado y visualización del resultado se utiliza la función “filtrarDifusion2D(const
char*)”.
El fichero de cabecera de esta clase, cuya base fue creada con Rational Rose,
resulta el siguiente (“filtradoDifusion2D.h”):
/*******************************************************************/
// Copyright (C) 1991 - 1999 Rational Software Corporation
#if defined (_MSC_VER) && (_MSC_VER >= 1000)
#pragma once
#endif
#ifndef _INC_FILTRADODIFUSION2D_408681C30196_INCLUDED
#define _INC_FILTRADODIFUSION2D_408681C30196_INCLUDED
//##ModelId=416F9F9C0290
class filtradoDifusion2D
{
//##ModelId=416F9F9C0292
const char* nombreFich;
int nIteraciones;
float umbralDifusion, factorDifusion;
GVA-ELAI-UPM®PFC0081-2004
139
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
public:
//##ModelId=416F9F9C02A3
int filtrarDifusion2D(const char*);
//##ModelId=416F9F9C02A1
void setNombreFich(const char*file2)
{
nombreFich = file2;
}
//##ModelId=416F9F9C029F
const char* getNombreFich(void)
{
return (nombreFich);
}
//##ModelId=416F9F9C029D
void setIteraciones ( int nIter = 1)
{ nIteraciones = nIter;}
//##ModelId=416F9F9C029B
int getIteraciones ( void)
{ return(nIteraciones);}
//##ModelId=416F9F9C0299
void setFactorDifusion ( float factorDif )
{ factorDifusion = factorDif;}
//##ModelId=416F9F9C0297
float getFactorDifusion ( void)
{ return(factorDifusion);}
//##ModelId=416F9F9C0295
void setUmbralDifusion ( float umbralDif )
{ umbralDifusion = umbralDif;}
//##ModelId=416F9F9C0293
float getUmbralDifusion ( void)
{ return(umbralDifusion);}
};
#endif /* _INC_VISUALIZAR2D_408681C30196_INCLUDED */
/******************************************************************/
140
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
El fichero fuente
(“filtradoDifusion2D.cpp”):
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
de
esta
clase
se
incluye
a
continuación
/******************************************************************/
// Copyright (C) 1991 - 1999 Rational Software Corporation
//#include "stdafx.h"
#include "filtradoDifusion2D.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkJPEGReader.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkImageMapper.h"
#include "vtkActor2D.h"
#include "vtkImageAnisotropicDiffusion2D.h"
#include "vtkImageData.h"
#include "vtkJPEGWriter.h"
#define ERROR_APERTURA_JPG
-1
//##ModelId=408682020399
filtradoDifusion2D::filtrarDifusion2D(const char*nombreFich)
{
//Creamos el renderizador,la ventana de renderización y el interactor con la ventana
vtkRenderer *aRenderer = vtkRenderer::New();
vtkRenderWindow *renWin = vtkRenderWindow::New();
renWin->AddRenderer(aRenderer);
vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
iren->SetRenderWindow(renWin);
//Creamos el JPEGReader:
vtkJPEGReader *reader = vtkJPEGReader::New();
if (!reader->CanReadFile(nombreFich))
return (ERROR_APERTURA_JPG);
reader->SetFileName(nombreFich);
reader->Update();
//Hallamos la dimensión en pixels de la imagen:
GVA-ELAI-UPM®PFC0081-2004
141
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
int dim[2];
reader-> GetOutput()->GetDimensions(dim);
// Creamos el filtro de difusión anisotrópica y conectamos su entrada con la salida del
//reader:
vtkImageAnisotropicDiffusion2D *difusor =
vtkImageAnisotropicDiffusion2D::New();
difusor->SetInput(reader->GetOutput());
difusor->CornersOn();
difusor->EdgesOn();
difusor->FacesOn();
difusor->GradientMagnitudeThresholdOn();
difusor->SetNumberOfIterations(nIteraciones);
difusor->SetDiffusionThreshold(umbralDifusion);
difusor->SetDiffusionFactor(factorDifusion);
difusor->Update();
// Guardamos la imagen filtrada:
vtkJPEGWriter *imgDifusion=vtkJPEGWriter::New();
imgDifusion->SetInput(difusor->GetOutput());
imgDifusion>SetFileName("D:\\iberzal\\Difusion2D3D\\Codigo\\visualizacion2D3D_0.2\\R
esultados\\filtrado2D.jpg");
imgDifusion->Write();
//Creamos el mapper y conectamos su entrada con la salida del filtro:
vtkImageMapper *mapper = vtkImageMapper::New();
mapper->SetInput(difusor->GetOutput());
mapper->SetColorWindow(256);
mapper->SetColorLevel(128);
//Creamos el actor y le asignamos el mapper
vtkActor2D *actor = vtkActor2D::New();
actor->SetMapper(mapper);
//Asignamos el actor al renderer
142
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
aRenderer->AddActor(actor);
//Establecemos parámetros de la visualización
aRenderer->SetBackground(1,1,1);
renWin->SetSize(dim[0]+1,dim[1]+1);
iren->Initialize();
iren->Start();
//Liberamos los objetos creados:
iren->Delete();
mapper->Delete();
actor->Delete();
renWin->Delete();
aRenderer->Delete();
difusor->Delete();
return (0);
}
/*******************************************************************/
7.5.1.4 Clase filtradoDifusión3D
La clase “filtradoDifusión3D”, como su nombre indica, es la encargada de
llevar a cabo el filtrado de difusión y la posterior visualización de imágenes en tres
dimensiones a partir de archivos con formato PIC. Esta clase consta de trece
operaciones y un seis atributos:
GVA-ELAI-UPM®PFC0081-2004
143
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
Figura 7.27: Clase filtradoDifusión3D
Esta clase incluye las mismas funciones que la clase “visualización3D” para
obtener el nombre del archivo que contiene la imagen PIC, así como para establecer
el numero de rodajas que tomará el programa para crear la imagen 3D. Además,
incluye las funciones necesarias para proporcionar al programa los parámetros
necesarios para llevar a cabo el filtrado de difusión. Estos parámetros son factor de
difusión, número de iteraciones y umbral de difusión. Para llevar a cabo el filtrado y
visualización del resultado se utiliza la función “filtrarDifusion3D(const char*, int,
int)”.
El fichero de cabecera de esta clase, cuya base fue creada con Rational Rose,
resulta el siguiente (“filtradoDifusion3D.h”):
/*******************************************************************/
// Copyright (C) 1991 - 1999 Rational Software Corporation
#if defined (_MSC_VER) && (_MSC_VER >= 1000)
#pragma once
#endif
#ifndef _INC_FILTRADODIFUSION3D_4086837102DE_INCLUDED
#define _INC_FILTRADODIFUSION3D_4086837102DE_INCLUDED
//##ModelId=416F9F9C0242
class filtradoDifusion3D
{
144
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
//##ModelId=416F9F9C0251
const char* nombreFich;
int primerCorte, ultimoCorte;
//##ModelId=416F9F9C0243
int nIteraciones;
float umbralDifusion, factorDifusion;
public:
//##ModelId=416F9F9C026A
int filtrarDifusion3D(const char*,int,int);
//##ModelId=416F9F9C0268
void setNombreFich(const char*file2)
{
nombreFich = file2;
}
//##ModelId=416F9F9C0266
const char* getNombreFich(void)
{
return (nombreFich);
}
//##ModelId=416F9F9C0264
void setPrimerCorte(int prim)
{
primerCorte = prim;
}
//##ModelId=416F9F9C0262
void setUltimoCorte(int ult)
{
ultimoCorte = ult;
}
//##ModelId=416F9F9C0260
int getPrimerCorte(void)
{
return (primerCorte);
}
//##ModelId=416F9F9C025E
int getUltimoCorte(void)
{
return (ultimoCorte);
}
GVA-ELAI-UPM®PFC0081-2004
145
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
//##ModelId=416F9F9C025C
void setIteraciones ( int nIter = 1)
{ nIteraciones = nIter;}
//##ModelId=416F9F9C025A
int getIteraciones ( void)
{ return(nIteraciones);}
//##ModelId=416F9F9C0258
void setFactorDifusion ( float factorDif )
{ factorDifusion = factorDif;}
//##ModelId=416F9F9C0256
float getFactorDifusion ( void)
{ return(factorDifusion);}
//##ModelId=416F9F9C0254
void setUmbralDifusion ( float umbralDif )
{ umbralDifusion = umbralDif;}
//##ModelId=416F9F9C0252
float getUmbralDifusion ( void)
{ return(umbralDifusion);}
};
#endif /* _INC_FILTRARDIFUSION3D_4086837102DE_INCLUDED */
/*******************************************************************/
El fichero fuente
(“filtradoDifusion3D.cpp”):
de
esta
clase
se
incluye
a
continuación
/*******************************************************************/
// Copyright (C) 1991 - 1999 Rational Software Corporation
//#include "stdafx.h"
#include "filtradoDifusion3D.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkImageReader.h"
#include "vtkContourFilter.h"
#include "vtkSmoothPolyDataFilter.h"
146
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
#include "vtkPolyDataNormals.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkOutlineFilter.h"
#include "vtkCamera.h"
#include "vtkProperty.h"
#include "vtkMergePoints.h"
#include "vtkImageAnisotropicDiffusion3D.h"
#define BIORAD_HEADER_LENGTH 76
#define BYTE_TO_WORD(lsb,msb) (((unsigned char) lsb) + (((unsigned
char) msb) << 8))
#define ERROR_APERTURA_PIC
-1
#define ERROR_NUMERO_COLUMNAS -2
#define ERROR_NUMERO_FILAS -3
#define ERROR_NUMERO_CORTES -4
//##ModelId=4086838B0242
filtradoDifusion3D::filtrarDifusion3D(const char*nombreFich,int
primerCorte,int ultimoCorte)
{
//Creamos el renderer, renderwindow y rederwindowinteracior
vtkRenderer *aRenderer = vtkRenderer::New();
vtkRenderWindow *renWin = vtkRenderWindow::New();
renWin->AddRenderer(aRenderer);
vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
iren->SetRenderWindow(renWin);
int nx, ny, nz;
unsigned char *head2 = new unsigned char[76];
//Apertura del fichero.pic y comprobación de que nombreFich contiene el nombre de
//un fichero .pic
FILE *head1;
head1 = fopen(nombreFich,"rb");
if (head1 == NULL)
return (ERROR_APERTURA_PIC);
//Lectura de la cabecera del fichero PIC BIORAD
fread(head2,sizeof(unsigned char),BIORAD_HEADER_LENGTH,head1);
GVA-ELAI-UPM®PFC0081-2004
147
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
nx = BYTE_TO_WORD(head2[0], head2[1]);
ny = BYTE_TO_WORD(head2[2], head2[3]);
nz = BYTE_TO_WORD(head2[4], head2[5]);
fclose(head1);
//Verificaciones
if ( nx <= 0 )
return (ERROR_NUMERO_COLUMNAS);
if ( ny <= 0 )
return (ERROR_NUMERO_FILAS);
if ( nz <= 0 )
return (ERROR_NUMERO_CORTES);
nx = nx -1;
ny = ny -1;
nz = nz -1;
//Creamos el ImageReader:
vtkImageReader *reader = vtkImageReader::New();
reader->SetFileName(nombreFich);
reader->SetFileDimensionality(3);
reader->SetDataExtent(0, nx, 0, ny, 0, nz);
reader->SetDataVOI(0, nx, 0, ny, primerCorte, ultimoCorte);
reader->SetDataOrigin(0, 0, 0);
reader->SetDataScalarTypeToUnsignedChar();
reader->SetDataSpacing(1.0, 1.0, 0.2);
reader->SetHeaderSize(76);
//Creamos el filtro de difusión anisotrópica y conectamos su entrada con la salida del
//reader:
vtkImageAnisotropicDiffusion3D *difusor =
vtkImageAnisotropicDiffusion3D::New();
difusor->SetInput(reader->GetOutput());
difusor->CornersOn();
difusor->EdgesOn();
difusor->FacesOn();
difusor->GradientMagnitudeThresholdOn();
difusor->SetNumberOfIterations(nIteraciones);
difusor->SetDiffusionThreshold(umbralDifusion);
148
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
difusor->SetDiffusionFactor(factorDifusion);
difusor->Update();
//Aplicamos los filtros, mappers y actores necesarios:
vtkContourFilter *skinExtractor = vtkContourFilter::New();
skinExtractor->SetInput((vtkDataSet *) difusor->GetOutput());
skinExtractor->SetValue(0, 254);
vtkSmoothPolyDataFilter *smooth = vtkSmoothPolyDataFilter::New();
smooth->SetInput(skinExtractor->GetOutput());
smooth->SetNumberOfIterations(50);
smooth->BoundarySmoothingOn();
smooth->SetFeatureAngle(120);
smooth->SetEdgeAngle(90);
smooth->SetRelaxationFactor(.025);
vtkPolyDataNormals *skinNormals = vtkPolyDataNormals::New();
skinNormals->SetInput(smooth->GetOutput());
skinNormals->SetFeatureAngle(60.0);
vtkPolyDataMapper *skinMapper = vtkPolyDataMapper::New();
skinMapper->SetInput(skinNormals->GetOutput());
skinMapper->ScalarVisibilityOff();
vtkActor *skin = vtkActor::New();
skin->SetMapper(skinMapper);
vtkOutlineFilter *outlineData = vtkOutlineFilter::New();
outlineData->SetInput((vtkDataSet *) reader->GetOutput());
vtkPolyDataMapper *mapOutline = vtkPolyDataMapper::New();
mapOutline->SetInput(outlineData->GetOutput());
vtkActor *outline = vtkActor::New();
outline->SetMapper(mapOutline);
outline->GetProperty()->SetColor(0,0,0);
//Creamos la cámara, estableciendo sus parámetros:
vtkCamera *aCamera = vtkCamera::New();
aCamera->SetViewUp (0, 0, -1);
aCamera->SetPosition (0, 1, 0);
aCamera->SetFocalPoint (0, 0, 0);
aCamera->ComputeViewPlaneNormal();
GVA-ELAI-UPM®PFC0081-2004
149
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
//Añadimos los actores al renderer y establecemos sus parámetros:
aRenderer->AddActor(outline);
aRenderer->AddActor(skin);
aRenderer->SetActiveCamera(aCamera);
aRenderer->ResetCamera ();
aCamera->Dolly(1.5);
aRenderer->SetBackground(1,1,1);
renWin->SetSize(512, 512);
aRenderer->ResetCameraClippingRange ();
//Iniciamos la renderización
iren->Initialize();
iren->Start();
//Libreamos todos los objetos creados
difusor->Delete();
smooth->Delete();
skinExtractor->Delete();
skinNormals->Delete();
skinMapper->Delete();
skin->Delete();
outlineData->Delete();
mapOutline->Delete();
outline->Delete();
aCamera->Delete();
iren->Delete();
renWin->Delete();
aRenderer->Delete();
return 0;
}
/******************************************************************/
7.5.1.5 Clase vistaFiltradoDifusión2D3D
La clase “vistaFiltradoDifusión2D3D” es la clase encargada de gestionar el
programa. A través de ella se accede a las clases restantes, y se establecen sus
parámetros. Es la encargada de interactuar con el usuario, mediante un menú de
150
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
opciones, que permite seleccionar la opción deseada de entre las que presenta el
programa.
Figura 7.28: Clase vistaFiltradoDifusión2D3D
A continuación se presenta el fichero de cabecera de esta clase
(vistaFiltradoDifusión2D3D.h):
/******************************************************************/
// Copyright (C) 1991 - 1999 Rational Software Corporation
#if defined (_MSC_VER) && (_MSC_VER >= 1000)
#pragma once
#endif
#ifndef
_INC_VISTAFILTRADODIFUSION2D3D_40868690034B_INCLUDED
#define
_INC_VISTAFILTRADODIFUSION2D3D_40868690034B_INCLUDED
class visualizacion2D;
class visualizacion3D;
//##ModelId=416F9F9C02AF
class vistaFiltradoDifusion2D3D
{
public:
//##ModelId=416F9F9C02B0
vistaFiltrarDifusion2D3D();
};
#endif /* _INC_VISUALIZAR2D3D_40868690034B_INCLUDED */
/******************************************************************/
El fichero fuente de esta clase (vistaFiltradoDifusión2D3D.cpp), incluye el
menú de opciones, y el código necesario para que el usuario establezca los
parámetros a definir, según la opción elegida, para el correcto funcionamiento del
programa.
GVA-ELAI-UPM®PFC0081-2004
151
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
/******************************************************************/
// Copyright (C) 1991 - 1999 Rational Software Corporation
//#include "stdafx.h"
#include <iostream>
#include "filtradoDifusion2D.h"
#include "filtradoDifusion3D.h"
#include "visualizacion2D.h"
#include "visualizacion3D.h"
#include "vistaFiltradoDifusion2D3D.h"
//##ModelId=408686CD03D8
vistaFiltradoDifusion2D3D::vistaFiltrarDifusion2D3D()
{
char opcion='0';
char file2[300];
int prim,ult,error=0;
int nIter;
float umbralDif, factorDif;
//Menú de opciones
while (opcion!='5')
{
std::cout<<"Opciones disponibles:"<<std::endl << std::endl;
std::cout<<" 1- Visualizacion 2D\n 2- Filtrado de difusion 2D"
<<std::endl;
std::cout<<" 3- Visualizacion 3D\n 4- Filtrado de difusion 3D\n 5- Salir"
<< std::endl<<std::endl;
std::cout<<"Elige la opcion deseada: ";
std::cin>> opcion;
std::cout<<" "<<std::endl;
switch (opcion){
case '1':{
std::cout<<"Introduce
.jpg:"<<std::endl;
std::cin>>file2;
el
nombre
visualizacion2D imagen2D;
imagen2D.setNombreFich(file2);
error
imagen2D.visualizar2D(imagen2D.getNombreFich());
if (error==-1)
152
del
fichero
=
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
std::cout<<"El archivo indicado no tiene formato
.jpg "<<std::endl;
};
break;
case '2':{
std::cout<<"Introduce el nombre del fichero
.jpg:"<<std::endl;
std::cin>>file2;
std::cout << "Indica los parametros de
filtrado:"<<std::endl<<std::endl;
std::cout << "Factor de difusion: ";
std::cin >> factorDif;
std::cout << "Umbral de difusion: ";
std::cin >> umbralDif;
std::cout << "Numero de iteraciones: ";
std::cin >> nIter;
filtradoDifusion2D filtro2D;
filtro2D.setNombreFich(file2);
filtro2D.setFactorDifusion(factorDif);
filtro2D.setUmbralDifusion(umbralDif);
filtro2D.setIteraciones(nIter);
error =
filtro2D.filtrarDifusion2D(filtro2D.getNombreFich());
if (error==-1)
std::cout<<"El archivo indicado no tiene formato
.jpg "<<std::endl;
};
break;
case '3':{
std::cout<<"\nIntroduce el nombre del fichero .pic:
"<<std::endl;
std::cin>>file2;
std::cout<<"Introduce el numero del primer corte: ";
std::cin>>prim;
std::cout<<"Introduce el numero del ultimo corte: ";
std::cin>>ult;
visualizacion3D imagen3D;
imagen3D.setNombreFich(file2);
imagen3D.setPrimerCorte(prim);
imagen3D.setUltimoCorte(ult);
error=imagen3D.visualizar3D(imagen3D.getNombreFich(),imagen3D.
getPrimerCorte(),imagen3D.getUltimoCorte());
GVA-ELAI-UPM®PFC0081-2004
153
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
switch (error){
case -1: std::cout<<"El archivo indicado no tiene formato
.pic"<<std::endl;
break;
case -2: std::cout<<"Numero de columnas
incorreto"<<std:: endl;
break;
case -3: std::cout<<"Numero de filas incorreto"<<
std::endl;
break;
case -4: std::cout<<"Numero de cortes incorrecto"<<std::
endl;
break;
}
};
break;
case '4':{
std::cout<<"\nIntroduce el nombre del fichero .pic:
"<<std::endl;
std::cin>>file2;
std::cout<<"Introduce el numero del primer corte: ";
std::cin>>prim;
std::cout<<"Introduce el numero del ultimo corte: ";
std::cin>>ult;
std::cout << "Indica los parametros de
filtrado:"<<std::endl<<std::endl;
std::cout << "Factor de difusion: ";
std::cin >> factorDif;
std::cout << "Umbral de difusion: ";
std::cin >> umbralDif;
std::cout << "Numero de iteraciones: ";
std::cin >> nIter;
filtradoDifusion3D filtro3D;
filtro3D.setNombreFich(file2);
filtro3D.setPrimerCorte(prim);
filtro3D.setUltimoCorte(ult);
filtro3D.setFactorDifusion(factorDif);
filtro3D.setUmbralDifusion(umbralDif);
filtro3D.setIteraciones(nIter);
error =
filtro3D.filtrarDifusion3D(filtro3D.getNombreFich(),filtro3D.getPrimerCorte(),fil
tro3D.getUltimoCorte());
154
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
switch (error){
case -1: std::cout<<"El archivo indicado no tiene formato
.pic"<<std::endl;
break;
case -2: std::cout<<"Numero de columnas
incorreto"<<std:: endl;
break;
case -3: std::cout<<"Numero de filas incorreto"<<
std::endl;
break;
case -4: std::cout<<"Numero de cortes incorrecto"<<std::
endl;
break;
}
};
break;
case '5': break;
default:
std::cout << "Opcion no valida." << std::endl <<std::endl;
}
}
}
/******************************************************************/
7.5.2 Fichero principal de la aplicación
El fichero principal de la aplicación es el que contiene a la función “main( )”.
Esta función se emplea para iniciar el programa, y simplemente se encarga de crear
un objeto de la clase “vistaFiltradoDifusión2D3D”, que gestionará la aplicación.
El archivo fuente del fichero principal (“principalVisualización2D3D.cpp”),
se muestra a continuación:
/******************************************************************/
#include <iostream>
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkJPEGReader.h"
#include "vtkImageAnisotropicDiffusion2D.h"
GVA-ELAI-UPM®PFC0081-2004
155
Aplicaciones del filtrado de difusión con imágenes .jpg y .pic
Ignacio Berzal Moreno
#include "vtkRenderWindowInteractor.h"
#include "vtkImageMapper.h"
#include "vtkActor2D.h"
#include "vtkImageViewer.h"
#include "vistaFiltradoDifusion2D3D.h"
void main()
{
vistaFiltradoDifusion2D3D vista1;
vista1.vistaFiltrarDifusion2D3D();
}
/******************************************************************/
7.5.3 Archivo CMakeLists
Como ya hemos visto en capítulos anteriores, para poder compilar una
aplicación que emplee las librerías de VTK es necesario utilizar la herramienta
CMake. Se incluye a continuación el archivo de texto “CMakeLists” necesario para
posibilitar la compilación de la aplicación “difusión2D3D”:
/*******************************************************************/
PROJECT (visualizacion2D3D_0.2)
INCLUDE (${CMAKE_ROOT}/Modules/FindVTK.cmake)
IF (USE_VTK_FILE)
INCLUDE(${USE_VTK_FILE})
ENDIF (USE_VTK_FILE)
ADD_EXECUTABLE(principalVisualizacion2D3D
principalVisualizacion2D3D.cpp)
TARGET_LINK_LIBRARIES(principalVisualizacion2D3D vtkRendering vtkIO)
/*******************************************************************/
156
GVA-ELAI-UPM®PFC0081-2004
8
Conclusiones
8.1 Principales aportaciones
En este proyecto se ha tratado de desarrollar un estudio sobre distintos
algoritmos de procesamiento y visualización de imágenes. Como herramienta para
este fin, se han empleado las librerías de VTK, llevando a cabo un análisis bastante
completo de las mismas, desde su instalación hasta su funcionamiento en C++,
incluyendo ejemplos significativos.
Estudiar, analizar y describir imágenes médicas a partir del procesamiento
digital, constituye en la actualidad, una herramienta de trabajo, cuya precisión facilita
al especialista la obtención de inferencias de valor diagnóstico y pronóstico de
enfermedades, con el lógico beneficio para el paciente. En la actualidad, las
aplicaciones de tratamiento y análisis de imágenes aparecen frecuentemente
integradas con aplicaciones de visualización tridimensional. Además de detectar y
localizar zonas de interés, los usuarios de las aplicaciones informáticas de imágenes
médicas (radiólogos, cirujanos, etc.) desean en general mostrar dichas zonas
visualizándolas tridimensionalmente, aprovechando de este modo la naturaleza
tridimensional de la mayoría de las imágenes utilizadas. Así, los médicos demandan
de forma creciente aplicaciones que integren técnicas de tratamiento y análisis con
funcionalidades de visualización tridimensional. De todo esto podemos derivar la
GVA-ELAI-UPM®PFC0081-2004
157
Conclusiones
Ignacio Berzal Moreno
importancia del estudio realizado en este proyecto sobre la visualización de imágenes
3D a partir de una pila de imágenes 2D obtenidas con microscopía confocal.
La creación de aplicaciones basadas en el modelado UML es una herramienta
muy importante en la ingeniería del software. Al ser un modelo basado en
componentes, conduce a la reutilización del software, brindando importantes
beneficios al grupo desarrollador. Por ello, la aplicación “difusión 2D3D“ puede
tener cierta importancia como ejemplo orientativo de utilización de este modelo.
8.2 Futuras mejoras
Son muchas las mejoras que se pueden hacer a todo lo desarrollado a lo largo
de este proyecto, algunas de ellas son:
158
•
Profundizar en el estudio de las herramientas de visualización de imágenes
distintas de las VTK, para poder llevar a cabo una comparativa con las
mismas, y así determinar cuál es la más apropiada en cada momento, según
nuestros objetivos.
•
Aunque el análisis de las librerías VTK es bastante completo, el estudio de su
funcionamiento sólo se ha tratado bajo el lenguaje C++. Podría llevarse a
cabo un análisis y comparativa de su funcionamiento con otros de los
lenguajes de programación que soporta, como Java, Tcl/Tk, o Python.
•
Realizar un estudio de técnicas de reconstrucción 3D distintas de las
expuestas, como Marching Cubes, para poder decidir emplear la más
apropiada en cada caso.
•
Ahondar en el estudio de las distintas técnicas de filtrado de difusión,
isotrópica y anisotrápica, y en la combinación de las mismas.
•
La aplicación “difusión2D3D” es susceptible de muchas mejoras, entre otras,
la culminación de algunos de los objetivos que aparecían en su documento de
“visión y alcance”, y que no han sido llevados a cabo en este proyecto. Entre
ellos, cabe destacar la creación de un GUI (Grafical User Interface), mediante
las librerías MFC, que permita al usuario decidir entre las distintas opciones
de uso del programa, así como introducir los parámetros necesarios para su
funcionamiento de manera más sencilla. La opción de procesamiento
distribuído para mejorar el tiempo de ejecución al llevar a cabo el filtrado de
difusión tampoco ha sido incluída en esta aplicación, aunque su
implementación ha sido desarrollada con éxito en otros proyectos.
•
Aunque no aparezca en su documento de “visión y alcance”, la aplicación
“difusión2D3D” podría completarse con la inclusión de nuevos tipos de
algoritmos de filtrado, distintos de la difusión, que permitan emplear el más
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Conclusiones
adecuado en cada caso. También se podría tratar de llevar a cabo la
visualización y tratamiento de imágenes PIC en color, y no sólo en escala de
grises.
•
Empleando VTK, y siguiendo el método de modelado UML, podrían crearse
multitud de aplicaciones del estilo de la implementada en este proyecto, que
permitan explotar las capacidades de VTK en lo que respecta al desarrollo de
algoritmos de procesamiento de imágenes.
Estas son sólo algunas de las posibles mejoras a este proyecto, aunque podrían
incluirse muchas más, ya que es lógico que cualquier aplicación software, sea
susceptible de nuevas mejoras que mejoren el funcionamiento global de la
aplicación, o de nuevas aplicaciones que den más versatilidad a los programas
diseñados.
GVA-ELAI-UPM®PFC0081-2004
159
Conclusiones
160
Ignacio Berzal Moreno
GVA-ELAI-UPM®PFC0081-2004
9
Bibliografía
PROCESAMIENTO DE IMÁGENES
Thomas Bauer,”Processing and 3D visualization of biological volumes of confocal
microscopy”, Grupo de Visión Artificial (GVA), Escuela Universitaria de Ingeniería
Técnica Industrial de Madrid, www.elai.upm.es
Marta García Nuevo, “Procesamiento y Visualización Tridimensional de Imágenes
Biomédicas del Microscopio Confocal”, Grupo de Visión Artificial (GVA), Escuela
Universitaria de Ingeniería Técnica Industrial de Madrid, www.elai.upm.es
Mihai Spulber, “Implementation of biomedical tools”, Grupo de Visión Artificial
(GVA), Escuela Universitaria de Ingeniería Técnica Industrial de Madrid,
www.elai.upm.es
David López Peinado, “Implementación multiplataforma de algoritmos de
procesamiento de imágenes biomédicas 2D en Matlab y C++”, Grupo de Visión
Artificial (GVA), Escuela Universitaria de Ingeniería Técnica Industrial de Madrid,
www.elai.upm.es
GVA-ELAI-UPM®PFC0081-2004
161
Bibliografía
Ignacio Berzal Moreno
Carlos Platero, Gabriel Asensio, Jorge Moreno, “Combinación de la difusión
isotrópica y anisotropica en el procesamiento de imágenes”, Escuela Universitaria
de Ingeniería Técnica Industrial de Madrid.
http://www.exaflop.org/docs/marchcubes/ind.html Marching Cubes
http://www.ldc.usb.ve/~vtheok/cursos/ci5322/marching/marching.html Marching
Cubes
http://www.kitware.com
VTK
Kitware, Inc., “The Visualization Toolkit User's Guide”,publicado por Kitware, Inc.
Guía del usuario para la versión 4.2 de VTK
Kitware, Inc., “The Visualization Toolkit, An Object-Oriented Approach To 3D
Graphics, 3rd edition”, publicado por Kitware, Inc. Algoritmos de visualización y
estructuras de datos.
http://www.vtk.org
http://public.kitware.com/mailman/listinfo/vtkusers Mailing-List
http://public.kitware.com/cgi-bin/vtkfaq FAQ de VTK
http://www.cmake.org/ Página oficial de CMake
OTRAS HERRAMIENTAS DE VISUALIZACIÓN
http://www.itk.org/ Página oficial de ITK
http://www.paraview.org/HTML/Index.html Página oficial de Paraview
http://www.mathworks.com/products/matlab/ Página oficial de Matlab
162
GVA-ELAI-UPM®PFC0081-2004
Ignacio Berzal Moreno
Bibliografía
MODELADO UML Y RATIONAL ROSE
Mihai Spulber, “Implementation of biomedical tools”, Grupo de Visión Artificial
(GVA), Escuela Universitaria de Ingeniería Técnica Industrial de Madrid,
www.elai.upm.es
Carlos Platero Dueñas, “Prácticas de Informática Industrial”, Escuela Universitaria
de Ingeniería Técnica Industrial de Madrid.
http://www.uml.org/
http://www-306.ibm.com/software/rational/
http://www.vico.org/TallerRationalRose.pdf
http://doc.mor.itesm.mx:8181/labvir/archivos/estandares/Modelos_proceso.pdf
http://dark.disca.upv.es/enheror/pdf/ActaUML.pdf
C++
http://www.e-manuales.com/dir.asp?cat=/programacion/cc Manuales de C++.
http://msdn.microsoft.com/library/
http://www.lafacu.com/apuntes/informatica/Programacion_en_C++/
GVA-ELAI-UPM®PFC0081-2004
163
Bibliografía
164
Ignacio Berzal Moreno
GVA-ELAI-UPM®PFC0081-2004

Documentos relacionados