Manual Program Ad Or Final

Embed Size (px)

Citation preview

Tabla de Contenidos1 2 Introduccin........................................................................................................... 4 Algoritmo mastitis ................................................................................................. 5 2.1 Documentacin de clases................................................................................. 5 2.1.1 Referencia de la clase CV ................................................................ 5 2.1.1.1 cvThreshold................................................................................... 5 2.1.1.2 cvFindContours ............................................................................ 7 2.1.1.3 cvContourArea.............................................................................. 8 2.1.1.4 cvBox2D........................................................................................ 9 2.1.1.5 cvFitEllipse ................................................................................... 9 2.1.2 Referencia a la clase HighGUI ........................................................ 11 2.1.2.1 cvNamedWindow ......................................................................... 11 2.1.2.2 cvDestroyWindow ......................................................................... 11 2.1.2.3 cvShowImage ................................................................................ 12 2.1.2.4 cvWaitKey ..................................................................................... 12 2.1.2.5 cvLoadImage................................................................................. 12 2.1.2.6 cvSaveImage ................................................................................. 13 2.1.3 Referencia a la clase CxCore ........................................................... 14 2.1.3.1 IplImage........................................................................................ 14 2.1.3.2 CvPoint ......................................................................................... 16 2.1.3.3 CvPoint2D32f ............................................................................... 17 2.1.3.4 CvSize ........................................................................................... 17 2.1.3.5 cvCreateImage .............................................................................. 18 2.1.3.6 cvCloneImage ............................................................................... 18 2.1.3.7 CvMemStorage.............................................................................. 19 2.1.3.8 cvCreateMemStorage.................................................................... 20 2.1.3.9 CvSeq ............................................................................................ 20 2.1.3.10 cvCvtSeqToArray ........................................................................ 22 2.1.3.11 CV_RGB ..................................................................................... 22 2.1.3.12 cvDrawContours......................................................................... 23 2.1.3.13 cvZero ......................................................................................... 23 2.1.3.14 CvScalar ..................................................................................... 24 2.1.3.15 CvSize ......................................................................................... 24 2.1.3.16 CvArr .......................................................................................... 25 2.1.3.17 cvCmp ......................................................................................... 25 2.1.3.18 cvGetSize..................................................................................... 26 2.1.3.19 cvRound ...................................................................................... 26 2.1.3.20 cvEllipse...................................................................................... 27 2.2 Algoritmo......................................................................................................... 28 2.2.1 Explicacin del cdigo..................................................................... 29 2.2.1.1 Includes......................................................................................... 29 2.2.1.2 Declaracin e inicializacin de variables .................................... 29 2.2.1.3 Mostrar Imagen ............................................................................ 32 2.2.1.4 Inicio del main .............................................................................. 33 2.2.1.5 Obtencin de los contornos exteriores ......................................... 37 2.2.1.6 Clculo del rea de los contornos ................................................ 38 2.2.1.7 Eliminacin de los contornos exteriores....................................... 42 2.2.1.8 Clculo del nmero de clulas...................................................... 44 2.2.1.9 Tratamiento imagen final.............................................................. 53 Haartraining ........................................................................................................... 56 3.1 Proceso............................................................................................................. 56 3.2 Imgenes de entrenamiento ............................................................................. 56 3.2.1 Createsamples .................................................................................. 57 3.2.2 Muestras positivas............................................................................ 59

3

Manual del programador

1

3.2.2.1 Imgenes simples .......................................................................... 59 3.2.2.2 imgenes clulas ........................................................................... 62 3.2.3 Muestras negativas........................................................................... 64 3.2.3.1 Imgenes simples .......................................................................... 64 3.2.3.2 Imgenes clulas........................................................................... 67 3.3 Comando Haartraining..................................................................................... 70 3.4 Performance..................................................................................................... 80 3.5 Creacin de ejemplos (Application) ................................................................ 87 3.6 Ubicacin de los archivos................................................................................ 90

Manual del programador

2

Lista de FigurasFigura 1: cvThreshold ........................................................................................................................................6 Figura 2: Ejmplo de estructura IplImage..........................................................................................................16 Figura 3: Imagen pasada como parmetro........................................................................................................28 Figura 4: Primera imagen mostrada .................................................................................................................34 Figura 5: Imagen inicial binarizada..................................................................................................................36 Figura 6: Bordes exteriores ..............................................................................................................................40 Figura 7: Imagen en blanco y negro sin bordes exteriores...............................................................................42 Figura 8: Clculo de elipses (2)........................................................................................................................49 Figura 9: Clulas eliminadas ............................................................................................................................51 Figura 10: Imagen final ....................................................................................................................................54 Figura 11: Parmetros fichero de ndices .........................................................................................................57 Figura 12: Fondo y primer plano de la imagen simple.....................................................................................59 Figura 13: Muestras positivas aleatorias ..........................................................................................................60 Figura 14: Fondo blanco y puntos negros ........................................................................................................64 Figura 15: Imagen con puntos negros ..............................................................................................................65 Figura 16: Imgenes de fondo ..........................................................................................................................67 Figura 17: Imgenes de fondo (2) ....................................................................................................................69 Figura 18: Directorio eyes_classifier_take_1 con diez etapas .........................................................78 Figura 19: Contenido del fichero AdaBoostCARTHaarClassifier.txt..............................................................79 Figura 20: Objeto encontrado (Hit)................................................................................................................81 Figura 21: falso positivo (False) ...................................................................................................................81 Figura 22: Falso negativo (Missed) ...............................................................................................................82 Figura 23: Imagen de partida para el Createsamples........................................................................................87 Figura 24: Imgenes creadas con Createsamples .............................................................................................88 Figura 25: rbol de directorios (1)...................................................................................................................90 Figura 26: rbol de directorios (2)...................................................................................................................90 Figura 27: rbol de directorios (3)...................................................................................................................91 Figura 28: rbol de directorios (4)...................................................................................................................91 Figura 29: rbol de directorios (5)...................................................................................................................92

Manual del programador

3

Manual del programador 1 Introduccin

En este apartado se pretende ofrecer a futuros usuarios tanto del algoritmo de deteccin de la mastitis como de la herramienta Haartraining una informacin detallada de cada una de las clases y elementos que los componen. En primer lugar, analizaremos todo lo referente al algoritmo de la mastitis centrndonos en cada una de sus clases y funciones y detallando la estructura y uso de cada uno de los mtodos utilizados de la misma. El resto de mtodos no usados podrn consultarse en la documentacin incluida en la biblioteca OpenCV. Puede accederse a estos ficheros a travs del archivo index.htm situado en la carpeta /share/doc. Posteriormente analizaremos la herramienta Haartraining, describiendo todos sus comandos individualmente, sus caractersticas y los resultados que aqullos producen.

Manual del programador

4

2

Algoritmo mastitis

2.1 Documentacin de clases2.1.1 Referencia de la clase CV#include En el mdulo Cv encontramos las primitivas de anlisis, procesamiento y reconocimiento de imgenes que son realizadas sobre las estructuras definidas en el mdulo CxCore. La biblioteca Cv define tambin operadores estndar para el clculo de gradientes, deteccin de bordes, esquinas y contornos, conversin de modelos de color, operaciones morfolgicas como dilatacin, erosin y adelgazamiento, transformadas geomtricas, etc. Tambin encontraremos funciones para tratar aspectos de la deteccin de objetos mediante su anlisis y movimiento y la deteccin de patrones a travs de conjuntos de imgenes.

2.1.1.1 cvThresholdvoid cvThreshold (IplImage* src, IplImage* dst, float threshold, float maxvalue, CvThreshType type) NECESITA: src: Imagen origen. dst: Imagen destino. Puede coincidir con la imagen origen. threshold: Parmetro umbral (lmite inferior). maxvalue: Valor mximo (lmite superior) usado en los tipos de umbral: CV_THRESH_BINARY, CV_THRESH_BINARY_INV y CV_THRESH_TRUNC. type: Tipos de umbral. Existen los siguientes tipos: CV_THRESH_BINARY: Si val > threshold CV_THRESH_TRUNC: Si val > threshold CV_THRESH_TOZERO: Si val > threshold val = maxvalue; si no val = 0. val = 0; si no val = maxvalue. val = threshold; si no val = maxvalue. val = val; si no val = 0. val = 0; si no val = val. CV_THRESH_BINARY_INV: Si val > threshold

CV_THRESH_TOZERO_INV: Si val > threshold Grficamente los tipos de umbral son los siguientes:

Manual del programador

5

Figura 1: cvThreshold

MODIFICA: La imagen destino guardando en ella la umbralizacin de la imagen origen, segn el mtodo dado en type y el umbral threshold. La umbralizacin se hace con un valor constante. Un mtodo ms avanzado es cvAdaptativeThreshold (consultar documento opencvref_cv.htm incluido en la documentacin de OpenCV) que calcula un umbral para cada pxel (adaptativo). Esta funcin se utiliza tpicamente para conseguir imgenes en escala de grises o de dos niveles.

Manual del programador

6

2.1.1.2 cvFindContoursint cvFindContours (CvArr* image, CvMemStorage* storage, CvSeq** first_contour, int header_size = sizeof(CvContour), int mode = CV_RETR_LIST, int method = CV_CHAIN_APPROX_SIMPLE, CvPoint offset = cvPoint(0,0) ) NECESITA: image: Imagen fuente de 8 bits o canales. storage: Donde se almacenan los contornos encontrados (contenedor de contornos). first_contour: Parmetro de salida que contendr el puntero al primer contorno exterior. Ser nulo si no se detectan contornos. header_size: Tamao de la cabecera de la secuencia. Ser mayor o igual que sizeof (cvChain) si method = CV_CHAIN_CODE y mayor o igual que sizeof (CvContour) en otro caso. mode: Modo de obtencin de los contornos. Existen varios tipos: CV_RETR_EXTERNAL: Recupera slo el contorno exterior de la imagen. CV_RETR_LIST: Recupera todos los contornos y los pone en la lista. CV_RETR_CCOMP: Recupera todos los contornos y los organiza en una jerarqua de dos niveles. El nivel superior estar formado por los lmites externos y el inferior por los internos. CV_RETR_TREE: Recupera todos los contornos y reconstruye la jerarqua completa. method: Mtodo de aproximacin para todos los modos excepto para el CV_RETR_RUNS, que usa un sistema propio (incorporado) de aproximacin: CV_CHAIN_CODE: Contornos exteriores mediante el cdigo de cadena de Freeman. CV_CHAIN_APPROX_NONE: Traduce todas las partes del cdigo de cadena a puntos. CV_CHAIN_APPROX_SIMPLE: Comprime los segmentos horizontales, verticales y diagonales dejando slo sus puntos finales. CV_CHAIN_APPROX_TC89_L1: Primera versin del algoritmo de aproximacin TehChin. CV_CHAIN_APPROX_TC89_KCOS: Segunda versin del algoritmo Teh-Chin. CV_LINK_RUNS: Slo puede ser usado con mode = CV_RETR_LIST. Utiliza un mtodo de enlaces de segmentos horizontales de 1s. offset: Desplazamiento a partir del cual se quitan todos los puntos del contorno.

Manual del programador

7

MODIFICA: Si se detectan contornos, first_contour contendr un puntero al primer contorno exterior encontrado. Los siguientes contornos se alcanzan utilizando h_next y v_next. PRODUCE: Encuentra los contornos de una imagen binaria y devuelve el nmero de contornos encontrados. En la imagen inicial, se trata a los pxeles de valor distinto de cero como unos y a los de valor cero como ceros. Esto produce el tratamiento de la imagen pasada como parmetro como binaria. Para obtener una imagen binaria a partir de una escala de grises, puede usarse cvThreshold, cvAdaptativeThreshold o cvCanny.

2.1.1.3 cvContourAreadouble cvContourArea (const CvArr* contour, CvSlice slice = CV_WHOLE_SEQ) NECESITA: contour: Contorno del cual queremos calcular el rea. slice: Puntos iniciales y finales de la seccin del contorno de inters. Por defecto se calcula el rea de todo el contorno.

PRODUCE: El rea de todo el contorno o de una seccin del mismo. La orientacin del contorno puede hacer que la funcin devuelva un resultado negativo, por lo que ser conveniente utilizar la funcin fabs() para obtener su valor absoluto.

Manual del programador

8

2.1.1.4 cvBox2Dtypedef struct CvBox2D32f { CvPoint2D32f center CvSize2D32f float angle } size

Estructura con tres campos que genera, usando flotantes, un rectngulo girado en 2 dimensiones y 32 bits. center: Centro del rectngulo. size: Ancho y largo del rectngulo. angle: ngulo formado entre el eje horizontal y el largo del rectngulo en radianes.

2.1.1.5 cvFitEllipsevoid cvFitEllipse (CvPoint* points, int n, CvBox2D32f* box) NECESITA: points: Puntero al conjunto de puntos 2D. n: Nmero de puntos. Debe ser mayor o igual que 6. box: Puntero a la estructura donde se almacena la elipse.

MODIFICA: La estructura box de la siguiente manera: box box box center: Punto central de la elipse. size: Dimensiones de los 2 ejes de la elipse. angle: ngulo formado entre el eje horizontal y el eje longitudinal de la elipse.

PRODUCE: Forma una elipse ajustada al conjunto de puntos pasados como parmetro. En versiones anteriores de OpenCV esta funcin exista pero no funcionaba, producindose un error en tiempo de ejecucin. En versiones recientes tambin podemos encontrar la funcin:

Manual del programador

9

CvBox2D cvFitEllipse2 (const CvArr* points) NECESITA: points: Secuencia o array de puntos

MODIFICA: La estructura box de salida de la siguiente manera: box box box center: Punto central de la elipse. size: Dimensiones de los 2 ejes de la elipse. angle: ngulo formado entre el eje horizontal y el eje longitudinal de la elipse.

PRODUCE: Calcula la elipse que mejor se adapta (atendiendo al sistema de los mnimos cuadrados) al conjunto de puntos pasados.

Manual del programador

10

2.1.2 Referencia a la clase HighGUI#include HighGUI permite la grabacin de imgenes en disco en los formatos vistos en el punto 1.5 de esta documentacin. Dispone de funciones para facilitar la captura y reproduccin de video y de mtodos para la captura de eventos de teclado (deteccin de teclas presionadas) o ratn.

2.1.2.1 cvNamedWindowint cvNamedWindow (const char* name, int flags) NECESITA: name: Nombre de la ventana a crear. flags: Flags de la ventana. Actualmente el nico soportado es CV_WINDOWS_AUTOSIZE, que puede estar a uno (el tamao de la ventana se ajusta automticamente a la imagen) o a cero (la imagen se escalar con la ventana).

MODIFICA: Crea una ventana en la que se pueden insertar imgenes y trackbars. Estas ventanas son referidas por su nombre. Si a la ventana se le da un nombre ya existente, la funcin no hace nada. PRODUCE: Produce un uno si la ventana se cre correctamente y cero en caso contrario.

2.1.2.2 cvDestroyWindowvoid cvDestroyWindow (const char* name) NECESITA: name: Nombre de la ventana a eliminar.

MODIFICA: Destruye la ventana de nombre name.

Manual del programador

11

2.1.2.3 cvShowImagevoid cvShowImage (const char* name, CvArr* image) NECESITA: name: Nombre de la ventana a mostrar. image: Imagen a mostrar.

MODIFICA: Muestra la imagen en la ventana especificada con name. Si la ventana fue creada con el flag de CV_WINDOWS_AUTOSIZE a uno, la imagen ser mostrada en su tamao original; si no, ser escalada con la ventana.

2.1.2.4 cvWaitKeyint cvWaitKey (int delay = 0) NECESITA: delay: espera en milisegundos.

MODIFICA: Espera a que se pulse una tecla indefinidamente si delay es menor o igual que cero. En caso contrario, espera delay milisegundos. PRODUCE: Devuelve el cdigo de la tecla pulsada 1 si no se ha pulsado ninguna tecla antes de cumplirse los delay milisegundos.

2.1.2.5 cvLoadImageIplImage* cvLoadImage (const char* filename, int iscolor = 1) NECESITA: filename: Nombre del archivo que contiene la imagen. Los archivos soportados por OpenCV son: Windows bipmap: BMP, DIB Archivos JPEG: JPEG, JPG, JPE Portable Network Graphics: PNG Sun rasters: SR, RAS TIFF files: TIFF, TIF

Manual del programador

12

iscolor: Especifica en nmero de canales con los que se carga la imagen. Si iscolor > 0, la imagen se carga con tres canales (rojo, verde y azul). Igual a cero si queremos que se cargue con un canal, en escala de grises. Menor que cero si queremos que se cargue con la cabecera del archivo.

MODIFICA: Carga una imagen del archivo especificado en la llamada. PRODUCE: Devuelve un puntero a la estructura de la imagen cargada (IplImage).

2.1.2.6 cvSaveImageint cvSaveImage (const char* filename, const CvArr* image) NECESITA: filename: Nombre del archivo. image: Nombre de la imagen a guardar.

MODIFICA: Guarda la imagen en el archivo especificado. El formato de la imagen depende de la extensin del filename. Los formatos permitidos son los mismos que los especificados en cvLoadImage. PRODUCE: Produce un uno si la imagen se guarda correctamente y un cero en caso contrario.

Manual del programador

13

2.1.3 Referencia a la clase CxCore#include El mdulo CxCore define e implementa las estructuras y operaciones que permiten realizar la edicin y manipulacin bsica de la imagen. Proporciona la estructura bsica con la que Intel representa las imgenes, denominada IplImage y que, como vimos anteriormente, est formado por una cabecera que contiene los atributos de la imagen y los punteros a los datos asociados. Adems, CxCore dispone de estructuras de datos dinmicas y operadores en las que se apoyan el resto de mdulos, como son los vectores (cvArr), matrices (cvMat), imgenes, grafos, etc. La mayora recibe por parmetro un vector mscara para especificar sobre qu elementos de la estructura se aplica el operador. Podremos encontrar operadores aritmticos (Add, Mult, Sub, etc.), lgicos (AND, OR, NOT, XOR), de comparacin, etc., as como funciones para aplicar clculos estadsticos (SUM, MAX, MIN, AVG) y operadores de conversin de tipo o escala de colores (ConvertScale).

2.1.3.1 IplImageComo ya hemos visto, la estructura de representacin de las imgenes es IplImage, que ya es utilizada por IPL (Intel Image Processing Library). Esta estructura dispone de muchos campos, muchos de los cuales son heredados de IPL y no se usan en OpenCV. A continuacin, mostramos y explicamos los campos ms importantes de la estructura: typedef struct _IplImage { int nSize; int nChannels; int width; int height; int depth; int dataOrder; int origin; char *imageData; int widthStep; struct _IplROI *roi; char *imageDataOrigin; int void } align; *imageId; struct _IplImage *maskROI; struct _IplTileInfo *tileInfo;

Manual del programador

14

CAMPOS: nSize: sizeof (IplImage). nChannels: nmero de canales. las ltimas versiones de OpenCV soportan 1, 2, 3 4 canales. width: ancho de la imagen (en pxeles). height: altura de la imagen (en pxeles). depth: profundidad del pxel en bits: IPL_DEPTH_8U Entero de 8 bits sin signo. IPL_DEPTH_8S Entero de 8 bits con signo. IPL_DEPTH_16S Entero de 16 bits con signo. IPL_DEPTH_32S Entero de 32 bits con signo. IPL_DEPTH_32F Reales de precisin simple (32 bits). IPL_DEPTH_64F Reales de precisin doble (64 bits). dataOrder: orden de los canales. Puede tener dos valores: 0 1 Entrelazado de pxeles. Por canales (pxeles separados).

cvCreateImage slo puede crear entrelazado de pxeles, mediante el flag IPL_DATA_ORDER_PIXEL. Sin embargo, si COI est activado, los canales seleccionados pueden ser procesados. origin: origen. Indica donde empieza la imagen, puede ser: origin = 0 habitual. Top-left: El pxel i(0,0) es la esquina superior izquierda. Es la ms

origin = 1 Bottom-left: El pxel i(0,0) es la esquina inferior izquierda. Usada en algunos formatos como BMP. imageData: puntero a los pxeles de la imagen. widthStep: tamao de la fila de datos de la imagen en bytes (entre una fila y la siguiente hay widthStep bytes). Al final de la fila pueden sobrar algunos bytes con le propsito de alinear las filas. roi: imagen ROI (zona de inters). Cuando no es nula (NULL), especifica la regin de la imagen que va a ser procesada. imageDataOrigin: puntero al origen de los datos de la imagen. align: alineamiento de los datos de la imagen. Pueden ser de 4 u 8 bytes. maskROI: debe ser nulo en OpenCV. imageId: tambin debe ser nulo. tileInfo: tambin debe ser nulo.

Los pxeles de la imagen estn referenciados en *imageData. Se almacenan por filas, de izquierda a derecha, empezando por la fila superior o la inferior (dependiendo del valor de origin) y entre una fila y otra encontramos widthStep bytes. Un ejemplo de esto puede ser:

Manual del programador

15

IplImage *img

int width = 2 int height = 2 int nChannels = 3 int depth = 8U char *imageData Figura 2: Ejmplo de estructura IplImage

widthStep = 8

2.1.3.2 CvPointCoordenadas de un punto (un pxel) en una imagen. La numeracin de filas y columnas empieza en cero. typedef struct CvPoint { int x; int y; } CAMPOS: x: coordenada x. y: coordenada y.

Existen funciones inline para crear e inicializar variables de estos tipos de datos: Constructor: inline CvPoint cvPoint (int x, int y) Conversin desde CvPoint2D32f: (CvPoint2D32f point) inline CvPoint cvPointFrom32f

Manual del programador

16

2.1.3.3 CvPoint2D32fCoordenadas de un punto (un pxel) expresado como real (flotante). typedef struct CvPoint2D32f { float x; float y; } CAMPOS: x: coordenada x. y: coordenada y.

