基于opnecv的常用功能函数及其相关函数

标定板生成

void gencaliboard()
{
	//单位转换  
	int dot_per_inch = 96;  //我的电脑是96DPI(dot per inch)  
	double cm_to_inch = 0.3937; //1cm=0.3937inch  
	double inch_to_cm = 2.54;   //1inch = 2.54cm  
	double inch_per_dot = 1.0 / 96.0;

	//自定义标定板  
	double blockSize_cm = 2.5; //方格尺寸:边长1.3cm的正方形  
	int blockNumX = 19; //
	int blockNumY = 13; //


	int blockSize = (int)(blockSize_cm / inch_to_cm * dot_per_inch);
	cout << blockSize << endl;

	int imageSizeX = blockSize * blockNumX;
	int imageSizeY = blockSize * blockNumY;
	cout << imageSizeX << endl;
	cout << imageSizeY << endl;
	Mat chessBoard(imageSizeY, imageSizeX, CV_8UC3, Scalar::all(0));
	unsigned char color = 0;

	for (int i = 0; i < imageSizeX; i = i + blockSize) {
		//color = ~color;
		for (int j = 0; j < imageSizeY; j = j + blockSize) {
			Mat ROI = chessBoard(Rect(i, j, blockSize, blockSize));
			ROI.setTo(Scalar::all(color));
			color = ~color;
		}
	}
	imshow("Chess board", chessBoard);
	imwrite("D:\\chessBoard.jpg", chessBoard);
	cvWaitKey(3000);
}

获取某一文件夹下的所有文件名

只有32位可以编译
来自网络 https://www.cnblogs.com/wqpkita/p/6849283.html

void getFiles(string path, vector<string>& files)
{
	//文件句柄  
	long   hFile = 0;
	//文件信息,声明一个存储文件信息的结构体  
	struct _finddata_t fileinfo;
	string p;//字符串,存放路径
	if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1)//若查找成功,则进入
	{
		do
		{
			//如果是目录,迭代之(即文件夹内还有文件夹)  
			if ((fileinfo.attrib &  _A_SUBDIR))
			{
				//文件名不等于"."&&文件名不等于".."
				//.表示当前目录
				//..表示当前目录的父目录
				//判断时,两者都要忽略,不然就无限递归跳不出去了!
				if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
					getFiles(p.assign(path).append("\\").append(fileinfo.name), files);
			}
			//如果不是,加入列表  ,这里进行了判断,只有是.jpg的文件才加入列表
			else
			{
				string a = ".jpg";
				string b = ".jpg.bmp";
				string::size_type idx1, idx2;
				char* temp = fileinfo.name;
				string temp1 = temp;
				idx1 = temp1.find(a);
				idx2 = temp1.find(b);
				if (idx1 != string::npos  && idx2 == string::npos)
					files.push_back(p.assign(path).append("\\").append(fileinfo.name));
			}
		} while (_findnext(hFile, &fileinfo) == 0);
		//_findclose函数结束查找
		_findclose(hFile);
	}
}

opencv按照想要的缩放比例显示Mat

调用后需要使用waitkey。

void imageshow(Mat draw, float scale, string str)
{
	Size dsize = Size(draw.cols*scale, draw.rows*scale);
	Mat imgshow = Mat(dsize, CV_32S);
	resize(draw, imgshow, dsize);

	namedWindow(str);
	imshow(str, imgshow);
}

opencv读取摄像头并逐帧写入视频文件

