欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

相机标定软件编写(vs+opencv+qt designer)

程序员文章站 2023-12-27 09:10:51
...

联系方式:QQ:936874728
标定板:棋盘格标定板
标定算法:张正友标定法
模块:登录界面模块、时间显示模块、相机标定模块
闲话不多说,上代码。
ui界面:
相机标定软件编写(vs+opencv+qt designer)
登陆界面模块:

void login::on_clicked() //自定义函数
{
	if (ui.UserlineEdit->text() == tr("1") && ui.PassWordlineEdit->text() == tr("1")) //用户密码
	{
		accept();
	}
	else
	{
		QMessageBox::warning(this, tr("warning!"), tr("username or password is wrong"),QMessageBox::Yes); //错误提示
		}
}

时间显示模块

//显示实时系统时间的函数定义*******************************
void camcali::timerUpdate(void)

{
	//获取实时时间
	QDateTime time = QDateTime::currentDateTime();
	//设置显示的时间日期的格式
	QString str = time.toString("yyyy-MM-dd hh:mm:ss dddd");
	//显示在label标签上
	ui.label->setText(str);
}

读取文件模块

/*读取图片和保存数据的路径获取与规划*/
	/************************************/

	ifstream inImgPath("cali.txt");//ifstream读操作(输入)标定所用图像文件的路径
	vector<string> imgList;	//vrter<string>是一种数据类型,字符串
	vector<string>::iterator p;	//迭代器是一种允许程序员检查容器内元素,并实现元素遍历的数据类型,::是域操作符
	string temp;
	if (!inImgPath.is_open())//!是非的意思,真的变成假的,假的变成真的
	{
		cout << "没有找到文件" << endl;	//输出字符串“没有没有找到文件”和换行符到屏幕。cout是标准库iostream中定义好的对象,cout 是std的一个成员函数
		ui.textEdit_shuchu->append("没有找到文件");
	}
	//读取文件中保存的图片文件路径,并存放在数组中
	while (getline(inImgPath, temp))//getline()是从输入流中读取一行字符,读到终止符时会将'0'存入结果缓冲区中,作为输入的终止。
	{
		imgList.push_back(temp);//push_back()函数将一个新的元素加到vector的最后面,位置为当前最后一个元素的下一个元素
	}
	ofstream fout("caliberation_result.txt");//ofstream写操作(输出)保存标定结果的文件,fout()向文件中进行写操作 

角点提取模块

