简易C语言矩阵运算库

参考网址:

异想家纯C语言矩阵运算库 - Sandeepin - 博客园

这次比opencv快⑥倍!!!

参考上述网址,整理了一下代码:

//main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "matlib.h"

typedef struct 
{
	int x;
	int y;
} Point_t;

typedef struct 
{
	Point_t stSrc;
	Point_t stDsc;
} Perspective_map_t;

//解非齐次线性方程组Ax=b求x
int get_perspective_transform(Perspective_map_t stPointMap[4] ,Matrix_t *pstPerspectiveMat)
{
	int ret = 0;
	Matrix_t * pstMatrix_A = NULL;
	Matrix_t * pstMatrix_InvA = NULL;
	Matrix_t * pstMatrix_x = NULL;
	Matrix_t * pstMatrix_b = NULL;
	
#define GET_2D_ARRAY_VAL(buf, i, j, column) *((buf) + (i)*(column) + (j))

	if(!pstPerspectiveMat || 
		pstPerspectiveMat->row != 3 || pstPerspectiveMat->column!= 3)
	{
		printf("Param err\n");
		return -1;
	}

	pstMatrix_A = MatCreate(8, 8);
	pstMatrix_InvA = MatCreate(8, 8);
	pstMatrix_x = MatCreate(8, 1);
	pstMatrix_b = MatCreate(8, 1);

	for(int i = 0; i < 8; i += 2)
	{
		
		GET_2D_ARRAY_VAL(pstMatrix_A->matrix_data, i, 0, 8) = stPointMap[i /2 ].stSrc.x;
		GET_2D_ARRAY_VAL(pstMatrix_A->matrix_data, i, 1, 8) = stPointMap[i /2 ].stSrc.y;
		GET_2D_ARRAY_VAL(pstMatrix_A->matrix_data, i, 2, 8) = 1;
		GET_2D_ARRAY_VAL(pstMatrix_A->matrix_data, i, 6, 8) = -stPointMap[i /2 ].stSrc.x * stPointMap[i /2 ].stDsc.x;
		GET_2D_ARRAY_VAL(pstMatrix_A->matrix_data, i, 7, 8) = -stPointMap[i /2 ].stDsc.x * stPointMap[i /2 ].stSrc.y;
		
		GET_2D_ARRAY_VAL(pstMatrix_A->matrix_data, i+1, 3, 8) = stPointMap[i /2 ].stSrc.x;
		GET_2D_ARRAY_VAL(pstMatrix_A->matrix_data, i+1, 4, 8) = stPointMap[i /2 ].stSrc.y;
		GET_2D_ARRAY_VAL(pstMatrix_A->matrix_data, i+1, 5, 8) = 1;
		GET_2D_ARRAY_VAL(pstMatrix_A->matrix_data, i+1, 6, 8) = -stPointMap[i /2 ].stSrc.x * stPointMap[i /2 ].stDsc.y;
		GET_2D_ARRAY_VAL(pstMatrix_A->matrix_data, i+1, 7, 8) = -stPointMap[i /2 ].stSrc.y * stPointMap[i /2 ].stDsc.y;  

		pstMatrix_b->matrix_data[i] = stPointMap[i /2 ].stDsc.x;
		pstMatrix_b->matrix_data[i + 1] = stPointMap[i /2 ].stDsc.y;
	}
	
	ret = MatInv(pstMatrix_A, pstMatrix_InvA);
	ret |= MatMul(pstMatrix_InvA, pstMatrix_b, pstMatrix_x);
		
	memcpy(pstPerspectiveMat->matrix_data, pstMatrix_x->matrix_data, pstMatrix_x->row * pstMatrix_x->column * sizeof(double));
	GET_2D_ARRAY_VAL(pstPerspectiveMat->matrix_data, 2, 2, 3) = 1;

	MatRelease(pstMatrix_A);
	MatRelease(pstMatrix_InvA);
	MatRelease(pstMatrix_x);
	MatRelease(pstMatrix_b);
	
#undef GET_2D_ARRAY_VAL

	return ret;
}