bool usecamera()
{
	VideoCapture cap(1);
	VideoWriter writer;
	string outFlie = "test3.avi";

	cap.set(CV_CAP_PROP_FRAME_HEIGHT, 960);
	cap.set(CV_CAP_PROP_FRAME_WIDTH, 2560);

	int w = static_cast<int>(cap.get(CV_CAP_PROP_FRAME_WIDTH));
	int h = static_cast<int>(cap.get(CV_CAP_PROP_FRAME_HEIGHT));

	Size videoSize(w, h);
	int rate = 30;
	writer.open(outFlie, CV_FOURCC('M', 'J', 'P', 'G'), rate, videoSize);

	 obtain the video parameters
	//int rate = cap.get(CV_CAP_PROP_FPS);         //the rate of video frame
	//int frameHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT);  // the height of video frame
	//int frameWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH);    // the width of video frame


	//VideoWriter writer("VideoTest.avi", CV_FOURCC('M', 'J', 'P', 'G'), 60, videoSize);  
	if (!cap.isOpened())
	{
		return -1;
	}
	Mat frame;
	while (1)
	{
		cap.read(frame);
		cout << frame.type() << endl;
		writer.write(frame);
		if (frame.empty()) break;
		imshow("当前视频", frame);
		if (waitKey(10) == 27)
			break;
	}
	return 0;
}

三点确定一个圆

struct CircleData
{
	Point2f center;
	int radius;
};

CircleData findCircle1(Point2f pt1, Point2f pt2, Point2f pt3)
{
	//定义两个点,分别表示两个中点  
	Point2f midpt1, midpt2;
	//求出点1和点2的中点  
	midpt1.x = (pt2.x + pt1.x) / 2;
	midpt1.y = (pt2.y + pt1.y) / 2;
	//求出点3和点1的中点  
	midpt2.x = (pt3.x + pt1.x) / 2;
	midpt2.y = (pt3.y + pt1.y) / 2;
	//求出分别与直线pt1pt2,pt1pt3垂直的直线的斜率  
	float k1 = -(pt2.x - pt1.x) / (pt2.y - pt1.y);
	float k2 = -(pt3.x - pt1.x) / (pt3.y - pt1.y);
	//然后求出过中点midpt1,斜率为k1的直线方程(既pt1pt2的中垂线):y - midPt1.y = k1( x - midPt1.x)  
	//以及过中点midpt2,斜率为k2的直线方程(既pt1pt3的中垂线):y - midPt2.y = k2( x - midPt2.x)  
	//定义一个圆的数据的结构体对象CD  
	CircleData CD;
	//连立两条中垂线方程求解交点得到:  
	CD.center.x = (midpt2.y - midpt1.y - k2 * midpt2.x + k1 * midpt1.x) / (k1 - k2);
	CD.center.y = midpt1.y + k1 * (midpt2.y - midpt1.y - k2 * midpt2.x + k2 * midpt1.x) / (k1 - k2);
	//用圆心和其中一个点求距离得到半径:  
	CD.radius = sqrtf((CD.center.x - pt1.x)*(CD.center.x - pt1.x) + (CD.center.y - pt1.y)*(CD.center.y - pt1.y));
	return CD;
}

轮廓平滑操作

来自网络 https://blog.csdn.net/qq_16949707/article/details/70340090

int filterRadius = 20;
int filterSize = 2 * filterRadius + 1;
double sigma = 10;

vector<vector<Point>> smooth(vector<vector<Point>> contours)
{
	vector<vector<Point> > smoothContours;
	for (size_t j = 0; j < contours.size(); j++)
	{
		// extract x and y coordinates of points. we'll consider these as 1-D signals
		// add circular padding to 1-D signals
		size_t len = contours[j].size() + 2 * filterRadius;
		size_t idx = (contours[j].size() - filterRadius);
		vector<float> x, y;
		for (size_t i = 0; i < len; i++)
		{
			x.push_back(contours[j][(idx + i) % contours[j].size()].x);
			y.push_back(contours[j][(idx + i) % contours[j].size()].y);
		}
		// filter 1-D signals
		vector<float> xFilt, yFilt;
		GaussianBlur(x, xFilt, Size(filterSize, filterSize), sigma, sigma);
		GaussianBlur(y, yFilt, Size(filterSize, filterSize), sigma, sigma);

		// build smoothed contour
		vector<Point> smooth;
		for (size_t i = filterRadius; i < contours[j].size() + filterRadius; i++)
		{
			smooth.push_back(Point(xFilt[i], yFilt[i]));
		}
		smoothContours.push_back(smooth);
	}
	return smoothContours;
}

相机标定函数