Funciones inline de creacin e inicializacin de variables: Constructor: inline CvPoint2D32f cvPoint2D32f( double x, double y ) Conversin desde CvPoint: point) inline CvPoint2D32f cvPointTo32f (CvPoint

2.1.3.4 CvSizeExpresa el tamao de una regin rectangular, en pxeles typedef struct CvSize { int width; int height; } CAMPOS: width: anchura del rectngulo. height: altura del rectngulo.

Funciones inline de creacin e inicializacin de variables: Constructor: inline CvSize cvSize (int width, int height).

Manual del programador

17

2.1.3.5 cvCreateImageIplImage* cvCreateImage (CvSize size, int depth, int channels) NECESITA: size: tamao de la imagen depth: profundidad del pxel en bits. Como vimos en la estructura IplImage, esta profundidad puede ser: IPL_DEPTH_8U Entero de 8 bits sin signo. IPL_DEPTH_8S Entero de 8 bits con signo. IPL_DEPTH_16S Entero de 16 bits con signo. IPL_DEPTH_32S Entero de 32 bits con signo. IPL_DEPTH_32F Reales de precisin simple (32 bits). IPL_DEPTH_64F Reales de precisin doble (64 bits). channels: nmero de canales. Puede ser 1, 2, 3 4.

MODIFICA: Crea una imagen, formando su cabecera y la localizacin de sus datos. PRODUCE: Puntero a la estructura IplImage de la imagen creada.

2.1.3.6 cvCloneImageIplImage* cvCloneImage (const IplImage* image) NECESITA: image: imagen a clonar.

MODIFICA: Almacena la nueva imagen en la estructura IplImage de salida. PRODUCE: Una copia exacta y completa de la imagen inicial.

Manual del programador

18

2.1.3.7 CvMemStorageCvMemStorage crea una estructura esttica global necesaria para almacenar estructuras de datos que crecen dinmicamente como secuencias, contornos, etc. Esta estructura est organizada en forma de bloques de igual tamao, donde la cima (top) es actualmente usado (pero no necesariamente el ltimo bloque de la lista) y el campo bottom principio de la lista de bloques. Todos los bloques entre bottom y top (excluyendo a considerados ocupados, mientras que los bloques entre top y el ltimo bloque (excluyendo al considerados totalmente vacos. El bloque top puede estar parcialmente ocupado, por lo que free_space marca la cantidad de bytes libres en dicho bloque. el bloque apunta al ste) son top) son el campo

La nueva estructura de memoria puede ser asignada explcitamente por la funcin cvMemStorageAlloc o implcitamente por funciones de ms alto nivel como cvSeqPush, cvGraphAddEdge, etc., comenzando siempre por el final del bloque actual (top) - si tiene suficiente capacidad -. Despus de la asignacin, free_space es decrementado con el valor del espacio asignado incrementado en algunos bytes ms para mantener la alineacin adecuada. Si el bloque top no tiene espacio suficiente, es tomado como top el siguiente bloque de almacenaje y free_space guarda el tamao del bloque completo. Si no hay ms bloques libres, se asigna un nuevo bloque, pudiendo tomarlo del padre, y aadindolo al final de la lista. As, la estructura de almacenamiento se comporta como una pila, donde bottom, top y free_space son los elementos clave. typedef struct CvMemStorage { struct CvMemBlock* bottom; struct CvMemBlock* top; struct CvMemStorage* parent; int block_size; int free_space; } CAMPOS: bottom: puntero al primer bloque de memoria. top: cima actual de la pila. parent: situacin de los nuevos bloques, puede ser un puntero a los bloques del padre. block_size: tamao del bloque. free_space: espacio libre en bytes en el bloque apuntado por top.

Manual del programador

19

2.1.3.8 cvCreateMemStorageCvMemStorage* cvCreateMemStorage (int block_size = 0) NECESITA: bloq_size: tamao de los bloques que forman la estructura de almacenamiento en bytes. Si es cero, los bloques toman el tamao por defecto (64K).

MODIFICA: Crea una zona de almacenamiento en memoria, inicialmente vaca. Todos los campos de la estructura creada, excepto block_size, son puestos a cero. PRODUCE: Devuelve un puntero a la estructura de almacenamiento creada.

2.1.3.9 CvSeqLa estructura CvSeq es la base para todas las estructuras dinmicas de OpenCV. Dispone de una macro que facilita la extensin de la estructura con parmetros (secuencias) adicionales definidos por el programador. Para ampliar CvSeq, el programador define estas nuevas secuencias a continuacin de las ya existentes en la macro CV_SEQUENCE_FIELDS(). Hay dos tipos de secuencias, llamadas dense y sparse. Las secuencias dense tienen como tipo base CvSeq y se usan para representar estructuras dinmicas como vectores, pilas o colas. No disponen de elementos vacos en posiciones intermedias, de tal manera que si se inserta o se elimina un elemento en una de estas posiciones, el resto de elementos se reagrupan. Las secuencias sparse tienen como tipo base CvSet y estn formadas por nodos que disponen de un flag que indica si estn vacos o no. Estas secuencias se usan para estructuras de datos desordenadas como conjuntos de elementos, tablas hash, etc.

typedef struct CvSeq { CV_SEQUENCE_FIELDS() } donde CV_SEQUENCE_FIELDS() se define de la siguiente manera:

Manual del programador

20

#define CV_SEQUENCE_FIELDS() int flags; int header_size; struct CvSeq* h_prev; struct CvSeq* h_next; struct CvSeq* v_prev; struct CvSeq* v_next; int total; int elem_size; char* block_max; char* ptr; int delta_elems; CvMemStorage* storage; CvSeqBlock* free_blocks; CvSeqBlock* first; CAMPOS DE CV_SEQUENCE_FIELDS(): flags: contiene distintos flags. Si la secuencia es de tipo dense, en sus 16 bits ms altos contiene el campo CV_SEQ_MAGIC_VAL mientras que si es sparse, este campo ser el CV_SET_MAGIC_VAL, adems de otras informaciones referentes a la secuencia. Los bits ms bajos, referenciados por CV_SEQ_ELTYPE_BITS contienen la ID del tipo de elemento. header_size: tamao de la cabecera. Debe ser mayor o igual que sizeof (CvSeq). h_prev: secuencia previa. h_next: siguiente secuencia. v_prev: segunda secuencia previa. v_next: segunda secuencia posterior. total: contiene el nmero total de elementos en una secuencia de tipo dense, y el nmero de nodos asignados en una secuencia de tipo sparse. elem_size: tamao de los elementos de la secuencia en bytes. block_max: cota superior del ltimo bloque. ptr: puntero al elemento actual. delta_elems: nmero de elementos reservados cuando la secuencia crece. storage: estructura de almacenamiento de la secuencia. free_blocks: lista de bloques vacos. first: puntero al primer bloque de la secuencia.

Los campos h_prev, h_next, v_prev y v_next pueden ser usados para crear una estructura jerrquica de secuencias separadas, donde h_prev y h_next apuntarn a la secuencia previa y siguiente respectivamente en el mismo nivel jerrquico, mientras que v_prev y v_next apuntarn a la previa y posterior en direccin vertical, es decir, al padre y a su primer hijo.

Manual del programador

21

2.1.3.10 cvCvtSeqToArrayvoid * cvCvtSeqToArray (const CvSeq* seq, void* elements, CvSlice slice = CV_WHOLE_SEQ) NECESITA: seq: puntero a la estructura de la secuencia. elements: puntero al array de destino, que debe ser suficientemente grande. slice: parte de la secuencia a copiar al array. Por defecto copia la secuencia completa.

MODIFICA: Copia la secuencia completa o la subsecuencia en la estructura de almacenamiento especificada. PRODUCE: Puntero a la estructura de almacenamiento.

2.1.3.11 CV_RGBConstruye una variable de color. # define CV_RGB (r, g, b) Ejemplo: CV_RGB (255, 0, 0) CV_RGB (0, 255, 0) CV_RGB (0, 0, 255) color rojo color verde color azul cvScalar ((b), (g), (r))

Manual del programador

22

2.1.3.12 cvDrawContoursvoid cvDrawContours (CvArr* img, CvSeq* contour, CvScalar external_color, CvScalar hole_color, int max_level, int thickness = 1, int line_type = 8) NECESITA: img: imagen de la que se dibujarn los contornos. contour: puntero al primer contorno. external_color: color de los contornos exteriores. hole_color: color de los contornos interiores (agujeros). max_level: nivel mximo para dibujar contornos. Si es 0, slo contour ser dibujado (nivel 0). Si es 1, contour y todos los contornos del nivel 1 sern dibujados, etc. Si tiene un valor negativo, la funcin dibujar el contorno de nivel 0 y los de nivel abs(max_level)-1. thickness: Grosor de las lneas que dibujarn los contornos. Si es negativo (por ejemplo CV_FILLED), se dibujarn los contornos interiores (rea delimitada por los contornos exteriores). line_type: tipo de lnea: line_type = 8 line_type = 0 line_type = 4 lnea unida de 8 puntos. lnea unida de 8 puntos. lnea unida de 4 puntos. lnea de tipo antialiased.

line_type = CV_AA MODIFICA:

Dibuja los contornos exteriores de la imagen si thickness thickness < 0.

0 el rea interior a los contornos si

2.1.3.13 cvZerovoid cvSetZero (CvArr* arr) #define cvZero cvSetZero NECESITA: arr: array a vaciar o inicializar a cero. Se utiliza tambin para inicializar una imagen toda a cero (color negro).

MODIFICA: Pone el array a cero. En caso de arrays de tipo dense, cvZero (array) es equivalente a cvSet (array, cvScalarAll (0), 0) mientras que si el array es de tipo sparse, todos los elementos son eliminados.

Manual del programador

23

2.1.3.14 CvScalarProporciona un contenedor para nmeros con forma de tupla de 1, 2, 3 4 elementos. typedef struct CvScalar { double val[4]; } Funciones inline de creacin e inicializacin de variables: Constructor 1: inicializa val[0] = val0; val[1] = val1, etc. inline CvScalar cvScalar (double val0, double val1 = 0, double val2 = 0, double val3 = 0) Constructor 2 : Inicializa val[0]... val[3] con val0123 inline CvScalar cvScalarAll (double val0123) Constructor 3: Inicializa val[0] = val0; val[1] = val[2] = val[3] = 0 inline CvScalar cvRealScalar (double val0)

2.1.3.15 CvSizeIndica el tamao exacto de un pxel de un rectngulo. typedef struct CvSize { int width; int height; } CAMPOS: width: ancho del rectngulo. height: altura del rectngulo.

Funciones inline de creacin e inicializacin de variables: Constructor: inline CvSize cvSize (int width, int height)

Manual del programador

24

2.1.3.16 CvArrEspecifica un array arbitrario. typedef void CvArr; El tipo CvArr* se usa slo como parmetro de funciones, y puede representar distintos tipos de arrays como IplImage *, CvMat * CvSeq *.

2.1.3.17 cvCmpvoid cvCmp cmp_op) NECESITA: src1: primer array origen. Debe ser de un canal. src2: segundo array origen. Debe ser de un canal. dst: array destino. Debe ser de enteros de 8 bits con o sin signo. cmp_op: flag que especifica la relacin entre los elementos de los arrays. Puede ser: CV_CMP_EQ: src1 igual a src2. CV_CMP_GT: src1 mayor que src2. CV_CMP_GE: src1 mayor o igual a src2. CV_CMP_LT: src1 menor que src2. CV_CMP_LE: src1 menor o igual que src2. CV_CMP_NE: src1 distinto a src2. MODIFICA: Compara, elemento a elemento, los arrays origen, guardando el resultado de la operacin en el array destino. Los arrays deben ser del mismo tipo (excepto el de destino) y tener la misma dimensin. El resultado ser un array binario. Cada posicin de este array ser un 1 si la relacin entre src1 y src2 es cierta y un 0 en caso contrario. (const CvArr* src1, const CvArr* src2, CvArr* dst, int

Manual del programador

25

2.1.3.18 cvGetSizeCvSize cvGetSize (const CvArr* arr) NECESITA: arr: matriz o imagen de la cual se devolver su tamao.

MODIFICA: Calcula las dimensiones de la estructura pasada como parmetro. PRODUCE: Devuelve el nmero de filas (CvSize::height) y el nmero de columnas (CvSize::width) de la matriz o imagen pasada por parmetro.

2.1.3.19 cvRoundint cvRound (double value) NECESITA: value: punto expresado como flotante.

MODIFICA: Convierte el punto con coordenadas flotantes de entrada en un nmero entero. PRODUCE: Devuelve el valor del nmero entero ms cercano al argumento.

Manual del programador

26

2.1.3.20 cvEllipsevoid cvEllipse (CvArr* img, CvPoint center, CvSize axes, double angle, double start_angle, double end_angle, CvScalar color, int thickness = 1, int line_type = 8, int shift = 0); NECESITA: img: imagen inicial. center: centro de la elipse. axes: longitud de los ejes de la elipse. angle: ngulo de rotacin. start_angle: ngulo inicial del arco de la elipse. end_angle: ngulo final del arco de la elipse. color: color de la elipse. thickness: grosor del arco de la elipse. line_type: tipo de lnea (ver 9.2.1.3.12) shift: nmero de bits fraccionados en el centro de coordenadas. MODIFICA: Dibuja un arco elptico o rellena el interior de una elipse.

Manual del programador

27

2.2 AlgoritmoEn este punto explicaremos paso a paso el funcionamiento del algoritmo de deteccin de la mastitis, analizando el cdigo as como los resultados intermedios y finales producidos en una imagen pasada como parmetro. La imagen inicial utilizada para este anlisis es la siguiente:

Figura 3: Imagen pasada como parmetro

Manual del programador

28

2.2.1 Explicacin del cdigo 2.2.1.1 Includes#include // incluye la biblioteca de OpenCV

#include // incluye definiciones HighGUI #include // estructuras y operaciones de CxCore #include #include #include #include #include #include

2.2.1.2 Declaracin e inicializacin de variables// Origen contendr la imagen inicial pasada por parmetro:IplImage *origen;

/* Declaramos una serie de estructuras IplImagen de un slo canal (blanco y negro), que contendrn imgenes parciales obtenidas despus de transformaciones. ByN contendr la imagen inicial transformada a blanco y negro; ByNSinBordes esa misma imagen sin los bordes exteriores; BordesExt contendr slo los bordes de la imagen y FINAL tendr la imagen final despus de todos los clculos realizados. Como se puede observar, estas imgenes son creadas con el tamao de la imagen inicial, una profundidad de 8 bits y 1 canal. */IplImage* ByN = cvCreateImage (cvGetSize(origen), 8, 1); IplImage* ByNSinBordes = cvCreateImage (cvGetSize(origen), 8,1); IplImage* BordesExt = cvCreateImage (cvGetSize(origen), 8, 1); IplImage* FINAL = cvCreateImage (cvGetSize(origen), 8, 1);

/* Creamos una zona de almacenamiento en memoria, inicialmente vaca, para almacenar las imgenes y las secuencias que contendrn dichas imgenes. Como parmetro de la funcin pasamos un cero, lo que har que el tamao del bloque de memoria ser el de por defecto (64K). */CvMemStorage* mem = cvCreateMemStorage(0);

Manual del programador

29

/* Declaramos secuencias de memoria, de tipo dense, para representar estructuras dinmicas que contendrn los contornos de las imgenes: */CvSeq * contorno0 = 0; CvSeq * contorno1 = 0; CvSeq * contorno2 = 0;

/* Declaramos coordenadas de puntos (pxeles) de una imagen en formato de entero o flotante. La numeracin de filas y columnas empieza en cero. */CvPoint* PointArray; CvPoint2D32f* PointArray2D32f;

/* Declaramos una estructura que genera, usando flotantes, un rectngulo girado en 2 dimensiones y 32 bits y servir para almacenar elipses. */CvBox2D32f* MemElipse;

/* Inicializamos con cvZero las imgenes en blanco y negro. Est inicializacin pone a cero dichas imgenes (color negro). */cvZero(ByN); cvZero(BordesExt); cvZero(ByNSinBordes); cvZero(FINAL);

/* Declaramos tres contadores que registrarn el nmero de clulas. El primero de ellos, contar las clulas de los bordes exteriores de la imagen; el segundo, el de las clulas interiores (sin bordes) y el ltimo de ellos registrar el nmero de clulas totales. */int NumeroCelulasContorno int NumeroCelulasTotal = 0; = 0;

int NumeroCelulasSinBordes = 0;

/* A continuacin declaramos lmites numricos que usaremos a lo largo del programa. Estos valores fueron proporcionados por el equipo de microscopa del proyecto. */

Manual del programador

30

/* Limites para el parmetro maxvalue de la instruccin cvThreshold, usada principalmente en este algoritmo para conseguir imgenes binarias: */int LimiteInfByN int LimiteSupByN = 127; = 255; // Lmite inferior de la imagen en blanco y negro. // Lmite superior de la imagen en blanco y negro. // Lmite inferior de los contornos exteriores. // Lmite superior de los contornos exteriores. // Lmite inferior de la imagen final. // Lmite superior de la imagen final.

int LimiteInfContExt = 180; int LimiteSupContExt = 255; int LimiteInfFINAL int LimiteSupFINAL = 127; = 255;

// Otros lmites usados:long int LimSupCelsContorno long int LimInfCelsContorno long int LimSupSinBordes1 long int LimInfSinBordes1 long int LimSupSinBordes2 long int LimInfSinBordes2 = 1700000; = 160000; = 1700000; = 160000; = 340000; = 5000;

long int LimSupCelEliminadas = 4999; long int LimInfCelEliminadas = 2000; int TamMedioCelulas = 12000;

// Declaramos variables que almacenarn distintas reas :double area1_contorno double area2_contorno double area_positiva double area_negativa double area_elipse double area_total double cociente = 0; = 0; = 0; = 0; = 0; = 0; = 0;

double area_total_contorno = 0;

// Otras variables:CvSize size; // Variable de tamao. CvPoint center; // Puntero de coordenada float media = 0; double suma = 0; int nele = 0, cont = 0, eliminadas = -1; double PI = 3.141592;

Manual del programador

31

2.2.1.3 Mostrar Imagenvoid MostrarImagen (char *nombre, IplImage *im, int val) { cvNamedWindow (nombre, val); cvShowImage (nombre, im); cvWaitKey (0); // Espera indefinidamente hasta que se pulse una tecla cvDestroyWindow (nombre); // Destruye la ventana despus de pulsar la tecla anterior }

NECESITA: nombre: nombre de la ventana a crear. im: imagen a mostrar. val: flag CV_WINDOWS_AUTOSIZE de la ventana. Si est a uno, el tamao de la ventana se ajusta automticamente a la imagen; si est a cero la imagen se escala con la ventana (se puede cambiar su tamao).

MODIFICA: Crea una ventana denominada nombre y muestra en ella la imagen im pasada por parmetro. La ventana permanecer visible hasta que se pulse cualquier tecla, momento en el cual ser eliminada.

Manual del programador

32

2.2.1.4 Inicio del mainint main (int argc, char** argv) { // argc contiene el nmero de argumentos de la llamada mientras que argv la lista de esos argumentos. IplImage *origen; // Cargamos en origen la imagen inicial que queremos procesar. if (argc == 2 && (origen = cvLoadImage (argv[1], 0)) != 0) { /* */ // Resto de declaraciones: IplImage* ByN = cvCreateImage (cvGetSize(origen), 8, 1); IplImage* ByNSinBordes = cvCreateImage (cvGetSize(origen), 8, 1); IplImage* BordesExt = cvCreateImage (cvGetSize(origen), 8, 1); IplImage* FINAL = cvCreateImage (cvGetSize(origen), 8, 1); CvMemStorage* mem = cvCreateMemStorage(0); argv[1]: archivo que contiene la imagen 0: la imagen se carga con un canal

CvSeq * contorno0 = 0; CvSeq * contorno1 = 0; CvSeq * contorno2 = 0; CvPoint* PointArray; CvPoint2D32f* PointArray2D32f; CvBox2D32f* MemElipse; cvZero(ByN); cvZero(BordesExt); cvZero(ByNSinBordes); cvZero(FINAL); int NumeroCelulasContorno int NumeroCelulasTotal = 0; = 0;

int NumeroCelulasSinBordes = 0;

Manual del programador

33

int LimiteInfByN int LimiteSupByN

= 127; = 255;

int LimiteInfContExt = 180; int LimiteSupContExt = 255; int LimiteInfFINAL int LimiteSupFINAL = 127; = 255; = 1700000; = 160000; = 1700000; = 160000; = 340000; = 5000;

long int LimSupCelsContorno long int LimInfCelsContorno long int LimSupSinBordes1 long int LimInfSinBordes1 long int LimSupSinBordes2 long int LimInfSinBordes2

long int LimSupCelEliminadas = 4999; long int LimInfCelEliminadas = 2000; int TamMedioCelulas = 12000;

MostrarImagen ("Foto origen sin ningn tratamiento", origen);

Figura 4: Primera imagen mostrada

Manual del programador

34

// Guardamos la imagen anterior en un archivo de extensin png. cvSaveImage($DIRECTORIOBASE/Tratamiento_imagen/01_imagen.png, /* 01_imagen.png: nombre del archivo origen: nombre de la imagen a guardar */ // Clonamos la imagen inicial para no modificarla (quedar almacenada en origen), almacenando la copia en al estructura ByN. ByN = cvCloneImage (origen); /* origen: imagen a clonar */ // Binarizamos la imagen anterior, aplicando la funcin cvThreshold. cvThreshold(ByN, ByN, LimiteInfByN, LimiteSupByN, CV_THRESH_BINARY ); /* ByN: imagen origen ByN: imagen destino LimiteInfByN: parmetro umbral (lmite inferior) LimiteSupByN: valor mximo (lmite superior) CV_THRESH_BINARY: Si val > LimiteInfByN */ val = LimiteSupByN; sino val = 0 origen);

MostrarImagen ("Foto origen en blanco y negro", ByN);

Manual del programador

35

Figura 5: Imagen inicial binarizada

// Volvemos a guardar la imagen en el mismo directorio: cvSaveImage($DIRECTORIOBASE/Tratamiento_imagen/02_ByN.png", ByN); /* 02_ByN.png: nombre del archivo ByN: nombre de la imagen a guardar */

Manual del programador

36

2.2.1.5 Obtencin de los contornos exteriores // Clonamos la imagen ByN, almacenando la copia en BordesExt. BordesExt = cvCloneImage (ByN); // ByN: imagen a clonar // Buscamos los contornos exteriores de la imagen BordesExt, almacenndolos en el contenedor mem. contorno0 tendr un puntero al primer contorno encontrado. Con CV_RETR_EXTERNAL recuperamos slo los contornos exteriores de la imagen. cvFindContours (BordesExt, mem, &contorno0, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE); /* BordesExt: imagen fuente mem: lugar de almacenamiento de los contornos encontrados contorno0: puntero al primer contorno exterior sizeof(CvContour): tamao de la cabecera de la secuencia CV_RETR_EXTERNAL: recupera slo el contorno exterior de la imagen CV_CHAIN_APPROX_SIMPLE: Comprime los segmentos horizontales, verticales y diagonales dejando slo sus puntos finales */ sizeof(CvContour),

Manual del programador

37

2.2.1.6 Clculo del rea de los contornos /* En este punto calculamos el rea de los contornos obtenidos anteriormente. Una vez hecho esto, comprobamos si en dicha rea puede haber clulas a detectar, para lo que hacemos una media del rea total obtenida con el tamao medio de las clulas. */ /* Declaramos dos variables de color, una para los bordes exteriores y otra para los huecos, dndole valores aleatorios, ya que no modificarn el resultado final. Esto es debido a que las imgenes a tratar son binarias (en blanco y negro). */ CvScalar colorExterior = CV_RGB (rand(), rand(), rand()); CvScalar colorHuecos = CV_RGB ( rand(), rand(), rand() ); // El siguiente for recorre los contornos encontrados anteriormente (recordemos que contorno0 contiene un puntero al primer contorno encontrado. A travs de h_next, h_prev, v_next y v_prev podemos acceder al resto de contornos. for (; contorno0 { area1_contorno = fabs (cvContourArea (contorno0, CV_WHOLE_SEQ)); /* contorno0: contorno del cual queremos calcular el rea CV_WHOLE_SEQ: calculamos el rea de todo el contorno */ cvDrawContours CV_FILLED, 8); /* BordesExt: imagen de la que se dibujarn los contornos contorno0: puntero al primer contorno colorExterior: color de los contornos exteriores colorHuecos: color de los contornos interiores (huecos) -1: nivel mximos para dibujar los contornos CV_FILLED: grosor de las lneas. CV_FILLED indica que se dibujarn los contornos interiores 8: tipo de lnea */ } //fin_for (BordesExt, contorno0, colorExterior, colorHuecos, -1, 0; contorno0 = contorno0 -> h_next)

Manual del programador

38

/* Clculo de reas parciales y totales, recorriendo los contornos horizontal y verticalmente. El resultado de dichos clculos se almacenar en la variable total. */ for (; contorno0 { area2_contorno = fabs (cvContourArea (contorno0, CV_WHOLE_SEQ)); /* contorno0: contorno del cual queremos calcular el rea CV_WHOLE_SEQ: calculamos el rea de todo el contorno */ contorno1 = contorno0 -> v_next; // Contornos verticales if (contorno1) { for (; contorno1 /* contorno1: contorno del cual queremos calcular el rea CV_WHOLE_SEQ: calculamos el rea de todo el contorno */ 0; contorno1 = contorno1 -> h_next) 0; contorno0 = contorno0 -> h_next)

area2_contorno += fabs (cvContourArea (contorno1, CV_WHOLE_SEQ));

total_contorno += area1_contorno + area2_contorno; }//fin_if /* En el siguiente bucle, comprobamos la existencia de aglomeraciones de clulas. Para ello, comparamos el resultado del rea anterior con los lmites dados por el equipo de microscopa. */ if ((total_contorno LimInfCelsContorno)) { /* Hacemos una aproximacin del nmero de clulas del contorno, dividiendo el rea total por el tamao medio de las clulas. */ NumeroCelulasContorno += (int) (total_contorno / TamMedioCelulas); }//fin_If }//fin_for LimSupCelsContorno) && (total_contorno

Manual del programador

39

// Volvemos a binarizar la imagen: cvThreshold (BordesExt, CV_THRESH_BINARY); /* BordesExt: imagen origen BordesExt: imagen destino LimiteInfContExt: parmetro umbral (lmite inferior) LimiteSupContExt: valor mximo (lmite superior) CV_THRESH_BINARY: Si val > LimiteInfContExt val = 0 */ val = LimiteSupContExt sino BordesExt, LimiteInfContExt, LimiteSupContExt,

MostrarImagen ("Contornos exteriores", BordesExt, 0);

Figura 6: Bordes exteriores

Manual del programador

40

cvSaveImage($DIRECTORIOBASE/Tratamiento_imagen/03_BordesExt.png", BordesExt); /* 02_BordesExt.png: nombre del archivo BordesExt: nombre de la imagen a guardar */

Manual del programador

41

2.2.1.7 Eliminacin de los contornos exteriores // Una vez obtenidos los contornos exteriores, los eliminamos de la imagen. // Clonamos la imagen ByN, que contiene la imagen inicial en blanco y negro. ByNSinBordes contendr esa misma imagen pero sin los contornos exteriores. ByNSinBordes = cvCloneImage (ByN); //ByN: imagen a clonar // Realizamos la operacin [ByNSinBordes = ByN op BordesExt], siendo op la operacin lgica ' ' = cvCmp (ByN, BordesExt, ByNSinBordes, CV_CMP_EQ); /* ByN: primer array origen BordesExt: segundo array origen ByNSinBordes: array destino CV_CMP_EQ: ByN igual a BordesExt */ MostrarImagen ("Imagen ByNSinBordes, 0); inicial binarizada sin contornos exteriores", 1 si ByN = BordesExt; 0 si no.

Figura 7: Imagen en blanco y negro sin bordes exteriores

Manual del programador

42

cvSaveImage($DIRECTORIOBASE/Tratamiento_imagen/04_SinBordes.png", ByNSinBordes); /* 04_SinBordes.png: nombre del archivo ByNSinBordes: nombre de la imagen a guardar */

Manual del programador

43

2.2.1.8 Clculo del nmero de clulas // En este punto y una vez conseguida la imagen en blanco y negro sin los bordes exteriores, calcularemos el nmero de clulas de la mastitis. Para ello ajustaremos las clulas detectadas con elipses y compararemos las dimensiones de dichas elipses con las medidas dadas por el equipo de microscopa para comprobar si dichas clulas son somticas o no. // Inicializamos de nuevo los contornos. contorno0 = 0; contorno1 = 0; // Volvemos a comprobar los contornos, pero esta vez los interiores (los exteriores ya han sido eliminados), realizando una jerarqua completa de los mismos. Para ello ponemos el flag CV_RETR_TREE. cvFindContours (ByNSinBordes, mem, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE); /* ByNSinBordes: imagen fuente mem: lugar de almacenamiento de los contornos encontrados contorno0: puntero al primer contorno exterior sizeof(CvContour): tamao de la cabecera de la secuencia CV_RETR_TREE: Recupera todos los contornos y reconstruye la jerarqua completa. CV_CHAIN_APPROX_SIMPLE: Comprime los segmentos horizontales, verticales y diagonales dejando slo sus puntos finales */ // Nos desplazamos por los contornos horizontalmente for ( ;contorno0; contorno0 = contorno0 -> h_next ) { // Bajamos un nivel en la jerarqua de contornos (hijo) contorno1 = contorno0 -> v_next; if (contorno1) { // Nos desplazamos horizontalmente en ese nivel inferior for (; contorno1; contorno1 = contorno1 -> h_next ) { // total: contiene el nmero total de elementos en una secuencia nele = contorno1 -> total; &contorno0, sizeof(CvContour),

Manual del programador

44

if ( nele >= 6 ) { PointArray = new CvPoint [nele * sizeof(CvPoint)]; PointArray2D32f=new CvPoint2D32f [nele * sizeof(CvPoint2D32f)]; // Reservo memoria para los datos de la elipse MemElipse = new CvBox2D32f [sizeof(CvBox2D32f)];

/* Hacemos una copia de la secuencia, almacenndola en la estructura PointArray. */ cvCvtSeqToArray (contorno1, PointArray, CV_WHOLE_SEQ); /* contorno1: puntero a los contornos PointArray: puntero al array de destino CV_WHOLE_SEQ: se copia la secuencia completa */ /* Guardamos la secuencia anterior pasndola a flotante */ for (int i=0; i < nele; i++) { PointArray2D32f[i].x =(float)PointArray[i].x; PointArray2D32f[i].y =(float)PointArray[i].y; }fin_for /* Formamos una elipse con la secuencia anterior almacenndola en MemElipse */ cvFitEllipse (PointArray2D32f, nele, MemElipse); /* PointArray2D32f: puntero al conjunto de puntos nele: nmero de puntos (tiene que ser mayor que 6) MemElipse: puntero a la estructura de almacenamiento de la elipse */ /* Guardamos en center el valor entero correspondientes a la coordenada del centro de la elipse. */ center.x = cvRound (MemElipse -> center.x); center.y = cvRound (MemElipse -> center.y); /* MemElipse -> center.x: punto expresado como flotante */

Manual del programador

45

/* Guardamos en size los enteros correspondiente al tamao de los radios de la elipse */ size.width = cvRound (MemElipse -> size.width * 0.5); size.height = cvRound (MemElipse -> size.height * 0.5); /* MemElipse -> size.width * 0.5: punto expresado como flotante */ // Evitamos la posible existencia de ngulos negativos MemElipse -> angle = fabs (MemElipse -> angle); // Guardamos en variables de flotantes el tamao de los radios de los ejes float eje_uno = MemElipse -> size.width; float eje_dos = MemElipse -> size.height; /* Calculamos el valor de los ejes mayor y menor, haciendo el mximo y el mnimo de los ejes calculados en el paso anterior */ float eje_mayor eje_dos)/2; float eje_menor eje_dos)/2; = = (eje_uno (eje_uno + + eje_dos)/2 eje_dos)/2 + fabs fabs (eje_uno (eje_uno -

area_positiva = cvContourArea (contorno1, CV_WHOLE_SEQ); /* contorno1: contorno del que queremos calcular el rea CV_WHOLE_SEQ: se calcular el rea de todo el contorno */ area_elipse = PI * eje_mayor * eje_mayor; cociente = area_positiva / area_elipse; /* Recorremos las elipses interiores a otras elipses calculando su rea (rea negativa) */ area_negativa = 0; contorno2 = contorno1 -> v_next; for(; contorno2; contorno2 = contorno2 -> h_next) { if ( contorno2 -> total >= 6 ) area_negativa += (cvContourArea (contorno2, CV_WHOLE_SEQ)); /* contorno2: contorno del que queremos calcular el rea CV_WHOLE_SEQ: se calcular el rea de todo el contorno */

Manual del programador

46

}//fin_for // El rea total ser la suma del rea positiva y la negativa area_total = area_negativa + area_positiva; if ((area_total LimInfSinBordes1)) { cvDrawContours (ByNSinBordes, colorHuecos, -1, 1, 8); /* ByNSinBordes: imagen de la que se dibujarn los contornos contorno1: puntero al primer contorno colorExterior: color de los contornos exteriores colorHuecos: color de los contornos interiores (huecos) -1: nivel mximo para dibujar los contornos 1: grosor de las lneas 8: tipo de lnea */ NumeroCelulasSinBordes += (int)( area_total / TamMedioCelulas ); MostrarImagen ("Calculo de elipses (1)", ByNSinBordes, 0); // En nuestro ejemplo no entr en este bucle cvSaveImage($DIRECTORIOBASE/Tratamiento_imagen/05_elipses1.png", ByNSinBordes); /* 05_elipses1.png: nombre del archivo ByNSinBordes: nombre de la imagen a guardar */ }fin_if contorno1, colorExterior, =

Manual del programador

47

else if ((area_total = 0.15) ) { //Dibujamos la elipse

&&

(area_total

>=

cvEllipse (ByNSinBordes, center, size, MemElipse -> angle, 0, 360, CV_RGB(255, 0, 0), 3); /* ByNSinBordes: imagen inicial center: centro de la elipse size: longitud de los ejes de la elipse MemElipse -> angle: ngulo de rotacin 0: ngulo inicial del arco de la elipse 360: ngulo final del arco de la elipse CV_RGB(255, 0, 0): color de la elipse 3: grosor del arco de la elipse 8 (por defecto): tipo de lnea 0 (por defecto): nmero de bits fraccionados en el centro de coordenadas */

cvDrawContours (ByNSinBordes, CV_RGB(0,0,255), -1, 1, 8); /*

contorno1,

CV_RGB(0,0,255),

ByNSinBordes: imagen de la que se dibujarn los contornos contorno1: puntero al primer contorno CV_RGB(0,0,255): color de los contornos exteriores CV_RGB(0,0,255): color de los contornos interiores (huecos) -1: nivel mximo para dibujar los contornos 1: grosor de las lneas 8: tipo de lnea */ cont ++; suma += area_total; MostrarImagen ("Calculo de elipses (2)", ByNSinBordes, 0);

Manual del programador

48

Figura 8: Clculo de elipses (2)

cvSaveImage($DIRECTORIOBASE/Tratamiento_imagen/05_elipses2.png", ByNSinBordes); /* 05_elipses2.png: nombre del archivo ByNSinBordes: nombre de la imagen a guardar */ }fin_else /* Comprobamos, segn los lmites dados por el equipo de microscopa para las reas, la necesidad de eliminar algunas clulas que se salen de dichos lmites */ if ((area_total angle, 0, 360, CV_RGB(0,0,255), 3); /* ByNSinBordes: imagen inicial LimSupCelEliminadas) && (area_total >=

Manual del programador

49

center: centro de la elipse size: longitud de los ejes de la elipse MemElipse -> angle: ngulo de rotacin 0: ngulo inicial del arco de la elipse 360: ngulo final del arco de la elipse CV_RGB(0, 0, 255): color de la elipse 3: grosor del arco de la elipse 8 (por defecto): tipo de lnea 0 (por defecto): nmero de bits fraccionados en el centro de coordenadas */ cvDrawContours (ByNSinBordes, CV_RGB(0,0,0), -1, 1, 8); /* ByNSinBordes: imagen de la que se dibujarn los contornos contorno1: puntero al primer contorno CV_RGB(0,0,0): color de los contornos exteriores CV_RGB(0,0,0): color de los contornos interiores (huecos) -1: nivel mximo para dibujar los contornos 1: grosor de las lneas 8: tipo de lnea */ MostrarImagen ("Clulas eliminadas", ByNSinBordes, 0); contorno1, CV_RGB(0,0,0),

Manual del programador

50

Figura 9: Clulas eliminadas

cvSaveImage($DIRECTORIOBASE/Tratamiento_imagen/06_Eliminadas. png", ByNSinBordes); /* 06_eliminadas.png: nombre del archivo ByNSinBordes: nombre de la imagen a guardar */ }fin_if

// Liberamos la memoria usada delete PointArray; delete PointArray2D32f; delete MemElipse; cvDrawContours (ByNSinBordes, colorHuecos, -1, -1, 8); /* ByNSinBordes: imagen de la que se dibujarn los contornos contorno1: puntero al primer contorno contorno1, colorExterior,

Manual del programador

51

colorExterior: color de los contornos exteriores colorHuecos: color de los contornos interiores (huecos) -1: nivel mximo para dibujar los contornos -1: grosor de las lneas 8: tipo de lnea */

} // fin_if } // fin_for } //fin_if }//fin_for

Manual del programador

52

2.2.1.9 Tratamiento imagen final

if (cont != 0) media = suma / cont; if (eliminadas > 0) NumeroCelulasTotal = cont + NumeroCelulasSinBordes - eliminadas; else NumeroCelulasTotal NumeroCelulasSinBordes; = cont + NumeroCelulasContorno +

NumeroCelulasContorno

+

if (NumeroCelulasTotal < 0) NumeroCelulasTotal = 0; cout