/*标定图片上的角点提取,即提取标定用特征点*/
	/******************************************/
	//读取每一幅图像,从中提取出角点,然后对角点进行亚像素精确化	
	cout << "开始提取角点......" << endl;//输入的图像,必须是8位的灰度或彩色图像
	//打印到软件界面的程序输出区(QTextEdit)
	ui.textEdit_shuchu->append("开始提取角点......");
	ui.textEdit_shuchu->append("遍历每一幅图片......");
	//cout.flush();//可以实答现立刻的输出
	cv::Size image_size;	//保存图片的大小
	int x = ui.lineEdit_x->text().toInt();
	int y = ui.lineEdit_y->text().toInt();
	int Length = ui.lineEdit_Length->text().toInt();
	//int x = 8;
	//int y = 11;
	cv::Size pattern_size = cv::Size(x, y);//标定板上每行、每列的角点数;测试图片中的标定板上内角点数为4*6
	vector<cv::Point2f>corner_points_buf;//建一个数组缓存检测到的角点,通常采用Point2f形式,缓存每幅图像上检测到的角点
	vector<cv::Point2f>::iterator corner_points_buf_ptr;
	vector<vector<cv::Point2f>>corner_points_of_all_imgs;//corner输出角点坐标,通常用cv::Point2f向量来保存,保存检测到的所有角点
	int image_num = 0;//定义整型变量,赋初值
	string filename;//定义字符串变量
	while (image_num < imgList.size())
	{
		filename = imgList[image_num++];//读取文件
		//string str1 = "image_num = ";
		//char* name;
		//sprintf(name, "%d", image_num);
		//string str2 = name;
		////string str = str1 + str2 + ".jpg";
		//QString qstr;
		//qstr = QString::fromStdString(str2);
		cout << "image_num = " << image_num << endl;// 用于观察检验输出
/*		ui.textEdit_shuchu->append(qstr);	*/										/* 输出检验*/
		cout << filename.c_str() << endl;

		//String转QString**
		QString qstr;
		qstr = QString::fromStdString(filename.c_str());
		ui.textEdit_shuchu->append(qstr);

		/*ui.textEdit_shuchu->setText("filename.c_str()");*/
		cv::Mat imageInput = cv::imread(filename.c_str());
		if (image_num == 1)	//读入第一张图片时获取图像宽高信息
		{
			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 (findChessboardCorners(imageInput, pattern_size, corner_points_buf) == 0)	//寻找图片中的角点
		{
			cout << "can not find chessboard corners!\n";//找不到角点
			ui.textEdit_shuchu->append("can not find chessboard corners!");
			exit(1);//非正常运行导致退出程序
		}
		else
		{
			cv::Mat gray;
			/*转换为灰度图像*/
			cv::cvtColor(imageInput, gray, CV_RGB2GRAY);
			/* 亚像素精确化 */
			cv::find4QuadCornerSubpix(gray, corner_points_buf, cv::Size(Length, Length));	//find4QuadCornerSubpix()函数实现亚像素角点检测,对粗提取的角点进行精确化
			corner_points_of_all_imgs.push_back(corner_points_buf);	//保存亚像素角点
																	/* 在图像上显示角点位置 */
			cv::drawChessboardCorners(gray, pattern_size, corner_points_buf, true);		//在图片上画出检测到的角点。
			cv::imshow("camera calibration", gray);	//显示图片
			cv::waitKey(100);//暂停0.1S	
		}
	}
	int total = corner_points_of_all_imgs.size();
	cout << "total=" << total << endl;
	int cornerNum = pattern_size.width * pattern_size.height;//每张图片上的总的角点数
	for (int i = 0; i < total; i++)
	{
		cout << "-->第" << i + 1 << "幅图片的数据 -->:" << endl;
		for (int j = 0; j < cornerNum; j++)
		{
			//输出所有的角点
			cout << "-->" << corner_points_of_all_imgs[i][j].x;
			cout << "-->" << corner_points_of_all_imgs[i][j].y;
			if ((j + 1) % 3 == 0)
			{
				cout << endl;
			}
			else
			{
				cout.width(10);
			}
		}
		cout << endl;
	}

	cout << endl << "角点提取完成" << endl;
	ui.textEdit_shuchu->append("角点提取完成");

相机标定模块

/*摄像机标定*/
	/****************************/

	cout << "开始摄像机标定………………" << endl;
	ui.textEdit_shuchu->append("开始摄像机标定......");
	/*为标定参数分配内存*/
	cv::Mat cameraMatrix = cv::Mat(3, 3, CV_32FC1, cv::Scalar::all(0));//内外参矩阵,H--单应性矩阵
	cv::Mat distCoefficients = cv::Mat(1, 5, CV_32FC1, cv::Scalar::all(0));//摄像机的5个畸变系数:k1,k2,p1,p2,k3

	vector<cv::Mat>tvecsMat;//每幅图像的平移向量,t
	vector<cv::Mat>rvecsMat;//每幅图像的旋转向量(罗德里格旋转向量)
	vector<vector<cv::Point3f>> objectPoints;//保存所有图片的角点的三维坐标,初始化每一张图片中标定板上角点的三维坐标

	int i, j, k;
	for (k = 0; k < image_num; k++)//遍历每一张图片
	{
		vector<cv::Point3f> tempCornerPoints;//每一幅图片对应的角点数组
											 //遍历所有的角点
		for (i = 0; i < pattern_size.height; i++)
		{
			for (j = 0; j < pattern_size.width; j++)
			{
				cv::Point3f singleRealPoint;//一个角点的坐标
				singleRealPoint.x = i * 10;
				singleRealPoint.y = j * 10;
				singleRealPoint.z = 0;//假设z=0
				tempCornerPoints.push_back(singleRealPoint);
			}
		}
		objectPoints.push_back(tempCornerPoints);
	}

	cv::calibrateCamera(objectPoints, corner_points_of_all_imgs, image_size, cameraMatrix, distCoefficients, rvecsMat, tvecsMat, 0);
	cout << "标定完成" << endl;
	ui.textEdit_shuchu->append("标定完成");

保存标定结果

/*开始保存标定结果*/
	/***********************************/
	cout << "开始保存标定结果" << endl;
	ui.textEdit_shuchu->append("开始保存标定结果");
	//相机内外参数
	cout << endl << "相机相关参数:" << endl;
	fout << "相机相关参数:" << endl;
	cout << "1.内外参矩阵:" << endl;
	fout << "1.内外参矩阵:" << endl;
	cout << "大小:" << cameraMatrix.size() << endl;
	fout << "大小:" << cameraMatrix.size() << endl;
	cout << cameraMatrix << endl;
	fout << cameraMatrix << endl;

	//相机畸变系数
	cout << "2.畸变系数:" << endl;
	fout << "2.畸变系数:" << endl;
	cout << "大小:" << distCoefficients.size() << endl;
	fout << "大小:" << distCoefficients.size() << endl;
	cout << distCoefficients << endl;
	fout << distCoefficients << endl;

	//图像相关参数
	cout << endl << "图像相关参数:" << endl;
	fout << endl << "图像相关参数:" << endl;
	cv::Mat rotation_Matrix = cv::Mat(3, 3, CV_32FC1, cv::Scalar::all(0));//旋转矩阵
	for (i = 0; i < image_num; i++)
	{
		//旋转矩阵
		cout << "第" << i + 1 << "幅图像的旋转向量:" << endl;
		fout << "第" << i + 1 << "幅图像的旋转向量:" << endl;
		cout << rvecsMat[i] << endl;
		fout << rvecsMat[i] << endl;
		cout << "第" << i + 1 << "幅图像的旋转矩阵:" << endl;
		fout << "第" << i + 1 << "幅图像的旋转矩阵:" << endl;
		cv::Rodrigues(rvecsMat[i], rotation_Matrix);//将旋转向量转换位相对应的旋转矩阵
													//平移向量
		cout << rotation_Matrix << endl;
		fout << rotation_Matrix << endl;
		cout << "第" << i + 1 << "幅图像的平移向量:" << endl;
		fout << "第" << i + 1 << "幅图像的平移向量:" << endl;
		cout << tvecsMat[i] << endl;
		fout << tvecsMat[i] << endl;
	}

	cout << "结果保存完毕" << endl;
	ui.textEdit_shuchu->append("结果保存完毕");

结果评价模块

/*对标定结果进行评价*/
	/*************************************/

	cout << "开始评价标定结果…………" << endl;
	ui.textEdit_shuchu->append("开始评价标定结果......");

	//计算每幅图像中的角点数量,假设全部角点都检测到了
	int corner_points_counts;
	/*角点总数*/
	corner_points_counts = pattern_size.width * pattern_size.height;

	cout << "每幅图像的标定误差:" << endl;
	fout << "每幅图像的标定误差:" << endl;
	double err = 0;//单张图像的误差
	double total_err = 0;//所有图像的平均误差
	for (i = 0; i < image_num; i++)
	{
		vector<cv::Point2f> image_points_calculated;//存放新的计算出得投影点的坐标
		vector<cv::Point3f> tempPointSet = objectPoints[i];
		/*通过得到的摄像机内外参数,对空间的三维点进行重新投影计算,得到新的投影点*/
		cv::projectPoints(tempPointSet, rvecsMat[i], tvecsMat[i], cameraMatrix, distCoefficients, image_points_calculated);
		/*计算新的投影点与旧的投影点之间的误差*/
		vector<cv::Point2f> image_points_old = corner_points_of_all_imgs[i];
		/*将两组数据换成Mat格式*/
		cv::Mat image_points_calculated_mat = cv::Mat(1, image_points_calculated.size(), CV_32FC2);
		cv::Mat image_points_old_mat = cv::Mat(1, image_points_old.size(), CV_32FC2);
		for (j = 0; j < tempPointSet.size(); j++)
		{
			image_points_calculated_mat.at<cv::Vec2f>(0, j) = cv::Vec2f(image_points_calculated[j].x, image_points_calculated[j].y);
			image_points_old_mat.at<cv::Vec2f>(0, j) = cv::Vec2f(image_points_old[j].x, image_points_old[j].y);
		}
		err = cv::norm(image_points_calculated_mat, image_points_old_mat, cv::NORM_L2);
		err /= corner_points_counts;
		total_err += err;
		cout << "第" << i + 1 << "幅图像的平均误差:" << err << "像素" << endl;
		fout << "第" << i + 1 << "幅图像的平均误差:" << err << "像素" << endl;
	}
	cout << "总体平均误差:" << total_err / image_num << "像素" << endl;
	fout << "总体平均误差:" << total_err / image_num << "像素" << endl;
	cout << "评价完成" << endl;
	ui.textEdit_shuchu->append("评价完成");

	fout.close();

矫正图像模块

	/*矫正图像*/
	/*******************************************/
	cv::Mat mapx = cv::Mat(image_size, CV_32FC1);
	cv::Mat mapy = cv::Mat(image_size, CV_32FC1);
	cv::Mat R = cv::Mat::eye(3, 3, CV_32F);
	cout << "保存矫正图像" << endl;
	ui.textEdit_shuchu->append("保存矫正图像");
	string imageFileName;
	std::stringstream StrStm;
	for (int i = 0; i < image_num; i++)
	{
		cout << "Frame #" << i + 1 << endl;
		cv::initUndistortRectifyMap(cameraMatrix, distCoefficients, R, cameraMatrix, image_size, CV_32FC1, mapx, mapy);
		cv::Mat src_image = cv::imread(imgList[i].c_str(), 1);
		cv::Mat new_image = src_image.clone();
		cv::remap(src_image, new_image, mapx, mapy, cv::INTER_LINEAR);
		imshow("original image", src_image);
		imshow("Dedistorted image", new_image);

		StrStm.clear();
		imageFileName.clear();
		StrStm << i + 1;
		StrStm >> imageFileName;
		imageFileName += "_d.jpg";
		cv::imwrite(imageFileName, new_image);

		cv::waitKey(200);
	}
	cout << "保存结束" << endl;
	ui.textEdit_shuchu->append("保存结束");
	cv::waitKey(0);

}

参数显示模块

//显示参数按键函数定义******************************************
void camcali::on_pushButton_canshu_clicked()
{
	QString displayString;
	QFile file("caliberation_result.txt");
	if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
	{
		qDebug() << "Can't open the file!" << endl;
		ui.textEdit_shuchu->append("Can't open the file!");
	}
	while (!file.atEnd())
	{
		QByteArray line = file.readLine();
		QString str(line);
		qDebug() << str;
		ui.textEdit_shuchu->append(str);
		displayString.append(str);
	}
	ui.textEdit_canshu->clear();
	ui.textEdit_canshu->setPlainText(displayString);
}

上一篇:

下一篇: