Procesamiento en OpenCV.

Operaciones de procesamiento global:
‡ Tipos: unarias, binarias, histogramas.
Recordar: un CvArr puede ser un IplImage

void cvUnaria (const CvArr* A, ..., CvArr* B, ...) void cvBinaria (const CvArr* A, const CvArr* B,.., CvArr* C, ...)

‡ Las funciones reciben una (unarias) o dos (binarias) imágenes de entrada, y producen una de salida. Todas ellas deben estar creadas, también la imagen de salida. ‡ La mayoría de las funciones admite modo inplace: una imagen de entrada se puede usar también para guardar el resultado. ‡ Muchas de las operaciones trabajan con ROI, COI y mask No operan sobre toda la imagen sino sólo sobre una parte concreta (rectángulo, canal o máscara de interés).

Procesamiento en OpenCV.
‡ Es importante observar las restricciones impuestas sobre las imágenes admitidas en cada función. ‡ En otro caso ocurrirá un error (se produce una excepción). ‡ Normalmente:
± Todas las imágenes deben ser del mismo tipo: profundidad y número de canales. ± Todas las imágenes deben tener el mismo tamaño. ± Algunas funciones requieren imágenes con 1 solo canal. ± Opcionalmente, algunas admiten el uso de una máscara (mask), que será otra imagen, de 8 bits y con un 1 canal. Un valor 0 significa que el píxel no se procesa, y  0 sí se procesa. ± Ver la documentación para cada función.

cvScale. cvEqualizeHist. cvLog ‡ Operaciones binarias: ± cvAdd. cvAbsDiffS. cvMinS. cvSetZero. cvConvertScaleAbs. cvXorS. cvConvertScale. cvDiv. cvCmpS. cvSubS. cvAbs. cvConvert. cvAndS. cvAbsDiff. cvPow. cvNormalizeHist. cvMin ‡ Operaciones con histogramas: ± cvCreateHist. cvAddWeighted. cvMul. cvLUT . cvAdaptiveThreshold. cvCmp. cvQueryHistValue.A. cvGetHistValue. cvSub. cvMax. Procesamiento en OpenCV. cvOrS. cvOr. cvNot. cvAddS. cvCalcHist. cvAnd. cvReleaseHist. cvGetMinMaxHistValue. cvXor. cvThreshold. cvCopy.2. ‡ Operaciones unarias: ± cvSet. cvSubRS. cvMaxS.