#define BOARD_SCALE 9.73   /* 实际测量得到的标定板上每个棋盘格的大小,单位是mm*/
#define BOARD_HEIGHT 12
#define BOARD_WIDTH 18
#include <time.h>
void calibration()
{
	clock_t start = clock();
	vector<string> files;
	vector<string> names;
	files.clear();
	string filePath = "pic/calibration/";   //calibration

	getFiles(filePath, files);

	cout << "找到的文件有" << endl;
	for (int i = 0; i < files.size(); i++)
	{
		cout << files[i] << endl;
	}


	//读取每一幅图像,从中提取出角点,然后对角点进行亚像素精确化   
	cout << "开始提取角点………………" << endl;
	int image_count = 0;  /* 图像数量 */
	Size image_size;  /* 图像的尺寸 */
	Size board_size = Size(BOARD_HEIGHT, BOARD_WIDTH);    /* 标定板上每行、列的角点数 */
	vector<Point2f> image_points_buf;  /* 缓存每幅图像上检测到的角点 */
	vector<vector<Point2f>> image_points_seq; /* 保存检测到的所有角点 */

	for (int i = 0; i < files.size(); i++)
	{
		cout << files[i] << endl;

		Mat imageInput = imread(files[i]);
		//cvtColor(imageInput, imageInput, CV_BGR2GRAY);
		image_size.width = imageInput.cols;
		image_size.height = imageInput.rows;
		cout << "image_size.width = " << image_size.width << endl;
		cout << "image_size.height = " << image_size.height << endl;

		/* 提取角点 */
		if (0 == findChessboardCorners(imageInput, board_size, image_points_buf))
		{
			cout << "can not find chessboard corners!\n"; //找不到角点  
			cout << "\n";
			continue;
		}
		else
		{
			//找到一幅有效的图片
			image_count++;

			//Mat view_gray;
			//cvtColor(imageInput, view_gray, CV_RGB2GRAY);

			///* 亚像素精确化 */
			find4QuadCornerSubpix(view_gray,image_points_buf,Size(5,5)); //对粗提取的角点进行精确化  
			//cornerSubPix(view_gray, image_points_buf,
			//	Size(5, 5),
			//	Size(-1, -1),
			//	TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS,
			//		30,		   // max number of iterations 
			//		0.1));     // min accuracy

			image_points_seq.push_back(image_points_buf);  //保存亚像素角点

														   /* 在图像上显示角点位置 */
			drawChessboardCorners(imageInput, board_size, image_points_buf, true); //用于在图片中标记角点 

																				  //写入文件
			string filePath = files[i];
			filePath += ".bmp";
			imwrite(filePath, imageInput);
			cout << "\n";
		}
	}

	int total = image_points_seq.size();
	cout << "共使用了" << total << "幅图片" << endl;
	cout << "角点提取完成!\n";


	cout << "开始标定………………\n";

	/*棋盘三维信息*/
	vector<vector<Point3f>> object_points; /* 保存标定板上角点的三维坐标 */
										   /*内外参数*/
	Mat cameraMatrix = Mat(3, 3, CV_32FC1, Scalar::all(0)); /* 摄像机内参数矩阵 */
	vector<int> point_counts;  // 每幅图像中角点的数量  
	Mat distCoeffs = Mat(1, 8, CV_32FC1, Scalar::all(0)); /* 摄像机的5个畸变系数:k1,k2,p1,p2,k3 */
	vector<Mat> tvecsMat;  /* 每幅图像的旋转向量 */
	vector<Mat> rvecsMat; /* 每幅图像的平移向量 */
						  /* 初始化标定板上角点的三维坐标 */
	int i, j, t;
	for (t = 0; t < image_count; t++)
	{
		vector<Point3f> tempPointSet;
		for (i = 0; i < board_size.height; i++)
		{
			for (j = 0; j < board_size.width; j++)
			{
				Point3f realPoint;
				/* 假设标定板放在世界坐标系中z=0的平面上 */
				realPoint.x = j * BOARD_SCALE;
				realPoint.y = i * BOARD_SCALE;
				realPoint.z = 0;
				tempPointSet.push_back(realPoint);
			}
		}
		object_points.push_back(tempPointSet);
	}

	/* 初始化每幅图像中的角点数量,假定每幅图像中都可以看到完整的标定板 */
	for (i = 0; i < image_count; i++)
	{
		point_counts.push_back(board_size.width*board_size.height);
	}


	/* 开始标定 */
	calibrateCamera(object_points, image_points_seq, image_size, cameraMatrix, distCoeffs, rvecsMat, tvecsMat, CV_CALIB_RATIONAL_MODEL);
	cout << "标定完成!\n";

	clock_t ends = clock();
	cout << "Running Time : " << (double)(ends - start) / CLOCKS_PER_SEC << endl;


	//对标定结果进行评价  
	ofstream fout("caliberation_result.txt");  /* 保存标定结果的文件 */

	double total_err = 0.0; /* 所有图像的平均误差的总和 */
	double err = 0.0; /* 每幅图像的平均误差 */
	vector<Point2f> image_points2; /* 保存重新计算得到的投影点 */
	cout << "\t每幅图像的标定误差:\n";
	fout << "每幅图像的标定误差:\n";
	for (i = 0; i < image_count; i++)
	{
		vector<Point3f> tempPointSet = object_points[i];
		/* 通过得到的摄像机内外参数,对空间的三维点进行重新投影计算,得到新的投影点 */
		projectPoints(tempPointSet, rvecsMat[i], tvecsMat[i], cameraMatrix, distCoeffs, image_points2);
		/* 计算新的投影点和旧的投影点之间的误差*/
		vector<Point2f> tempImagePoint = image_points_seq[i];
		Mat tempImagePointMat = Mat(1, tempImagePoint.size(), CV_32FC2);
		Mat image_points2Mat = Mat(1, image_points2.size(), CV_32FC2);
		for (int j = 0; j < tempImagePoint.size(); j++)
		{
			image_points2Mat.at<Vec2f>(0, j) = Vec2f(image_points2[j].x, image_points2[j].y);
			tempImagePointMat.at<Vec2f>(0, j) = Vec2f(tempImagePoint[j].x, tempImagePoint[j].y);
		}
		err = norm(image_points2Mat, tempImagePointMat, NORM_L2);
		total_err += err /= point_counts[i];
		cout << "第" << files[i] << "幅图像的平均误差:" << err << "像素" << endl;
		fout << "第" << files[i] << "幅图像的平均误差:" << err << "像素" << endl;
	}

	cout << "总体平均误差:" << total_err / image_count << "像素" << endl;
	fout << "总体平均误差:" << total_err / image_count << "像素" << endl << endl;

	//保存定标结果      
	cout << "开始保存定标结果………………" << endl;
	Mat rotation_matrix = Mat(3, 3, CV_32FC1, Scalar::all(0)); /* 保存每幅图像的旋转矩阵 */
	fout << "相机内参数矩阵:" << endl;
	fout << cameraMatrix << endl << endl;
	fout << "畸变系数:\n";
	fout << distCoeffs << endl << endl << endl;
	for (int i = 0; i < image_count; i++)
	{
		fout << "第" << files[i] << "幅图像的旋转向量:" << endl;
		fout << tvecsMat[i] << endl;
		/* 将旋转向量转换为相对应的旋转矩阵 */
		Rodrigues(tvecsMat[i], rotation_matrix);
		fout << "第" << files[i] << "幅图像的旋转矩阵:" << endl;
		fout << rotation_matrix << endl;
		fout << "第" << files[i] << "幅图像的平移向量:" << endl;
		fout << rvecsMat[i] << endl << endl;
	}
	cout << "完成保存" << endl;
	fout << endl;

	//畸变矫正
	for (int i = 0; i < image_count; i++)
	{
		cout << files[i] << endl;

		Mat src = imread(files[i]);
		Mat dst = src.clone();
		undistort(src, dst, cameraMatrix, distCoeffs);

		string filePath = files[i];
		filePath += "undis.bmp";
		imwrite(filePath, dst);
		cout << "\n";
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

仟人斩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值