int main(int argc, char** argv)
{
	Matrix_t Matrix_A;
	double A[] = { -3, 2, -5, -1, 0, -2, 3, -4, 1 };
	Matrix_A.row = 3;
	Matrix_A.column = 3;
	Matrix_A.matrix_data = A;

	Matrix_t Matrix_B;
	double B[] = { 1, 4, 7, 3, 0, 5, -1, 9, 11 };
	Matrix_B.row = 3;
	Matrix_B.column = 3;
	Matrix_B.matrix_data = B;

	Matrix_t Matrix_C;
	double C[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	Matrix_C.row = 3;
	Matrix_C.column = 3;
	Matrix_C.matrix_data = C;

	Matrix_t Matrix_Adj;
	double Adj[9] = {0};
	Matrix_Adj.row = 3;
	Matrix_Adj.column = 3;
	Matrix_Adj.matrix_data = Adj;
	
	Matrix_t Matrix_Out;
	double Out[9] = {0};
	Matrix_Out.row = 3;
	Matrix_Out.column = 3;
	Matrix_Out.matrix_data = Out;

	printf("A+B:\n");
	MatAdd(&Matrix_A, &Matrix_B, &Matrix_Out); 
	MatShow(&Matrix_Out);

	printf("A-B:\n");
	MatSub(&Matrix_A, &Matrix_B, &Matrix_Out); 
	MatShow(&Matrix_Out);

	printf("A*B:\n");
	MatMul(&Matrix_A, &Matrix_B, &Matrix_Out);
	MatShow(&Matrix_Out);

	printf("2*C:\n");
	MatMulk(&Matrix_C, 2, &Matrix_Out);
	MatShow(&Matrix_Out);

	printf("C的转置:\n");
	MatT(&Matrix_C, &Matrix_Out); 
	MatShow(&Matrix_Out);

	double det = 0.0;
	printf("B的行列式值:\n");
	MatDet(&Matrix_B, &det);
	printf("%16lf\n", det);
	printf("C的行列式值:\n");
	MatDet(&Matrix_C, &det);
	printf("%16lf\n", det);
	
	//矩阵的逆
	printf("A的逆:\n");
	MatInv(&Matrix_A, &Matrix_Out); 
	MatShow(&Matrix_Out);
	printf("C的逆:\n");
	MatInv(&Matrix_C, &Matrix_Out);
	MatShow(&Matrix_Out);

	//矩阵代数余子式
	printf("C的(0,0)元素的代数余子式:\n");
	printf("%16lf\n", MatACof(C, 3, 0, 0));
	
	//矩阵伴随矩阵
	printf("A的伴随矩阵:\n");
	MatAdj(&Matrix_A, &Matrix_Adj); 
	MatShow(&Matrix_Adj);

	//蒋方正矩阵库应用:多元线性回归
	//多元线性回归公式:β=(X'X)^(-1)X'Y
	double X[15][5] = {
		1, 316, 1536, 874, 981,//第一列要补1
		1, 385, 1771, 777, 1386,
		1, 299, 1565, 678, 1672,
		1, 326, 1970, 785, 1864,
		1, 441, 1890, 785, 2143,
		1, 460, 2050, 709, 2176,
		1, 470, 1873, 673, 1769,
		1, 504, 1955, 793, 2207,
		1, 348, 2016, 968, 2251,
		1, 400, 2199, 944, 2390,
		1, 496, 1328, 749, 2287,
		1, 497, 1920, 952, 2388,
		1, 533, 1400, 1452, 2093,
		1, 506, 1612, 1587, 2083,
		1, 458, 1613, 1485, 2390
	};
	double Y[15][1] = {
		3894,
		4628,
		4569,
		5340,
		5449,
		5599,
		5010,
		5694,
		5792,
		6126,
		5025,
		5924,
		5657,
		6019,
		6141
	};

	Matrix_t *pstMatrix_X = NULL;
	Matrix_t *pstMatrix_Y = NULL;
	Matrix_t *pstMatrix_XT = NULL;
	Matrix_t *pstMatrix_XTX = NULL;
	Matrix_t *pstMatrix_InvXTX = NULL;
	Matrix_t *pstMatrix_InvXTXXT = NULL;
	Matrix_t *pstMatrix_InvXTXXTY = NULL;

	pstMatrix_X = MatCreateInitFromArray(15, 5, (double *)X);
	pstMatrix_Y = MatCreateInitFromArray(15, 1, (double *)Y);
	pstMatrix_XT = MatCreate(5, 15);
	pstMatrix_XTX = MatCreate(5, 5);
	pstMatrix_InvXTX = MatCreate(5, 5);
	pstMatrix_InvXTXXT = MatCreate(5, 15);
	pstMatrix_InvXTXXTY = MatCreate(5, 1);
	
	//多元线性回归公式:β=(X'X)^(-1)X'Y
	MatT(pstMatrix_X, pstMatrix_XT);
	MatMul(pstMatrix_XT, pstMatrix_X, pstMatrix_XTX);
	MatInv(pstMatrix_XTX, pstMatrix_InvXTX);
	MatMul(pstMatrix_InvXTX, pstMatrix_XT, pstMatrix_InvXTXXT);
	MatMul(pstMatrix_InvXTXXT, pstMatrix_Y, pstMatrix_InvXTXXTY);
	printf("多元线性回归β系数:\n");
	MatShow(pstMatrix_InvXTXXTY);

	//保存矩阵到csv
	MatWrite("MulLinearBetaCoef.csv", pstMatrix_InvXTXXTY);
		
	MatRelease(pstMatrix_X);
	MatRelease(pstMatrix_Y);
	MatRelease(pstMatrix_XT);
	MatRelease(pstMatrix_XTX);
	MatRelease(pstMatrix_InvXTX);
	MatRelease(pstMatrix_InvXTXXT);
	MatRelease(pstMatrix_InvXTXXTY);

	printf("透视变换:\n");
	Perspective_map_t stPointMap[4] = 
	{
		{
  
  { 50 , 50 }  ,{ 0  , 0  }},
		{
  
  { 200, 50 }  ,{ 300, 0  }},
		{
  
  { 50 , 200}  ,{ 0  , 400}},
		{
  
  { 200, 200}  ,{ 300, 400}},
	};
	
	Matrix_t *pstPerspectiveMat = NULL;
	Matrix_t *pstPerspectiveInvMat = NULL;
	pstPerspectiveMat = MatCreate(3, 3);
	pstPerspectiveInvMat = MatCreate(3, 3);	

	//获取透视变换矩阵
	get_perspective_transform(stPointMap , pstPerspectiveMat);
	MatShow(pstPerspectiveMat);

	//反透视变换矩阵
	MatInv(pstPerspectiveMat, pstPerspectiveInvMat);
	MatShow(pstPerspectiveInvMat);

	//保存矩阵到csv
	MatWrite("PerspectiveMat.csv", pstPerspectiveInvMat);
	
	MatRelease(pstPerspectiveMat);
	MatRelease(pstPerspectiveInvMat);

	//读取csv文件数据到矩阵
	printf("读取csv文件:\n");
	Matrix_t *pstReadMat = NULL;
	pstReadMat = MatCreate(3, 3);
	
	MatRead("PerspectiveMat.csv", pstReadMat);
	MatShow(pstReadMat);
	
	return 0;
}

//matlib.h

#ifndef __MATLIB_H__
#define __MATLIB_H__

//定义csv文件读写矩阵函数,用于测试用例
#define USE_CSV_FILE_TEST

typedef struct 
{
	int row; //行
	int column; //列

	double *matrix_data; //缓冲区
} Matrix_t;

Matrix_t *MatCreate(int row, int column);
Matrix_t *MatCreateInitFromArray(int row, int column, double *Array);
void MatRelease(Matrix_t *Mat);
int MatCopy(Matrix_t *dsc, Matrix_t *src);

int MatAdd(Matrix_t* A, Matrix_t* B, Matrix_t *Out);
int MatSub(Matrix_t* A, Matrix_t* B, Matrix_t *Out);
int MatMul(Matrix_t* A, Matrix_t* B, Matrix_t *Out);
int MatMulk(Matrix_t* A, double k, Matrix_t *Out);
int MatT(Matrix_t* A, Matrix_t *Out);
int MatDet(Matrix_t* A, double *Out);
int MatInv(Matrix_t* A, Matrix_t *Out);
double MatACof(double *A, int row, int m, int n);
int MatAdj(Matrix_t* A, Matrix_t *Out);

void MatShow(Matrix_t* Mat);

#ifdef USE_CSV_FILE_TEST
int MatRead(char *InCsvFileName, Matrix_t *Out);
int MatWrite(const char *OutCsvFileName, Matrix_t *In);
#endif //USE_CSV_FILE_TEST

#endif //__MATLIB_H__
//matlib.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "matlib.h"

// (det用)功能:求逆序对的个数
static int inver_order(int *list, int n)
{
	int ret = 0;
	for (int i = 1; i < n; i++)
		for (int j = 0; j < i; j++)
			if (list[j] > list[i])
				ret++;
	return ret;
}

// (det用)功能:符号函数,正数返回1,负数返回-1
static int sgn(int order)
{
	return order % 2 ? -1 : 1;
}

// (det用)功能:交换两整数a、b的值
static void swap(int *a, int *b)
{
	int m;
	m = *a;
	*a = *b;
	*b = m;
}

// 功能:求矩阵行列式的核心函数
static double det(double *p, int n, int k, int *list, double sum)
{
	if (k >= n)
	{
		int order = inver_order(list, n);
		double item = (double)sgn(order);
		for (int i = 0; i < n; i++)
		{
			//item *= p[i][list[i]];
			item *= *(p + i * n + list[i]);
		}
		return sum + item;
	}
	else
	{
		for (int i = k; i < n; i++)
		{
			swap(&list[k], &list[i]);
			sum = det(p, n, k + 1, list, sum);
			swap(&list[k], &list[i]);
		}
	}
	return sum;
}

Matrix_t *MatCreate(int row, int column)
{
	unsigned int len = row*column*sizeof(double);
	Matrix_t *pMatrix = malloc(sizeof(Matrix_t));
	if(!pMatrix)
	{
		return NULL;
	}
	
	pMatrix->row = row;
	pMatrix->column = column;
	pMatrix->matrix_data = malloc(len);
	if(!pMatrix->matrix_data)
	{
		free(pMatrix);
		return NULL;
	}
	memset(pMatrix->matrix_data, 0, len);
	
	return pMatrix;
}

Matrix_t *MatCreateInitFromArray(int row, int column, double *Array)
{
	Matrix_t *pMatrix = MatCreate(row, column);
	memcpy(pMatrix->matrix_data, Array, row * column * sizeof(double));
	return pMatrix;
}

void MatRelease(Matrix_t *Mat)
{
	if(Mat)
	{
		if(Mat->matrix_data)
		{
			free(Mat->matrix_data);
		}
		
		free(Mat);
	}
}

// 功能:矩阵显示
// 形参:(输入)矩阵首地址指针Mat,矩阵行数row和列数col。
// 返回:无
void MatShow(Matrix_t* Mat)
{
	printf("\n");
	for (int i = 0; i < Mat->row * Mat->column; i++)
	{
		printf("%16lf ", Mat->matrix_data[i]);
		if (0 == (i + 1) % Mat->column) 
		{
			printf("\n");
		}
	}
	printf("\n");
}

// 功能:矩阵相加
// 形参:(输入)矩阵A首地址指针A,矩阵B首地址指针B,矩阵A(也是矩阵B)行数row和列数col
// 返回:A+B
int MatAdd(Matrix_t* A, Matrix_t* B, Matrix_t* Out)
{
	if(!A || !B || !Out ||
		A->row != B->row || A->column != B->column || 
		A->column != Out->column || A->row != Out->row )
	{
		printf("Input Matrix can not Add!\n");
		return -1;
	}
	
	for (int i = 0; i < A->row; i++)
		for (int j = 0; j < A->column; j++)
		{
			Out->matrix_data[A->column*i + j] = A->matrix_data[A->column*i + j] + B->matrix_data[A->column*i + j];
		}
		
	return 0;
}

// 功能:矩阵相减
// 形参:(输入)矩阵A,矩阵B,矩阵A(也是矩阵B)行数row和列数col
// 返回:A-B
int MatSub(Matrix_t* A, Matrix_t* B, Matrix_t *Out)
{
	if(!A || !B || !Out ||
		A->row != B->row || A->column != B->column || 
		A->column != Out->column || A->row != Out->row )
	{
		printf("Input Matrix can not Sub!\n");
		return -1;
	}
	
	for (int i = 0; i < A->row; i++)
		for (int j = 0; j < A->column; j++)
		{
			Out->matrix_data[A->column*i + j] = A->matrix_data[A->column*i + j] - B->matrix_data[A->column*i + j];
		}
		
	return 0;
}

// 功能:矩阵相乘
// 形参:(输入)矩阵A,矩阵A行数row和列数col,矩阵B,矩阵B行数row和列数col
// 返回:A*B (Arow * Bcol)
int MatMul(Matrix_t* A, Matrix_t* B, Matrix_t *Out)
{
	if (!A || !B || !Out ||
		A->column != B->row)
	{
		printf("Input Matrix can not Mul!\n");
		return -1;
	}

	if(Out->row != A->row ||  Out->column != B->column)
	{
		printf("Output Matrix parameter err!\n");
		return -1;
	}
	
	int i, j, k;
	for (i = 0; i < A->row; i++)
		for (j = 0; j < B->column; j++)
		{
			Out->matrix_data[B->column*i + j] = 0;
			for (k = 0; k < A->column; k++)
				Out->matrix_data[B->column*i + j] = Out->matrix_data[B->column*i + j] + A->matrix_data[A->column*i + k] * B->matrix_data[B->column*k + j];
		}
		
	return 0;
}

// 功能:矩阵数乘(实数k乘以矩阵A)
// 形参:(输入)矩阵A首地址指针,矩阵行数row和列数col,实数k
// 返回:kA
int MatMulk(Matrix_t* A, double k, Matrix_t *Out)
{
	if(!A || !Out ||
		A->column != Out->column || A->row != Out->row )
	{
		printf("Input Matrix can not Mulk!\n");
		return -1;
	}
		
	for (int i = 0; i < A->row * A->column; i++)
	{
		Out->matrix_data[i] = A->matrix_data[i] * k;
	}
	
	return 0;
}

// 功能:矩阵转置
// 形参:(输入)矩阵A首地址指针A,行数row和列数col
// 返回:A的转置
int MatT(Matrix_t* A, Matrix_t *Out)
{
	if(!A || !Out ||
		Out->row != A->column || Out->column != A->row)
	{
		printf("Input Matrix can not T! (%d %d)->(%d %d)\n", Out->row, Out->column, A->row, A->column);
		return -1;
	}
		
	for (int i = 0; i < A->row; i++)
		for (int j = 0; j < A->column; j++)
			Out->matrix_data[A->row*j + i] = A->matrix_data[A->column*i + j];
		
	return 0;
}

// 功能:求行列式值
// 形参:(输入)矩阵A首地址指针A,行数row
// 返回:A的行列式值
int MatDet(Matrix_t* A, double *Out)
{
	if(!A || !Out ||
		A->column != A->row)
	{
		printf("Input Matrix can not Det!\n");
		return -1;
	}

	int *list = malloc(A->row * sizeof(int));
	
	for (int i = 0; i < A->row; i++)
		list[i] = i;
	
	*Out = det(A->matrix_data, A->row, 0, list, 0.0);
	
	free(list);
	
	return 0;
}

// 功能:矩阵的逆
// 形参:(输入)矩阵A首地址指针A,行数row和列数col
// 返回:A的逆
int MatInv(Matrix_t* A, Matrix_t *Out)
{
	if(!A || !Out ||
		A->column != A->row ||
		Out->row != A->column || Out->column != A->row)
	{
		printf("Input Matrix can not Inv!\n");
		return -1;
	}
		
	double det;
	MatDet(A, &det); //求行列式
	if (det == 0)
	{
		printf("Matrix can not Inv!\n");
		return -1;
	}
	
	MatAdj(A, Out); //求伴随矩阵
	int len = A->row * A->row;
	for (int i = 0; i < len; i++)
		Out->matrix_data[i] /= det;
	
	return 0;
}

// 功能:求代数余子式
// 形参:(输入)矩阵A首地址指针A,矩阵行数row, 元素a的下标m,n(从0开始),
// 返回:NxN 矩阵中元素A(mn)的代数余子式
double MatACof(double *A, int row, int m, int n)
{
	Matrix_t *pstMatrix_cofactor = MatCreate(row - 1, row - 1);

	int count = 0;
	int raw_len = row * row;
	double det = 0;
	
	for (int i = 0; i < raw_len; i++)
		if (i / row != m && i % row != n)
		{
			*(pstMatrix_cofactor->matrix_data + count++) = *(A + i);
		}
	
	MatDet(pstMatrix_cofactor, &det);
	if ((m + n) % 2)
		det = -det;
	
	MatRelease(pstMatrix_cofactor);
	
	return det;
}

// 功能:求伴随矩阵
// 形参:(输入)矩阵A首地址指针A,行数row和列数col
// 返回:A的伴随矩阵
int MatAdj(Matrix_t* A, Matrix_t *Out)
{
	if(!A || !Out ||
		Out->row != A->row || Out->column != A->column)
	{
		printf("Input Matrix can not Adj!\n");
		return -1;
	}
		
	int len = A->row * A->row;
	for (int i = 0; i < len; i++)
	{
		Out->matrix_data[i] = MatACof(A->matrix_data, A->row, i % A->row, i / A->row);
	}
	
	return 0;
}

#ifdef USE_CSV_FILE_TEST
// 读取文件行数
static int FileReadRow(const char *filename)
{
	FILE *f = fopen(filename, "r");
	int i = 0;
	char str[4096];
	while (NULL != fgets(str, 4096, f))
		++i;
	printf("数组行数:%d\n", i);
	return i;
}

// 读取文件每行数据数(逗号数+1)
static int FileReadCol(const char *filename)
{
	FILE *f = fopen(filename, "r");
	int i = 0;
	char str[4096];
	fgets(str, 4096, f);
	for (int j = 0; j < strlen(str); j++)
	{
		if (',' == str[j]) i++;
	}
	i++;// 数据数=逗号数+1
	printf("数组列数:%d\n", i);
	return i;
}

// 逗号间隔数据提取
static void GetCommaData(char str_In[4096], double double_Out[1024])
{
	int str_In_len = strlen(str_In); 
	//printf("str_In_len:%d\n", str_In_len);
	char str_Data_temp[128];
	int j = 0;
	int double_Out_num = 0;
	for (int i = 0; i < str_In_len; i++)
	{
		//不是逗号,则是数据,存入临时数组中
		if (',' != str_In[i]) str_Data_temp[j++] = str_In[i];
		//是逗号或\n(最后一个数据),则数据转换为double,保存到输出数组
		if (',' == str_In[i] || '\n' == str_In[i]) { str_Data_temp[j] = '\0'; j = 0; /*printf("str_Data_temp:%s\n", str_Data_temp); */double_Out[double_Out_num++] = atof(str_Data_temp); memset(str_Data_temp, 0, sizeof(str_Data_temp)); }
	}
}

// 功能:从csv文件读矩阵,保存到指针中
// 形参:(输入)csv文件名,预计行数row和列数col
// 返回:矩阵指针A
int MatRead(char *InCsvFileName, Matrix_t *Out)
{
	int row = FileReadRow(InCsvFileName); 
	int col = FileReadCol(InCsvFileName);
	
	FILE *f = fopen(InCsvFileName, "r");
	char buffer[4096];
	while (fgets(buffer, sizeof(buffer), f))
	{
		//printf("buffer[%s]\n",buffer);
		double double_Out[1024] = { 0 };
		GetCommaData(buffer, double_Out);
		for (int i = 0; i < col; i++)
		{
			//printf("double_Out:%lf\n", double_Out[i]);
			*Out->matrix_data++ = double_Out[i];
		}
	}
	
	Out->matrix_data = Out->matrix_data - row * col;//指针移回数据开头
	
	fclose(f);
	
	return 0;
}

// 功能:将矩阵A存入csv文件中
// 形参:(输入)保存的csv文件名,矩阵A首地址指针A,行数row和列数col
// 返回:无
int MatWrite(const char *OutCsvFileName, Matrix_t *In)
{
	FILE *DateFile;
	
	double *Ap = In->matrix_data;
	DateFile = fopen(OutCsvFileName, "w");//追加的方式保存生成的时间戳
	for (int i = 0; i < In->row*In->column; i++)
	{
		if ((i+1) % In->column == 0) fprintf(DateFile, "%lf\n", *Ap);//保存到文件,到列数换行
		else fprintf(DateFile, "%lf,", *Ap);//加逗号
		Ap++;
	}
	fclose(DateFile);
	
	return 0;
}
#endif //USE_CSV_FILE_TEST

我测试了一下解非齐次线性方程组(求透视变换矩阵),实现简单,但速度慢且内存需求较大,有兴趣可以尝试去优化。

C++矩阵运算库中,Eigen库是比较高效的

https://eigen.tuxfamily.org/index.php?title=Main_Pagehttps://eigen.tuxfamily.org/index.php?title=Main_Pagehttps://eigen.tuxfamily.org/index.php?title=Main_Page

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/964836.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

微服务知识——微服务架构的演进过程

文章目录 初始架构&#xff1a;单机架构第一次演进&#xff1a;Tomcat与数据库分开部署第二次演进&#xff1a;引入本地缓存和分布式缓存第三次演进&#xff1a;引入反向代理实现负载均衡第四次演进&#xff1a;数据库读写分离第五次演进&#xff1a;数据库按业务分库第六次演进…

Hackmyvm crack

简介 难度&#xff1a;简单 靶机地址&#xff1a; 环境 kali&#xff1a;192.168.194.9 靶机&#xff1a;192.168.194.23 扫描 nmap全端口扫描查看tcp服务 三个端口服务21的ftp服务、4200的shellinabox服务&#xff0c;是一个web界面的shell连接工具&#xff0c;12359的一…

P2036 [COCI 2008/2009 #2] PERKET(dfs)

#include<bits/stdc.h> using namespace std;int n; int a[15],b[15]; int ansINT_MAX; // 初始化最小差值为一个很大的数&#xff0c;保证能找到最小值void dfs(int i,int s,int k){if(in){ // 当遍历完所有元素时if(s1&&k0) return;int difabs(s-k);ans mi…

逻辑回归:Sigmoid函数在分类问题中的应用

欢迎来到我的主页&#xff1a;【Echo-Nie】 本篇文章收录于专栏【机器学习】 1 什么是Sigmoid函数&#xff1f; Sigmoid函数&#xff08;Logistic函数&#xff09;是机器学习中最经典的激活函数之一&#xff0c;是一个在生物学中常见的S型函数&#xff0c;也称为S型生长曲线。…

【OpenCV实战】基于 OpenCV 的多尺度与模板匹配目标跟踪设计与实现

文章目录 基于 OpenCV 的模板匹配目标跟踪设计与实现1. 摘要2. 系统概述3. 系统原理3.1 模板匹配的基本原理3.2 多尺度匹配 4. 逻辑流程4.1 系统初始化4.2 主循环4.3 逻辑流程图 5. 关键代码解析5.1 鼠标回调函数5.2 多尺度模板匹配 6. 系统优势与不足6.1 优势6.2 不足 7. 总结…

【系统架构设计师】操作系统 ② ( 存储管理 | 页式存储 | 逻辑地址 与 物理地址 | 页表结构 | 物理内存淘汰机制 )

文章目录 一、页式存储1、CPU 调用数据2、内存存储数据弊端3、分页存储4、逻辑地址 和 物理地址 的结构5、逻辑地址 和 物理地址 的结构 示例6、页式存储 优缺点 二、逻辑地址 与 物理地址1、逻辑地址2、物理地址3、逻辑地址 与 物理地址 区别4、逻辑地址 与 物理地址 的转换 三…

AMD数据中心业务创纪录,Instinct MI355X提前发布

没有人能预料到生成式人工智能&#xff08;GenAI&#xff09;会如此迅速地推动英伟达的扩张&#xff0c;也没有人能预料到英伟达的崛起和英特尔的衰落会如此之快。对于那些相信“第二名可以更努力并取得成功”的人来说&#xff0c;AMD的崛起无疑证明了这一点。然而&#xff0c;…

C++ 中的 `string` 类型:全面解析与高效操作

C 中的 string 类型&#xff1a;全面解析与高效操作 在 C 中&#xff0c;string 类型是对字符数组的高级封装&#xff0c;它提供了大量内置函数&#xff0c;使得字符串的处理变得更为简便和高效。与 C 风格的字符数组不同&#xff0c;string 类型不仅自动管理内存&#xff0c;…

穷举vs暴搜vs深搜vs回溯vs剪枝系列一>黄金矿工

目录 决策树&#xff1a;代码设计代码&#xff1a; 决策树&#xff1a; 代码设计 代码&#xff1a; class Solution {boolean[][] vis;int ret,m,n;public int getMaximumGold(int[][] grid) {m grid.length;n grid[0].length;vis new boolean[m][n]; for(int i 0; i <…

DeepSeek 的含金量还在上升

大家好啊&#xff0c;我是董董灿。 最近 DeepSeek 越来越火了。 网上有很多针对 DeepSeek 的推理测评&#xff0c;除此之外&#xff0c;也有很多人从技术的角度来探讨 DeepSeek 带给行业的影响。 比如今天就看到了一篇文章&#xff0c;探讨 DeepSeek 在使用 GPU 进行模型训练…

使用SpringBoot发送邮件|解决了部署时连接超时的bug|网易163|2025

使用SpringBoot发送邮件 文章目录 使用SpringBoot发送邮件1. 获取网易邮箱服务的授权码2. 初始化项目maven部分web部分 3. 发送邮件填写配置EmailSendService [已解决]部署时连接超时附&#xff1a;Docker脚本Dockerfile创建镜像启动容器 1. 获取网易邮箱服务的授权码 温馨提示…

两种文件类型(pdf/图片)打印A4半张纸方法

环境:windows10、Adobe Reader XI v11.0.23 Pdf: 1.把内容由横排变为纵排&#xff1a; 2.点击打印按钮&#xff1a; 3.选择打印页范围和多页&#xff1a; 4.内容打印在纸张上部 图片&#xff1a; 1.右键图片点击打印&#xff1a; 2.选择打印类型&#xff1a; 3.打印配置&am…

C语言打印输出星号图形(三角形、菱形、漏斗)

文章目录 1. 介绍2. 案例分析3. 漏斗型4. 直角三角形4.1 左上直角三角形4.2 右上直角三角形4.3 左下直角三角形4.4 右下直角三角形 5. 等腰三角形5.1 正等腰三角形5.2 倒等腰三角形 6. 平行四边形6.1 纵向左下平行四边形6.2 纵向左上平行四边形6.3 横向左上平行四边形6.4 横向左…

刷题记录 动态规划-7: 63. 不同路径 II

题目&#xff1a;63. 不同路径 II 难度&#xff1a;中等 给定一个 m x n 的整数数组 grid。一个机器人初始位于 左上角&#xff08;即 grid[0][0]&#xff09;。机器人尝试移动到 右下角&#xff08;即 grid[m - 1][n - 1]&#xff09;。机器人每次只能向下或者向右移动一步。…

springboot+vue+uniapp的校园二手交易小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

Python 自学秘籍:开启编程之旅,人生苦短,我用python。

从2009年&#xff0c;用了几次python后就放弃了&#xff0c;一直用的php&#xff0c;现在人工智能时代&#xff0c;完全没php什么事情。必须搞python了&#xff0c;虽然已经40多岁了。死磕python了。让滔滔陪着你一起学python 吧。 开启新世界 在当今人工智能化的时代&#xff…

react的antd表格自定义图标

将原版的加号换成箭头 自定义图标 安装图标包&#xff1a; npm install --save ant-design/icons 引入&#xff1a; import { RightOutlined, DownOutlined } from ant-design/icons; 参数是一个函数 <Table columns{columns} dataSource{data} indentSize{20}expandIc…

chrome浏览器chromedriver下载

chromedriver 下载地址 https://googlechromelabs.github.io/chrome-for-testing/ 上面的链接有和当前发布的chrome浏览器版本相近的chromedriver 实际使用感受 chrome浏览器会自动更新&#xff0c;可以去下载最新的chromedriver使用&#xff0c;自动化中使用新的chromedr…

Vim的基础命令

移动光标 H(左) J(上) K(下) L(右) $ 表示移动到光标所在行的行尾&#xff0c; ^ 表示移动到光标所在行的行首的第一个非空白字符。 0 表示移动到光标所在行的行首。 W 光标向前跳转一个单词 w光标向前跳转一个单词 B光标向后跳转一个单词 b光标向后跳转一个单词 G 移动光标到…

算法与数据结构(括号匹配问题)

思路 从题干可以看出&#xff0c;只要给出的括号对应关系正确&#xff0c;那么就可以返回true,否则返回false。这个题可以使用栈来解决 解题过程 首先从第一个字符开始遍历&#xff0c;如果是括号的左边&#xff08;‘&#xff08;‘&#xff0c;’[‘&#xff0c;’}‘&…