255. Copiar un trozo de imagen en otra imagen: cvSetImageROI(img. img2).y):= S ‡ Ejemplo. img->depth. cvRect(50. cvResetImageROI(img).y)0 entonces B(x. cvScalar(0.0)). .y) ‡ Ejemplo. const CvArr* mask =0) si mask(x. 100). ‡ Inicializar una imagen con un valor constante: void cvSet (CvArr* A.y):= A(x. CvArr* B.y)0 entonces A(x. cvCopy(img. Inicializar a verde: cvSet(img.Procesamiento en OpenCV. ‡ Inicializar una imagen con un valor 0: void cvSetZero (CvArr* A) / void cvZero (CvArr* A) A(x. CvScalar S.y):= 0 ‡ Copiar una imagen en otra: void cvCopy (const CvArr* A. 100. 100)). img2= cvCreateImage(cvSize(100. const CvArr* mask=0) si mask(x. img->nChannels).50.

‡ Restar a un valor constante una imagen : void cvSubRS (const CvArr* A. . img2). img). ‡ Aumentar el brillo (inplace): cvAddS(img. const CvArr* mask=0) si mask(x.y) ‡ Ejemplo.y) ± S ‡ Ejemplo. CvScalar S.0. ‡ Restar a una imagen un valor constante: void cvSubS (const CvArr* A. ‡ Sumar a una imagen un valor constante: void cvAddS (const CvArr* A.y):= S ± A(x.y) + S ‡ Ejemplo.0). cvScalar(40. Invertir una imagen (en color o B/N). CvArr* C. const CvArr* mask=0) si mask(x.y):= A(x.y):= A(x. cvScalarAll(50). CvArr* C.y)0 entonces C(x.Procesamiento OpenCV. const CvArr* mask=0) si mask(x.y)0 entonces C(x. CvScalar S.y)0 entonces C(x. cvScalarAll(50). CvArr* C. img). img). Disminuir el brillo: cvSubS(img. cvSubRS(img. cvScalarAll(255). CvScalar S. Sumar un poco de azul: cvAddS(img.

double scale=1. ‡ Tiene sinónimos. 1. CvScalar S) C(x. CvArr* C) C(x. ‡ Valor absoluto de una imagen: void cvAbs (const CvArr* A.y):= |A(x. ‡ La función permite hacer conversiones entre imágenes con distintos valores de profundidad (de 8 bits a 16. etc). ‡ Ejemplo.y):= |A(x.Procesamiento en OpenCV. Ver también cvConvertScaleAbs. cvScalar(40. Ajuste del contraste: cvConvertScale(img. img2.y) ± S| ‡ Ejemplo.y)| ‡ Tiene sentido cuando la profundidad son números con signo ‡ Producto/división de una imagen por una constante: void cvScale (const CvArr* A.150)). cvAbsDiffS(img.128. o a reales de 32 bits. como cvConvertScale. .6. ‡ Valor absoluto de diferencia entre una imagen y un valor constante: void cvAbsDiffS (const CvArr* A . CvArr* B. CvArr* C.y) * scale + shift (igual para todos los canales) ‡ Se puede hacer cualquier transformación lineal.y):= A(x. img2. double shift=0) B(x. -50).

y)0 entonces C(x. ‡ Ajuste lineal del histograma (y otros métodos de normalización): void cvNormalize(const CvArr* A.y):= NOT A(x.y)0 entonces C(x.y) OR S ‡ O exclusivo entre una imagen y un valor constante (a nivel de bits): void cvXorS (const CvArr* A.Procesamiento en OpenCV. Vale para invertir una imagen: cvNot(img. CvArr* C. CvArr* C.y)0 entonces C(x. CvScalar S. CvScalar S. CvScalar S. img). const CvArr* mask=0) si mask(x. double b.y) ‡ Ejemplo. CvArr* C) C(x. ¿para qué valen las otras operaciones booleanas con constantes? . const CvArr* mask=0) si mask(x.y) XOR S ‡ Negación lógica de una imagen (a nivel de bits): void cvNot (const CvArr* A. const CvArr* mask=0) si mask(x. double a.y) AND S ‡ O lógico entre una imagen y un valor constante (a nivel de bits): void cvOrS (const CvArr* A. A y C deben ser de 1 canal ‡ Y lógico entre una imagen y un valor constante (a nivel de bits): void cvAndS (const CvArr* A. CvArr* C.y):= A(x.y):= A(x. CV_MINMAX) hace que los píxeles de C vayan entre a y b. CvArr* C. ‡ Pero.y):= A(x.

El umbral se calcula para cada píxel.y) > threshold entonces maxValue sino 0 ‡ La umbralización se hace con un valor constante. CvArr* dst. ‡ Umbralización/binarización de una imagen: void cvThreshold (const CvArr* src. res). int thresholdType) ‡ Umbraliza la imagen según el método dado en thresholdType. scalar2.. CvArr* C. usando una vecindad local (adaptativo).y):= A(x. int cmp_op) C(x. double maxValue. ³<=´} ‡ cmp_op indica el modo de comparación: CV_CMP_EQ (igual). CV_CMP_GE (mayor o igual). ‡ P. double S. scalar1. ³>´.ej.Procesamiento en OpenCV. CV_THRESH_BINARY para binarizar: C(x. ‡ Ver también la función cvInRangeS(img.y):= si A(x. con op  {³=´. double threshold. con 0 ó 255 (todos los bits a 1). ³<´. Para un método más avanzado ver cvAdaptiveThreshold. ‡ Comparación entre una imagen y un valor constante: void cvCmpS (const CvArr* A. . etc. ‡ El resultado es una imagen binaria. CV_CMP_GT (mayor que). ³>=´. y el umbral es threshold.y) op S.

CvArr* C) C(x. CvArr* C) C(x. 255.y):= min {A(x.y).y):= max {A(x. S} ‡ Las imágenes deben ser de un solo canal. ‡ Potencia.y):= A(x. ‡ Máximo entre una imagen y un valor constante: void cvMaxS (const CvArr* A.y):= eA(x./255. exponencial y logaritmo de los píxeles de una imagen: void cvPow (const CvArr* A.y).y):= loge |A(x. S} ‡ Las imágenes deben ser de un solo canal. CvArr* C) (está mal en la ayuda) C(x. double scalar. es conveniente transformar las profundidad a reales de 32 o 64 bits. Transformación de gamma: cvConvertScale(img. double scalar. double p) C(x. CvArr* C.y)p void cvExp (const CvArr* A. 1. 0). gamma). img. . // imr es de profundidad 32F cvPow(imr.y) void cvLog (const CvArr* A. ‡ Mínimo entre una imagen y un valor constante: void cvMinS (const CvArr* A. cvConvertScale(imr. imr. imr. 0).Procesamiento en OpenCV.. CvArr* C) (está mal en la ayuda) C(x.y)| ‡ Para evitar saturación y pérdida de información. ‡ Ejemplo.

‡ Es mucho más adecuada para calcular la media de dos imágenes: cvAddWeighted(im1. im2. 0). // y luego la división por 2? ‡ Suma ponderada de dos imágenes: void cvAddWeighted(CvArr* A. double a. . Por ejemplo. 0).5.5. para obtener la media de dos imágenes. 0.5. 0.y) ‡ Las imágenes deben tener el mismo tamaño (o ROI) y el mismo tipo.y):= a·A(x. double g.y) + b·B(x.5.y)0 entonces C(x. double b. im2. im1.y):= A(x. 0. // ¿Qué pasa si hacemos primero la suma cvAdd(im1.y) + B(x. CvArr* C. CvArr* B. 0). CvArr* C) C(x. const CvArr* mask=0) si mask(x. imr. im1. ‡ Ojo: recordar los problemas de saturación. im2: cvScale(im1. 0. cvScale(im2. imr).y) + g ‡ Las mismas restricciones que antes.Procesamiento en OpenCV. const CvArr* B. Operaciones Binarias ‡ Sumar dos imágenes: void cvAdd (const CvArr* A. im2. 0.

y):= A(x. 32F). const CvArr* B. CvArr* C) C(x. ‡ Igual que antes. const CvArr* B. ‡ Diferencia absoluta entre dos imágenes: void cvAbsDiff (const CvArr* A.y)| ‡ Más adecuada cuando tenemos imágenes sin signo y solo queremos medir diferencias absolutas entre píxeles. Procesamiento en OpenCV.y)0 entonces C(x.y) .y):= |A(x. ‡ Esta operación tiene más sentido cuando se usan tipos con signo (16S.y) .y) ‡ Las imágenes deben tener el mismo tamaño (o ROI) y el mismo tipo.B(x.A. . ‡ Restar dos imágenes: void cvSub (const CvArr* A. const CvArr* mask=0) si mask(x.2. CvArr* C.B(x. tener cuidado con los problemas de saturación. 16F.

y)/B(x.y):= scale*A(x. CvArr* C. im2. im2. imr. en cuyo caso se supone que todos los píxeles son 1. const CvArr* B. ‡ Igual que antes.Procesamiento en OpenCV.y)*scale ‡ El valor scale permite evitar problemas de saturación. imr.y)*B(x. 255.y) ‡ A puede ser nulo. double scale=1) C(x. ‡ Ejemplo: multiplicar dos imágenes de 8 bits: cvMul(im1. double scale=1) C(x. Es más adecuado usar enteros con signo. ./255).0). ‡ Ejemplo: cvDiv(im1. tener cuidado con los problemas de saturación.y):= A(x. ‡ Dividir dos imágenes: void cvDiv (const CvArr* A. CvArr* C. const CvArr* B. 1. ‡ Multiplicar dos imágenes: void cvMul (const CvArr* A.

y):= A(x. a nivel de bits. CvArr* C.y)0 entonces C(x. const CvArr* B. entre dos imágenes: void cvOr (const CvArr* A. al menos alguna de las dos imágenes debería ser binaria (0/255).Procesamiento en OpenCV.y):= A(x.y):= A(x. const CvArr* B. const CvArr* mask=0) si mask(x.y) AND B(x.y) . pero ¿para qué puede valer? ‡ Para que tenga sentido. a nivel de bits. CvArr* C. const CvArr* B.y) ‡ También funciona con números reales. ‡ O lógico. a nivel de bits. ‡ Y lógico. CvArr* C.y)0 entonces C(x.y) ‡ O exclusivo.y) XOR B(x. const CvArr* mask=0) si mask(x. entre dos imágenes: void cvAnd (const CvArr* A.y)0 entonces C(x. entre dos imágenes: void cvXor (const CvArr* A. const CvArr* mask=0) si mask(x.y) OR B(x.

imMin. ³<=´} ‡ Los mismos modos de comparación que cvCmpS. ‡ Mínimo de dos imágenes: void cvMin (const CvArr* A. B(x.y)} ‡ Las imágenes deben tener 1 solo canal.y) op B(x. const CvArr* B.y). ‡ Ver también la función cvInRange(img.y):= A(x. CvArr* C) C(x. B(x. const CvArr* B.y):= max {A(x. ‡ La imagen de salida es binaria 0/255. ³>=´. const CvArr* B. ‡ Comparación de dos imágenes: void cvCmp (const CvArr* A.y):= min {A(x.y)} ‡ Las imágenes deben tener 1 solo canal. ³<´. . Las imágenes deben tener 1 canal. int cmp_op) C(x. imRes). CvArr* C) C(x. ³>´.y). ‡ Máximo de dos imágenes: void cvMax (const CvArr* A. con op  {³=´.Procesamiento en OpenCV. imMax. CvArr* C.y).

val[1]). ‡ Implementación 1.. más lento) y menos recomendable } . B.y))/255 + B(x. ‡ Implementación 2. (~5 veces cvSet2D(R.val[2]). R). pB.val[1]. queremos implementar la operación: R(x.0 CvScalar pA.pB.val[2]./255). #define CM(a. y. porque las operaciones están optimizadas Aunque no del todo correcto. pN= cvGet2D(N. x). x<A->width. 1.pB. y. N). cvMul(A. pR).pN. B. pR.val[0]. pR. for (int y=0.Procesamiento en OpenCV. y<A->height.pB.pN. y.val[0]). pR. ‡ Observar el estilo de programación usando estas funciones. N.val[1]= CM(pA. x). y. x). N.b.y)·(255-N(x. cvMul(B. y++) for (int x= 0.val[0]= CM(pA.y)/255 void Combina (const CvArr* A. pB= cvGet2D(B.val[1]. CvArr* R). modifica sus parámetros de entrada A.n) (a*(255-n)+b*n)/255./255). x. const CvArr* B.y)·N(x. cvAdd(A.val[2]. ‡ Por ejemplo. const CvArr* N. B y N.. pR. Esto es más sencillo y eficiente. pN. x++) { pA= cvGet2D(A.y):= A(x.val[0]. cvNot(N.pN. A. 1.val[2]= Esto es menos eficiente CM(pA.

/255).y)·N(x.y)/255 cvMul(B. B. const(CvArr* src2. 1. scale Optional scale factor A ( x .y))/255 + B(x. N. R void cvMul( const CvArr* src1. B. N). N. y src2 ) The second source array./255). R).y)·(255-N(x. double scale=1 ).y):= A(x. CvArr* dst.Procesamiento en OpenCV. The first source array. cvAdd(A. : dst = The destination array. x src1 . cvMul(A. R(x. cvNot(N. A. 1.

. ‡ Utilizaremos los histogramas de OpenCV. ‡ En OpenCV se define el tipo CvHistogram y las operaciones para manejarlo: cvCreateHist. ‡ Tenemos también una operación de ecualización del histograma: cvEqualizeHist. cvThreshHist. cvQueryHistValue. o LUT). cvGetMinMaxHistValue. ‡ Otra cuestión relacionada son las tablas de transformación (look-up table. cvCalcHist. cvNormalizeHist. cvReleaseHist.Procesamiento en OpenCV. Operaciones con histogramas ‡ Los histogramas se manejan de formas diferentes en IPL y en OpenCV. cvGetHistValue.

32. Normalmente tendremos 1 dimensión (escala de grises). 2 dimensiones (histogramas conjuntos de dos canales) o como mucho 3. Normalmente será una potencia de 2. número de celdas (bins). como 256. será uniforme). ± Para cada dimensión.Procesamiento en OpenCV. Histograma de 1 dimensión y 4 celdas Bin 0 (0-63) Histograma de 2 dimensiones Bin 0 (0-127) Bin 1 (128-255) Bin 1 Bin 2 Bin 3 Bin 0 (0-85) Bin 1 (86-170) Bin 2 (171-255) (64-127) (128-191) (192-255) . 64. ‡ Propiedades de un histograma: ± Número de dimensiones.. en el caso de haber menos celdas que valores (normalmt. ‡ Ejemplos.. ± Rango de valores correspondientes a cada celda.

‡ Crear un histograma: CvHistogram* cvCreateHist (int dims. CV_HIST_ARRAY). Crear un histograma con 1 dimensión y 256 celdas: CvHistogram* hist1. usar siempre CV_HIST_ARRAY. ± ranges: rango asociado a cada celda de cada dimensión. sizes: número de celdas en cada dimensión. Para histogramas uniformes.. es un array de pares (rmin. Si la imagen es de 8 bits y el rango es (0. int type.Procesamiento en OpenCV. uniform: poner a 1 para que el rango de valores en cada celda sea uniforme.. 255). ± ± ± ± . type: tipo. int* sizes.. int celdas= 256. se puede poner simplemente ranges=NULL. hist= cvCreateHist(1. float** ranges=0. . ‡ Ejemplo. rmax) y las celdas se reparten uniformemente este rango. &celdas. int uniform=1) dims: número de dimensiones del histograma.

± mask: máscara sobre la que se calculará el histograma. ‡ Ejemplo. Deben haber tantas como número de dimensiones del histograma. celdas. CV_HIST_ARRAY). int celdas[2]= {32. CvHistogram* hist. const CvArr* mask=0) ± img: array de imágenes de 1 canal.Procesamiento en OpenCV. . hist2= cvCreateHist(2. int acumulate=0. Crear un histograma con 2 dimensiones y 32 celdas en cada dimensión: CvHistogram* hist2. ± acumulate: si se pone a TRUE. 32}. Esto permite obtener histogramas acumulados de varias imágenes. no borra el contenido anterior de las celdas. ‡ Liberar la memoria ocupada por un histograma: void cvReleaseHist (CvHistogram** hist) ‡ Calcular el histograma de una imagen: void cvCalcHist (IplImage** img.

8. 8. ‡ Ojo. ‡ Esta forma tan particular de calcular el histograma. planos[0]= cvCreateImage(cvGetSize(img). // Ver abajo cvCvtColor(img. 0). hace que sea necesario separar los canales de una imagen. gris. CV_RGB2GRAY). planos+1. .Procesamiento en OpenCV. Calcular el histograma bidimensional de los canales R y G: IplImage *planos[3]. ‡ Ejemplo 1. cvCalcHist(planos. 1). 8. cvSplit(src. 1). planos[2]= cvCreateImage(cvGetSize(img). Calcular el histograma unidimensional del nivel de gris: IplImage *gris= cvCreateImage(cvGetSize(img). 1). planos+2. ‡ Ejemplo 2. porque la original no funciona bien si no hay un ROI establecido. hist1. 8. 1). cvCalcHist(&gris. hist2. planos[1]= cvCreateImage(cvGetSize(img). 0). planos+0. la función cvGetSize está redefinida en HighGUI2. 0).

± De forma similar para histogramas 3D y ND.Procesamiento global en OpenCV. Esta función será útil si lo que queremos es poder modificar a mano el valor de las celdas. float * cvGetHistValue_2D (CvHistogram*hist.. int idx0) ± Para el caso de histogramas unidimensionales. ‡ Obtener un puntero a una celda del histograma: float * cvGetHistValue_1D (CvHistogram*hist. int idx0. ± Devuelve un puntero. int idx1) ± Para el caso de histogramas bidimensionales.. . ± De forma similar para histogramas 3D y ND. ‡ Una vez calculado. int idx0. consultar las celdas del histograma: float cvQueryHistValue_1D (CvHistogram*hist. ± Realmente no es una función sino un macro. int idx1) ± Para el caso de histogramas bidimensionales. int idx0) ± Para el caso de histogramas unidimensionales. float cvQueryHistValue_2D (CvHistogram*hist.

double factor) ± Hace que la suma de todas las celdas del histograma sea factor. CvArr* dst) ± Ojo: la imagen debe ser de 1 solo canal y 8U. ‡ Obtener máximo y mínimo de un histograma: void cvGetMinMaxHistValue (const CvHistogram* hist. No se puede usar para hacer una ecualización conjunta de RGB. ‡ Normalizar un histograma: void cvNormalizeHist (CvHistogram* hist. el máximo (maxVal). int* minIdx =0. el índice de la celda mínima (minIdx) y máxima (maxIdx). ± Interesante.ej. p. ± Puede ser interesante para visualizar o comparar histogramas. float* minVal. calcula el mínimo (minVal). int* maxIdx =0) ± Dado el histograma.. ‡ Existen otras operaciones interesantes de consulta y manipulación de histogramas. ‡ Ecualizar el histograma de una imagen: void cvEqualizeHist (const CvArr* src. . para escalar todas las celdas entre 0 y 1.Procesamiento en OpenCV. float* maxVal.

‡ Operaciones Booleanas AND.Primer Previo ‡ Proyecto realizado utilizando las librerías de OpenCV que implemente las siguientes funciones: ‡ Histograma de una imagen. ‡ Umbralización. OR. resta. multiplicación de imágenes. Deben . ‡ Suma. NOT ‡ Calculo de Fondo de una imagen por combinación utilizando media.

5. Calcular la diferencia: D = abs(M-A). Obtener el modelo de fondo M. U = umbralizar(D. Umbralizar la imagen con un valor adecuado. 6. Sea F el nuevo fondo. ‡ Proceso.2. Para cada imagen A del vídeo. R:= (F AND NOT U) OR (A AND U) M A D U F R ¿Cómo arreglar eso? . 4. 3.4. Combinación de imágenes. x). 1. 2.

4.y)+B(x. ‡ Para evitar la saturación se puede usar la media. y):= (A(x.y))/2 A R B ‡ Significado: las imágenes son semitransparentes (al 50%).2. . Media de 2 imágenes: R(x. Combinación de imágenes.

comprobar si su valor está entre el máximo y el mínimo. Fondo mínimo Fondo máximo ‡ Dada una imagen nueva. Combinación de imágenes. Si lo está: fondo.2. si no lo está: objeto. ‡ Ejemplo. .4. Una alternativa para crear modelos de fondo es usar máximos y mínimos. para cada píxel. En lugar de tener media y varianza. tenemos máximo y mínimo del fondo en cada píxel.

Sign up to vote on this title
UsefulNot useful