Notas de Opencv-C++ (2): operaciones matriciales de opencv

Directorio de artículos

Creación e inicialización

Las operaciones con matrices en OpenCV son muy importantes. Este artículo resume la creación, la inicialización y las operaciones básicas con matrices de las matrices, y brinda códigos de muestra. Los contenidos principales incluyen:

1.1 Tipos de datos

Para establecer una matriz, debe especificar el tipo de datos almacenados en la matriz.Varios tipos de datos comúnmente utilizados en el procesamiento de imágenes son los siguientes:

CV_8UC1// 8位无符号单通道
CV_8UC3// 8位无符号3通道
CV_8UC4
CV_32FC1// 32位浮点型单通道
CV_32FC3// 32位浮点型3通道
CV_32FC4
 

Incluye profundidad de bits de datos de 8 bits, 32 bits, tipo de datos U: uchar, F: tipo flotante y número de canales C1: canal único, C3: tres canales, C4: cuatro canales.

1.2 Método básico

Podemos crear una matriz tipo Mat cargando una imagen, por supuesto, también podemos crear una matriz directamente manualmente, el método básico es especificar el tamaño de la matriz y el tipo de datos:

// 基本方法
	cv::Mat a(cv::Size(5,5),CV_8UC1); // 单通道
	cv::Mat b = cv::Mat(cv::Size(5,5),CV_8UC3); //3通道每个矩阵元素包含3个uchar值
	cout<<"a  = "<<endl<<a<<endl<<endl;
	cout<<"b  = "<<endl<<b<<endl<<endl;
	system("pause");`

inserte la descripción de la imagen aquí
En una matriz de 3 canales, un elemento de matriz contiene 3 variables.

1.3 Método de inicialización

El método anterior no inicializa los datos de la matriz, por lo que aparecerán valores aleatorios. Si desea evitar esta situación, puede utilizar varios métodos de inicialización de la clase Mat para crear matrices:

// 初始化方法 	
cv::Mat mz = cv::Mat::zeros(cv::Size(5,5),CV_8UC1); 
// 全零矩阵 	
cv::Mat mo = cv::Mat::ones(cv::Size(5,5),CV_8UC1); 
 // 全1矩阵 	
 cv::Mat me = cv::Mat::eye(cv::Size(5,5),CV_32FC1);  
 // 对角线为1的对角矩阵 
 	cout<<"mz = "<<endl<<mz<<endl<<endl; 	
 	cout<<"mo = "<<endl<<mo<<endl<<endl; 	
 	cout<<"me = "<<endl<<me<<endl<<endl;

resultado de la operación:
inserte la descripción de la imagen aquí

Adición y sustracción de matrices

Podemos usar los símbolos "+" y "-" para la suma y resta de matrices.

cv::Mat a= Mat::eye(Size(3,2), CV_32F);
cv::Mat b= Mat::ones(Size(3,2), CV_32F);
cv::Mat c= a+b;
cv::Mat d= a-b;

inserte la descripción de la imagen aquí

multiplicación de matrices

Use "*" para calcular la multiplicación de matriz y escalar, y la multiplicación de matriz y matriz (debe cumplir con las reglas correspondientes para el número de filas y columnas de la multiplicación de matriz)

Mat m1= Mat::eye(2,3, CV_32F); //使用cv命名空间可省略cv::前缀,下同
	Mat m2= Mat::ones(3,2, CV_32F);
	cout<<"m1  = "<<endl<<m1<<endl<<endl;
	cout<<"m2  = "<<endl<<m2<<endl<<endl;
	// Scalar by matrix
	cout << "\nm1.*2 = \n" << m1*2 << endl;
	// matrix per element multiplication
	cout << "\n(m1+2).*(m1+3) = \n" << (m1+1).mul(m1+3) << endl;
	// Matrix multiplication
	cout << "\nm1*m2 = \n" << m1*m2 << endl;

inserte la descripción de la imagen aquí

Transposición de matriz

La transposición de matrices consiste en invertir el orden de las filas y columnas de la matriz (la i-ésima fila se convierte en la i-ésima columna) para formar una nueva matriz. OpenCV se implementa a través de la función t() de la clase Mat.
// Transponer

Mat m1= Mat::eye(2,3, CV_32F);	
Mat m1t = m1.t();
cout<<"m1  = "<<endl<<m1<<endl<<endl;
cout<<"m1t  = "<<endl<<m1t<<endl<<endl;
system("pause");

resultado de la operación:
inserte la descripción de la imagen aquí

inversión de matriz

La matriz inversa aparece a menudo en algunos algoritmos y se implementa mediante el método inv() de la clase Mat en OpenCV.

// 求逆
	Mat meinv = me.inv();
	cout<<"me  = "<<endl<<me<<endl<<endl;
	cout<<"meinv = "<<endl<<meinv<<endl<<endl;
	system("pause");

inserte la descripción de la imagen aquí
La inversa de la matriz identidad es ella misma.

El número de elementos distintos de cero en la matriz.

Calcular el píxel o el área de un objeto a menudo requiere la cantidad de elementos distintos de cero en la matriz de cálculo, que se implementa en OpenCV mediante la función countNonZero().
// número de elementos distintos de cero

int nonZerosNum = countNonZero(me); // me es la matriz o imagen de entrada
cout<<"me = "<<endl<<me<<endl;
el número de elementos distintos de cero en cout<<"me="< <nonZerosNum< <endl<<endl;
system("pause");

resultado de la operación:
inserte la descripción de la imagen aquí

Desviación estándar y media de la matriz

OpenCV proporciona funciones de cálculo de desviación estándar y media de matriz, que se pueden implementar mediante la función meanStdDev(src, mean, stddev) Parámetros
src
: matriz de entrada o imagen
media: media, OutputArray
stddev: desviación estándar, OutputArray

 // 均值方差
	Mat mean;
	Mat stddev;
	meanStdDev(me, mean, stddev); //me为前文定义的5×5对角阵
	cout<<"mean = "<<mean<<endl;
	cout<<"stddev = "<<stddev<<endl;
	system("pause");

inserte la descripción de la imagen aquí
Cabe señalar que si src es una imagen multicanal o una matriz multidimensional, la función calcula la media y la desviación estándar de diferentes canales respectivamente, por lo que los valores devueltos mean y stddev son vectores de dimensiones correspondientes.

Mat mean3;
	Mat stddev3;
	Mat m3(cv::Size(5,5),CV_8UC3,Scalar(255,200,100));
	cout<<"m3  = "<<endl<<m3<<endl<<endl;
	meanStdDev(m3, mean3, stddev3);
	cout<<"mean3 = "<<mean3<<endl;
	cout<<"stddev3 = "<<stddev3<<endl;
	system("pause");

Resultado de la operación de matriz multicanal:
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Posición y extremo global de la matriz

求输入矩阵的全局最大最小值及其位置,可使用函数:
void minMaxLoc(InputArray src, CV_OUT double* minVal,
                           CV_OUT double* maxVal=0, CV_OUT Point* minLoc=0,
                           CV_OUT Point* maxLoc=0, InputArray mask=noArray());
                           参数:

 

src – 输入单通道矩阵(图像).
minVal – 指向最小值的指针, 如果未指定则使用NULL
maxVal – 指向最大值的指针, 如果未指定则使用NULL
minLoc – 指向最小值位置(2维情况)的指针, 如果未指定则使用NULL
maxLoc – 指向最大值位置(2维情况)的指针, 如果未指定则使用NULL
mask – 可选的蒙版,用于选择待处理子区域
 

// 求极值 最大、最小值及其位置
	Mat img = imread("Lena.jpg",0);
	imshow("original image",img);
 
	double minVal=0,maxVal=0;
	cv::Point minPt, maxPt;
	minMaxLoc(img,&minVal,&maxVal,&minPt,&maxPt);
	cout<<"min value  = "<<minVal<<endl;
	cout<<"max value  = "<<maxVal<<endl;
	cout<<"minPt = ("<<minPt.x<<","<<minPt.y<<")"<<endl;
	cout<<"maxPt = ("<<maxPt.x<<","<<maxPt.y<<")"<<endl;
	cout<<endl;
 
	cv::Rect rectMin(minPt.x-10,minPt.y-10,20,20);
	cv::Rect rectMax(maxPt.x-10,maxPt.y-10,20,20);
 
	cv::rectangle(img,rectMin,cv::Scalar(200),2);
	cv::rectangle(img,rectMax,cv::Scalar(255),2);
 
	imshow("image with min max location",img);
	cv::waitKey();

resultado de la operación:
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Multiplicación de matrices generales GEMM

void cvGEMM( const CvArr* src1, const CvArr* src2, doble alfa,
const CvArr* src3, doble beta, CvArr* dst, int tABC=0 );
#define cvMatMulAdd( src1, src2, src3, dst ) cvGEMM( src1, o
_
_
_
_
_
_
_ NULL si no hay compensación.
dst
matriz de salida
tABC
Indicador de operación T, que puede ser 0 o una combinación de los valores enumerados a continuación:
CV_GEMM_A_T - transponer src1
CV_GEMM_B_T - transponer src2
CV_GEMM_C_T - transponer src3
Por ejemplo, CV_GEMM_A_T+CV_GEMM_C_T corresponde a la función
alfa src1T src2 + beta*src3T
Ejecución de cvGEMM Multiplicación general de matrices:

dst = alpha*op(src1) op(src2) + beta op(src3), donde op(X) es X o XT
Todas las matrices deben tener el mismo tipo de datos y tamaño de matriz coordinado. Admite matrices de punto flotante reales o matrices de punto flotante complejas.

Transform realiza una transformación de matriz en cada elemento de la matriz

void cvTransform( const CvArr* src, CvArr* dst, const CvMat* transmat, const CvMat* shiftvec=NULL );
src
matriz de entrada
dst
matriz de salida
transmat
matriz de transformación
shiftvec función
de vector de desplazamiento opcional
cvTransform realiza la matriz en cada elemento de la matriz src Transformar y almacenar el resultado en dst:

dst(I)=transmat*src(I) + shiftvec
o

dst(I)k=sumj(transmat(k,j)*src(I)j) + shiftvec(k) Cada
elemento de la matriz de N-canales src se considera como un vector de N-elementos, usando un M×N El la matriz de transformación transmat y el vector de desplazamiento shiftvec lo transforman en un elemento de una matriz de canales M dst. Aquí puede optar por incrustar el vector de compensación shiftvec en transmat. En este caso, transmat debe ser una matriz de M × N + 1, y la columna más a la derecha se considera como el vector de compensación.

Las matrices de entrada y salida deben tener la misma profundidad y el mismo tamaño o tamaño de ROI. transmat y shiftvec deberían ser matrices reales de punto flotante.

Esta función se puede utilizar para la transformación geométrica del conjunto de puntos ND, la transformación del espacio de color lineal arbitrario, la transformación del canal, etc.

MulTransposed Calcula el producto de una matriz y la transposición de una matriz

void cvMulTransposed( const CvArr* src, CvArr* dst, int order, const CvArr* delta=NULL );
src
matriz de entrada
dst
destino matriz
orden
multiplicación orden
delta
una matriz opcional para restar de src antes de la multiplicación.
La función cvMulTransposed calcula el producto de src y su transpuesta.

Fórmula de evaluación de funciones:

si orden=0

dst=(src-delta)*(src-delta)T
más

dst=(origen-delta)T*(origen-delta)

Trace devuelve la traza de la matriz.

CvScalar cvTrace( const CvArr* mat );
mat
matriz de entrada
La función cvTrace devuelve la suma de los elementos diagonales de la matriz mat.

tr(origen) = ∑ mat(i,i)
i

Transponer la transpuesta de la matriz

void cvTranspose( const CvArr* src, CvArr* dst );
#define cvT cvTranspose
src
matriz de entrada
dst
matriz objetivo
La función cvTranspose busca la transposición de la matriz src:

dst(i,j)=src(j,i)
Tenga en cuenta que si es una matriz compleja, no se obtendrá el conjugado del número complejo. La conjugación debe ser independiente: consulte el código de ejemplo de cvXorS.

Det devuelve el valor determinante de la matriz.

double cvDet( const CvArr* mat );
mat
matriz de entrada
La función cvDet devuelve el valor determinante de la matriz cuadrada mat. Calcule directamente para matrices pequeñas y utilice el método de eliminación gaussiana (GAUSSIAN) para matrices grandes. Para una matriz simétrica positivamente determinada, también puede usar la función SVD, U=V=NULL, y luego usar el producto de los elementos diagonales de w para calcular el determinante.

Invert encuentra la inversa o pseudoinversa de una matriz

double cvInvert( const CvArr* src, CvArr* dst, int method=CV_LU );
#define cvInv cvInvert
src
input matrix
dst
target matrix
method
método de inversión:
CV_LU - Método de eliminación gaussiana para una selección de pivote óptima
CV_SVD - Método de descomposición de valores singulares (SVD)
CV_SVD_SYM - Método SVD para matrices simétricas definidas positivas
La función cvInvert invierte la matriz src y almacena el resultado en dst.

Si es el método LU, la función devuelve el valor determinante de src (src debe ser una matriz cuadrada). Si es 0, la matriz no se invierte y dst se llena con ceros.

Si el método SVD, la función devuelve el recíproco del número de condición de src (la proporción del valor singular más pequeño al valor singular más grande), y devuelve 0 si src es todo 0. Si src es singular, el método SVD calcula una matriz pseudo-inversa.

Resolver resuelve problemas de sistemas lineales o mínimos cuadrados

int cvSolve( const CvArr* src1, const CvArr* src2, CvArr* dst, int method=CV_LU );

src1 matriz de entrada
src2 parte derecha del sistema lineal
dst método de solución de salida

Solución (inversión de matriz) :
CV_LU - Eliminación gaussiana para selección de pivote óptima
CV_SVD - Descomposición en valores singulares (SVD)
CV_SVD_SYM - Método SVD para matrices simétricas definidas positivas
Función cvSolve para sistemas lineales o mínimos cuadrados (este último se puede resolver mediante el método SVD):

/mbox{dst} = /arg /min_X |/mbox{src1}/cdot X-/mbox{src2}|
si usa el método CV_LU. La función devuelve 1 si src1 no es singular y 0 en caso contrario, en cuyo caso dst no es válido.

SVD Descomposición en valores singulares de matrices reales de punto flotante

void cvSVD( CvArr* A, CvArr* W, CvArr* U=NULL, CvArr* V=NULL, int flags=0 );

Matriz de entrada AM×N W Matriz de valor singular resultante (M×N o N×N) o vector (N×1) U Matriz ortogonal izquierda opcional (M×M o M×N) Si CV_SVD_U_T es Especifica que el número
de las filas y columnas mencionadas anteriormente deben intercambiarse. V matriz ortogonal derecha opcional (N×N)

banderas
bandera de operación, puede ser 0 o una combinación de los siguientes valores:
CV_SVD_MODIFY_A La matriz src1 puede ser modificada por operación. De esta manera, la velocidad de procesamiento será más rápida.
CV_SVD_U_T significa que se devolverá la matriz transpuesta U, especificar este indicador acelerará el procesamiento.
CV_SVD_V_T significa que se devolverá la matriz transpuesta V, especificar este indicador acelerará el procesamiento.

La función cvSVD descompone la matriz A en un producto de una matriz diagonal y dos matrices ortogonales:

/matemáticas{/it A=UWV^T}

Aquí W es una matriz diagonal de valores singulares, que se puede codificar como un vector unidimensional de valores singulares, así como U y V. Todos los valores singulares son no negativos y se almacenan en orden descendente. (U y V
también se almacenan en consecuencia).

El algoritmo SVD ha sido muy estable en el procesamiento numérico y sus aplicaciones típicas incluyen:

Resuelve exactamente problemas de valores propios cuando A es una matriz cuadrada, simétrica y positiva, por ejemplo, cuando A es una matriz de covarianza. En este caso, W será un vector de valores propios, y
U=V es el vector propio de la matriz (por lo tanto, solo es necesario calcular uno de U y V cuando es necesario calcular los vectores propios). Resuelve exactamente sistemas lineales mal acondicionados.
Solución de mínimos cuadrados de sistemas lineales sobredeterminados. Tanto el problema anterior como este problema pueden usar el método cvSolve especificando CV_SVD.
Cálculo preciso de las diferentes características de las matrices, como el rango (número de valores singulares distintos de cero), el número de condición (relación entre los valores singulares más grandes y los más pequeños), el valor determinante (el valor absoluto del determinante es igual al producto de los valores singulares)
. valores no requieren el cálculo de las matrices U y V.

Algoritmo de sustitución hacia atrás de valor singular SVBkSb (sustitución hacia atrás)

void cvSVBkSb( const CvArr* W, const CvArr* U, const CvArr* V,
const CvArr* B, CvArr* X, int flags );
W
Matriz de valor singular o vector
U
Matriz ortogonal izquierda (posiblemente transpuesta)
V
Matriz ortogonal derecha (posiblemente transpuesta)
B
La matriz multiplicativa de la pseudo-inversa de la matriz original A. Este es un parámetro opcional. Si se omite, se supone que es una matriz identidad de tamaño adecuado (así, x será la reconstrucción de la pseudo-inversa de A).
Matriz de destino X : la bandera de operación de banderas
del resultado del algoritmo de sustitución inversa de valor singular , que es la misma que la bandera del cvSVD que acabamos de analizar. La función cvSVBkSb calcula la sustitución hacia atrás para la matriz A y la matriz B descompuestas (ver descripción de cvSVD):


X=V W-1 UT*B
aquí

W-1(i,i)=1/W(i,i) si W(i,i) > epsilon•sumiW(i,i), de lo contrario: 0. epsilon es un número
pequeño
. Esta función y la función cvSVD se usan para ejecutar cvInvert y cvSolve. La razón para usar estas funciones (svd y bksb) es que la función principal (de bajo nivel) puede evitar la matriz temporal asignada internamente en el cálculo de la función avanzada (inv y resolver).

EigenVV calcula los valores propios y los vectores propios de una matriz simétrica

void cvEigenVV( CvArr* mat, CvArr* evects, CvArr* evals, double eps=0 );
mat
entrada matriz cuadrada simétrica. cambiará durante el procesamiento.
Efectúa
la matriz de salida del vector propio, almacena la matriz de salida del valor propio
evals en orden descendente continuamente (por supuesto, la clasificación de los valores propios y los vectores propios está sincronizada). Precisión de la diagonalización de eps (típicamente, DBL_EPSILON=≈10-15 es suficiente). La función cvEigenVV calcula los autovalores y autovectores de la matriz A:



mat*evects(i,:)' = evals(i)*evects(i,:)' (notación en MATLAB) Los
datos de la matriz A serán modificados por esta función.

Actualmente esta función es más lenta y menos precisa que la función cvSVD.Si se sabe que A es definida positiva (por ejemplo, es una matriz de covarianza), generalmente se entrega a la función cvSVD para calcular sus valores propios y vectores propios. , especialmente sin la necesidad de calcular los vectores propios

CalcCovarMatrix Calcula la matriz de covarianza de una colección de vectores

void cvCalcCovarMatrix( const CvArr** vects, int count, CvArr* cov_mat, CvArr* avg, int flags );
vects
vector de entrada. Deben tener el mismo tipo y tamaño de datos. Los vectores no tienen que ser unidimensionales, también pueden ser bidimensionales (por ejemplo, imágenes) y así sucesivamente.
cuente
el número de vectores de entrada
cov_mat
genera la matriz de covarianza, que es una matriz cuadrada de tipo punto flotante.
matriz de entrada o salida promedio
(dependiendo de las banderas ") - Vector promedio de vectores de entrada.
banderas banderas
de operación, una combinación de los siguientes valores:
CV_COVAR_SCRAMBLED - la matriz de covarianza de salida se calcula de la siguiente manera:
scale * [vects[0] − avg,vects[1] − avg,…]T * [vects[0] − avg,vects[ 1] − avg,…], es decir, la matriz de covarianza es count×count. Una matriz tan inusual se usa en métodos PCA rápidos para un conjunto de vectores grandes (por ejemplo, EigenFaces técnica de reconocimiento facial). Los valores propios de esta matriz codificada ("codificados") coincidirán con los valores propios de la matriz de covarianza verdadera, y los vectores propios verdaderos se pueden calcular fácilmente a partir de los vectores propios de la matriz de covarianza codificada ("codificados").
CV_COVAR_NORMAL: la matriz de covarianza de salida se calcula como:
scale * [vects[0] − avg,vects[1] − avg,…] * [vects[0] − avg,vects[1] − avg,…]T, es decir, cov_mat será uno y cada uno. matriz de covarianza con el mismo tamaño lineal en el número de elementos de los vectores de entrada. CV_COVAR_SCRAMBLED y CV_COVAR_NORMAL solo pueden especificar uno de ellos al mismo tiempo.
CV_COVAR_USE_AVG: si se especifica este indicador, la función no calculará el promedio a partir del vector de entrada, sino que utilizará el vector promedio anterior, lo cual es útil si el promedio se calculó de alguna manera. O si la matriz de covarianza se calcula parcialmente, en este caso, avg no es el promedio de un subconjunto de los vectores de entrada, sino el vector promedio de todo el conjunto.
CV_COVAR_SCALE: si se especifica este indicador, se escala la matriz de covarianza. la matriz de covariación está escalada, en modo "normal" el escalado es 1./cuenta, en modo "codificado" el escalado es el recíproco de la suma de los elementos de cada vector de entrada. De forma predeterminada (si no se especifica ninguna bandera), la matriz de covarianza no está escalada (escala = 1).
La función cvCalcCovarMatrix calcula la matriz de covarianza y el vector medio de los vectores de entrada. Esta función se puede utilizar en el análisis de componentes principales (PCA) y el vector de comparación de la distancia de Mahalanobis (distancia de Mahalanobis), etc.

Mahalanobis calcula la distancia de Mahalanobis entre dos vectores (distancia de Mahalanobis)

double cvMahalanobis( const CvArr* vec1, const CvArr* vec2, CvArr* mat );
vec1
el primer vector de entrada unidimensional
vec2
el segundo vector de entrada unidimensional
mat
La función de matriz inversa de la matriz de covarianza
cvMahalanobis calcula la diferencia entre dos vectores Distancia ponderada, el resultado devuelto es:

d(vec1,vec2)=/sqrt{ /sum_{i,j} /{mat(i,j) (vec1(i)-vec2(i)) (vec1(j)-vec2(j))/} }
La matriz de covarianza se puede calcular con la función cvCalcCovarMatrix y la matriz inversa se puede calcular con la función cvInvert (el método CV_SVD es una mejor opción, porque la matriz puede ser singular).

CalcPCA realiza la transformación PCA en un conjunto de vectores

void cvCalcPCA( const CvArr* data, CvArr* avg,
CvArr* eigenvalues, CvArr* eigenvectors, int flags);
datos de entrada de datos, cada vector es un vector de
una sola fila (CV_PCA_DATA_AS_ROW) o un vector de una sola columna (CV_PCA_DATA_AS_COL). , en la función Calculada internamente o proporcionada por la persona que llama para proporcionar los valores propios de la salida de la matriz de covarianza por valores propios Los vectores propios (es decir, los componentes principales) de la salida de la matriz de covarianza por vectores propios, cada vector tiene una fila de banderas banderas de operación, que pueden ser una combinación de los siguientes métodos: CV_PCA_DATA_AS_ROW: los vectores se almacenan en filas (es decir, cualquier vector se almacena continuamente) CV_PCA_DATA_AS_COL: los vectores se almacenan en columnas (es decir, el valor de un almacenado continuamente) (los dos signos anteriores se excluyen mutuamente Exclusivo) CV_PCA_USE_AVG: use el valor promedio precalculado . Esta función realiza la transformación PCA en un conjunto de vectores. Primero calcula la matriz de covarianza usando cvCalcCovarMatrix y luego calcula los valores propios y vectores propios de la matriz de covarianza Los valores propios de salida /vectores propios El número es menor o igual que MIN(filas(datos), cols(datos)).












ProjectPCA proyecta un vector en un subespacio

void cvProjectPCA( const CvArr* data, const CvArr* avg,
const CvArr* eigenvectors, CvArr* result )
datos de entrada de datos, cada vector puede ser un vector promedio promedio
de una sola fila o de una sola columna . O bien es un vector de una sola fila lo que significa que los datos de entrada están en filas Los datos se almacenan en forma de un vector de una sola columna, lo que significa que el vector de entrada se almacena en una columna.vectores propios vectores propios (componentes principales ) , cada vector tiene una fila. El resultado matriz de coeficiente de descomposición de salida, el número de filas de la matriz debe ser el mismo que El número de vectores de entrada es igual, y el número de columnas de la matriz debe ser menor que el número de filas del vector propio. Esta función proyecta la entrada vectores a un sistema ortogonal (vectores propios).Antes de calcular el producto escalar, los vectores de entrada se restan del vector medio:






result(i,:)=(data(i,:)-avg)*eigenvectors' // para diseño CV_PCA_DATA_AS_ROW.

[editar]
BackProjectPCA
reconstruye el vector original según los coeficientes de proyección

void cvBackProjectPCA( const CvArr* proj, const CvArr* avg,
const CvArr* eigenvects, CvArr* result ); datos de entrada del
proyecto
, consistentes con el formato del vector promedio cvProjectPCA
avg
. Si es un vector de una sola fila, significa que la salida El vector es De lo contrario, es un vector de una sola columna, luego el vector de salida se almacena en una columna.Vectores
propiosVectores propios
(componentes principales), cada vector tiene una fila.La matriz reconstruida generada por la función
de resultado reconstruye el original de acuerdo con la proyección. vector coeficiente:

result(i,:)=proj(i,:)*eigenvectors + avg // para diseño CV_PCA_DATA_AS_ROW

adjunto

operación matricial

Asignar espacio de matriz libre

Resumen:
OpenCV tiene funciones de lenguaje C para operaciones matriciales. Muchos otros métodos proporcionan interfaces C++ más convenientes con la misma eficiencia que OpenCV. OpenCV maneja vectores
como matrices 1D.
La matriz se almacena en filas, cada fila tiene 4 bytes de corrección.

Asignar espacio de matriz:
CvMat* cvCreateMat(int filas, int cols, int tipo);

    type: 矩阵元素类型. 格式为CV_<bit_depth>(S|U|F)C<number_of_channels>.  
    例如: CV_8UC1 表示8位无符号单通道矩阵, CV_32SC2表示32位有符号双通道矩阵.

    例程:
    CvMat* M = cvCreateMat(4,4,CV_32FC1);

Liberar espacio de matriz:
CvMat* M = cvCreateMat(4,4,CV_32FC1);
cvReleaseMat(&M);

Copiar matriz:
CvMat* M1 = cvCreateMat(4,4,CV_32FC1),
CvMat* M2,
M2=cvCloneMat(M1);

Inicializar matriz:
doble a[] = { 1, 2, 3, 4, 5, 6
, 7, 8,
9, 10, 11, 12 };

CvMat Ma=cvMat(3, 4, CV_64FC1, a);
Otra forma:

Cv Mat Ma;
cvInitMatHeader(&Ma, 3, 4, CV_64FC1, a);

Inicialice la matriz como una matriz de identidad:
CvMat* M = cvCreateMat(4,4,CV_32FC1);
cvSetIdentity(M); // Parece que hay un problema aquí, sin éxito

Elementos de la matriz de acceso

Suponga que necesita acceder al (i,j)-ésimo elemento de una matriz bidimensional de punto flotante.

Acceso indirecto a los elementos de la matriz:
cvmSet(M,i,j,2.0); // Establecer M(i,j)
t = cvmGet(M,i,j); // Obtener M(i,j)

Acceso directo, asumiendo una alineación de 4 bytes:
CvMat* M = cvCreateMat(4,4,CV_32FC1),
int n = M->cols,
float *data = M->data.fl;

datos[i*n+j] = 3.0;

Acceso directo, byte de corrección arbitrario:
CvMat* M = cvCreateMat(4,4,CV_32FC1);
int step = M->step/sizeof(float);
float *data = M->data.fl;

(datos+i*paso)[j] = 3,0;

Acceso directo a un elemento de matriz inicializado:
double a[16];
CvMat Ma = cvMat(3, 4, CV_64FC1, a);
a[i*4+j] = 2.0; // Ma(i,j)=2.0 ;

Operaciones matriciales/vectoriales

operación matriz-matriz:
CvMat *Ma, *Mb, Mc;
cvAdd(Ma, Mb, Mc); // Ma+Mb -> Mc
cvSub(Ma, Mb, Mc); // Ma-Mb -> Mc
cvMatMul(Ma, Mb, Mc); // Ma
Mb -> Mc

按电影的电影的operación matricial:
CvMat *Ma, *Mb, *Mc;
cvMul(Ma, Mb, Mc); // Ma.*Mb -> Mc
cvDiv(Ma, Mb, Mc); // Ma./Mb -> Mc
cvAddS(Ma, cvScalar(-10.0), Mc); // Ma.-10 -> Mc

Producto vectorial:
doble va[] = {1, 2, 3},
doble vb[] = {0, 0, 1},
doble vc[3];

CvMat Va=cvMat(3, 1, CV_64FC1, va);
CvMat Vb=cvMat(3, 1, CV_64FC1, vb);
CvMat Vc=cvMat(3, 1, CV_64FC1, vc);

double res=cvDotProduct(&Va,&Vb); // producto punto: Va . Vb -> res cvCrossProduct
(&Va, &Vb, &Vc); // producto vectorial: Va x Vb -> Vc
end{verbatim}
Nota Va, Vb, Vc debe tener el mismo número de elementos vectoriales en el producto vectorial.

Operación de matriz única:
CvMat *Ma, *Mb;
cvTranspose(Ma, Mb); // transpose(Ma) -> Mb (no se puede transponer a sí mismo)
CvScalar t = cvTrace(Ma); // trace(Ma) - > t. val[0]
doble d = cvDet(Ma); // det(Ma) -> d
cvInvert(Ma, Mb); // inv(Ma) -> Mb

Solución de sistema lineal no homogéneo:
CvMat* A = cvCreateMat(3,3,CV_32FC1);
CvMat* x = cvCreateMat(3,1,CV_32FC1);
CvMat* b = cvCreateMat(3,1,CV_32FC1);
cvSolve(&A, &b, &x); // resuelve (Ax=b) para x

Análisis de valores propios (para matrices simétricas):
CvMat* A = cvCreateMat(3,3,CV_32FC1);
CvMat* E = cvCreateMat(3,3,CV_32FC1);
CvMat* l = cvCreateMat(3,1,CV_32FC1);
cvEigenVV( &A , &E, &l); // l = valores propios de A (en orden descendente)
// E = vectores propios correspondientes (por fila)

Descomposición en valores singulares SVD:
CvMat* A = cvCreateMat(3,3,CV_32FC1);
CvMat* U = cvCreateMat(3,3,CV_32FC1);
CvMat* D = cvCreateMat(3,3,CV_32FC1);
CvMat* V = cvCreateMat( 3,3,CV_32FC1);
cvSVD(A, D, U, V, CV_SVD_U_T|CV_SVD_V_T); // La
etiqueta A = UDV^T hace transponer U y V al regresar (si no hay etiqueta de transposición, no hay problema éxito !!!).

manipulación de secuencias de vídeo

Toma un cuadro de una secuencia de video

OpenCV admite la captura de imágenes de la cámara web o archivos de video (AVI).

Obtenga la inicialización de la cámara:
CvCapture* capture = cvCaptureFromCAM(0); // capture from video device #0

Obtenga la inicialización del archivo de video:
CvCapture* capture = cvCaptureFromAVI(“infile.avi”);

Toma un cuadro:
IplImage* img = 0;
if(!cvGrabFrame(capture)){ // toma un cuadro
printf("No se pudo tomar un cuadro/n/7");
exit(0);
}
img=cvRetrieveFrame(captura ); // Restaurar imágenes de fotogramas capturados
Para adquirir imágenes de varias cámaras al mismo tiempo, primero capture un fotograma de cada cámara. Restaure las imágenes de fotogramas después de completar todas las acciones de captura.

Libere la fuente de captura:
cvReleaseCapture(&capture);
tenga en cuenta que la imagen capturada por el dispositivo se asigna y libera automáticamente mediante la función de captura. No intente liberarla usted mismo.

Obtener/establecer información del marco

Obtenga las propiedades del dispositivo:
cvQueryFrame(capture); // esta llamada es necesaria para obtener
// las propiedades de captura correctas
int frameH = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
int frameW = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_W IDTH);
int fps = (int) cvGetCaptureProperty(capturar, CV_CAP_PROP_FPS);
int numFrames = (int) cvGetCaptureProperty(capturar, CV_CAP_PROP_FRAME_COUNT);
Todos los números de fotogramas parecen estar relacionados únicamente con archivos de video. ¡Error cuando se usa una cámara, extraño!

Obtenga información del cuadro:
float posMsec = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_MSEC);
int posFrames = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES);
float posRatio = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_AVI_RATIO) ;
Obtenga la posición del cuadro capturado en la secuencia de video, desde El primer cuadro se cuenta en milisegundos. O comience desde el primer cuadro con un número de 0 para obtener el número del cuadro capturado. O tome la posición relativa, el primer cuadro es 0 y el último cuadro es 1, que es solo válido para archivos de vídeo.

Establece la etiqueta del primer cuadro capturado:
// Captura desde la posición relativa 0.9 del archivo de video
cvSetCaptureProperty(capture, CV_CAP_PROP_POS_AVI_RATIO, (double)0.9);
solo es válido para capturar desde archivos de video. ¡Pero parece que no tiene éxito! ! !

almacenar archivos de video

Inicialice la memoria de video:
CvVideoWriter *writer = 0;
int isColor = 1;
int fps = 25; // o 30
int frameW = 640; // 744 para cámaras firewire
int frameH = 480; // 480 para cámaras firewirewriter
=cvCreateVideoWriter( "out.avi", CV_FOURCC('P','I','M','1'),
fps, cvSize(frameW,frameH),isColor);
otras codificaciones válidas:

CV_FOURCC('P','I','M','1') = códec MPEG-1
CV_FOURCC('M','J','P','G') = códec motion-jpeg (no funciona bien)
CV_FOURCC('M', 'P', '4', '2') = códec MPEG-4.2 CV_FOURCC (
'D', 'I', 'V', '3') = códec MPEG-4.3
CV_FOURCC( 'D', 'I', 'V', 'X') = códec MPEG-4 CV_FOURCC
('U', '2', '6', '3') = códec H263 CV_FOURCC
('I', '2 ', '6', '3') = Códec H263I
CV_FOURCC('F', 'L', 'V', '1') = Códec FLV1
Si el códec de video está configurado en -1, se abrirá una ventana de selección de códec (bajo sistema de ventanas).

Almacenar archivos de video:
IplImage* img = 0;
int nFrames = 50;
for(i=0;i<nFrames;i++){ cvGrabFrame(capturar); // capturar marco img=cvRetrieveFrame(capturar); // restaurar imagen cvWriteFrame ( escritor,img); //Agregar fotogramas al archivo de video } Para ver la imagen capturada durante la captura, agregue el siguiente código en el bucle:




cvShowImage(“mainWin”, img);
key=cvWaitKey(20); // espera 20 ms
Si no hay 20 [milisegundos] de retraso, la secuencia de video no se mostrará correctamente.

Liberar memoria de video:
cvReleaseVideoWriter(&writer);

Lista de otras funciones de operaciones matriciales

add

矩阵加法,A+B的更高级形式,支持mask

scaleAdd

矩阵加法,一个带有缩放因子dst(I) = scale * src1(I) + src2(I)

addWeighted

矩阵加法,两个带有缩放因子dst(I) = saturate(src1(I) * alpha + src2(I) * beta + gamma)

subtract

矩阵减法,A-B的更高级形式,支持mask

multiply

矩阵逐元素乘法,同Mat::mul()函数,与A*B区别,支持mask

gemm

一个广义的矩阵乘法操作

divide

矩阵逐元素除法,与A/B区别,支持mask

abs

对每个元素求绝对值

absdiff

两个矩阵的差的绝对值

exp

求每个矩阵元素 src(I) 的自然数 e 的 src(I) 次幂 dst[I] = esrc(I)

pow

求每个矩阵元素 src(I) 的 p 次幂 dst[I] = src(I)p

log

求每个矩阵元素的自然数底 dst[I] = log|src(I)| (if src != 0)

sqrt

求每个矩阵元素的平方根

min, max

求每个元素的最小值或最大值返回这个矩阵 dst(I) = min(src1(I), src2(I)), max同

minMaxLoc

定位矩阵中最小值、最大值的位置

compare

返回逐个元素比较结果的矩阵

bitwise_and, bitwise_not, bitwise_or, bitwise_xor

每个元素进行位运算,分别是和、非、或、异或

cvarrToMat

旧版数据CvMat,IplImage,CvMatND转换到新版数据Mat

extractImageCOI

从旧版数据中提取指定的通道矩阵给新版数据Mat

randu

以Uniform分布产生随机数填充矩阵,同 RNG::fill(mat, RNG::UNIFORM)

randn

以Normal分布产生随机数填充矩阵,同 RNG::fill(mat, RNG::NORMAL)

randShuffle

随机打乱一个一维向量的元素顺序

theRNG()

返回一个默认构造的RNG类的对象

 theRNG()::fill(...)

reduce

矩阵缩成向量

repeat

矩阵拷贝的时候指定按x/y方向重复

split

多通道矩阵分解成多个单通道矩阵

merge

多个单通道矩阵合成一个多通道矩阵

mixChannels

矩阵间通道拷贝,如Rgba[]到Rgb[]和Alpha[]

sort, sortIdx

为矩阵的每行或每列元素排序

setIdentity

设置单元矩阵

completeSymm

矩阵上下三角拷贝

inRange

检查元素的取值范围是否在另两个矩阵的元素取值之间,返回验证矩阵

checkRange

检查矩阵的每个元素的取值是否在最小值与最大值之间,返回验证结果bool

sum

求矩阵的元素和

mean

求均值

meanStdDev

均值和标准差

countNonZero

统计非零值个数

cartToPolar, polarToCart

笛卡尔坐标与极坐标之间的转换

flip

矩阵翻转

transpose

矩阵转置,比较 Mat::t() AT

trace

矩阵的迹

determinant

行列式 |A|, det(A)

eigen

矩阵的特征值和特征向量

invert

矩阵的逆或者伪逆,比较 Mat::inv()

magnitude

向量长度计算 dst(I) = sqrt(x(I)2 + y(I)2)

Mahalanobis

Mahalanobis距离计算

phase

相位计算,即两个向量之间的夹角

norm

求范数,1-范数、2-范数、无穷范数

normalize

标准化

mulTransposed

矩阵和它自己的转置相乘 AT * A, dst = scale(src - delta)T(src - delta)

convertScaleAbs

先缩放元素再取绝对值,最后转换格式为8bit型

calcCovarMatrix

计算协方差阵

solve

求解1个或多个线性系统或者求解最小平方问题(least-squares problem)

solveCubic

求解三次方程的根

solvePoly

求解多项式的实根和重根

dct, idct

正、逆离散余弦变换,idct同dct(src, dst, flags | DCT_INVERSE)

dft, idft

正、逆离散傅立叶变换, idft同dft(src, dst, flags | DTF_INVERSE)

LUT

查表变换

getOptimalDFTSize

返回一个优化过的DFT大小

mulSpecturms

两个傅立叶频谱间逐元素的乘法

La tabla anterior se cita de: http://blog.sina.com.cn/s/blog_7908e1290101i97z.html

Indique la fuente de la reimpresión (este artículo actualiza el enlace): http://blog.csdn.net/iracer/article/details/51296631

Supongo que te gusta

Origin blog.csdn.net/jiyanghao19/article/details/130887926
Recomendado
Clasificación