VS C++基于OpenCV进行相机标定和使用

记录一下自己实现的过程

首先找到自己opencv所在的目录找:

 然后通过VS新创一个工作环境将以上红框的三个部分放入到新建环境下;

1、首先是对 camera_calibration.cpp进行修改:

在头文件下添加:#pragma warning(disable:4996) 命令,不然运行会出错

 将以上注释部分修改为红框部分, in_VID5.xml 就是我们在opencv中复制的文件,

2、修改in_VID5.xml文件:

这里有和多地方需要进行修改,我就直接放图片了:

 

3、修改VID5.xml里面的图片路径为自己图片的路径:

4、数据集的获取(自己进行拍摄其它博主建议是在16到25张):

(数据集这里一定要注意,尽量对着电脑拍)

 做完以上步骤直接运行camera_calibration.cpp文件,会有一个展示效果图和保存一个out_camera_data.xml文件,这就是我们所要使用的东西。

效果图(你训练时用了几张就会有集装效果图,这里就展示单个):

5、如何使用自己保存好的标定文件:


#include <opencv2/opencv.hpp>
#include <opencv2/calib3d/calib3d.hpp>
using namespace std;
using namespace cv;

/**
 * @主函数
 */
int main()
{

	/// 读取一副图片,不改变图片本身的颜色类型(该读取方式为DOS运行模式)
	Mat src = imread("3.jpg");
	imshow("1", src);
	Mat distortion = src.clone();
	imshow("2", distortion);
	Mat camera_matrix = Mat(3, 3, CV_32FC1);
	Mat distortion_coefficients;


	//导入相机内参和畸变系数矩阵
	FileStorage file_storage("out_camera_data.xml", FileStorage::READ);
	file_storage["camera_matrix"] >> camera_matrix;
	cout << camera_matrix << endl;
	file_storage["distortion_coefficients"] >> distortion_coefficients;
	cout << distortion_coefficients << endl;
	file_storage.release();

	//矫正
	undistort(src, distortion, camera_matrix, distortion_coefficients);

	imshow("img", src);
	imshow("undistort", distortion);
	//imwrite("undistort.jpg", distortion);

	waitKey(0);
	return 0;
}

效果对比:
原图:

 效果图:

参考:​​​​​​利用opencv3标定单目相机(图片标定)和畸变校正_Pichairen-CSDN博客

物体根据相机位置显示_OpenCV相机标定与畸变校正_自闭本科生的博客-CSDN博客

  • 9
    点赞
  • 83
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
前言: 开源的opencv真是一件伟大的产品,那么多个函数跟变量(具体多少还没数过)。要是结合起来综合运用几乎可以胜任任何有关图像识别和处理方面的工作。如果能更深入一点根据具体需要修改或优化里面的源码那更是如虎添翼。 花了点时间浏览了www.opencv.org.cn论坛里的所有贴子,还好不多才200多页。总体上对opencv里的一些常用函数功能作用大致有点了解,筛选一些跟元件识别有关的运用内容,但它论坛里的贴子回复的内容点到即止的居多。从网上下载了能搜到的教程跟代码全学习了解测试了一下,图像处理流程通常先开始都是要进行滤波,除燥,灰度,二值化后再轮廓识别等。 开始动手 经过多次好多次运行测试组合,终于有一次显示出意外的惊人效果,而且相当简单只是调用了几个函数而以,就可以有这样效果实在出人意料。第一个是进行元件中心点获取,也是直接调用函数再加点东西就可以得出元件的四个矩形顶点坐标,有这几个坐标就可以直接算出元件中间点所在的坐标了。如果要检测元件摆放角度是否是垂直90度,只要判断边宽的长度为最小或最大时就是垂直90度。 但这个矩形框无法测出元件具体角度。如截图: 测试视频地址:https://v.youku.com/v_show/id_XMjU5NzY5NTI0.html 不过,还有另外一个函数可以提供这个功能,调用后可以直接求出最小外接矩形和角度 如截图: 测试视频地址:https://v.youku.com/v_show/id_XMjYwMDMzMDc2.html 说明:里面的光源不行,临时用手电筒,和在光盘上插几个LED做环形灯做照明,无法做到无阴影显示。如果光源做的好,效果应该是非常精确稳定。 识别包含下面2种做法: opencv里需要的头文件跟库文件都已编译好放在和设置在当前程序目录下,就可不用安装opencv 也能直接编译。
下面是基于OpenCV实现机械臂和相机手眼标定C++代码示例: ```c++ #include <iostream> #include <opencv2/opencv.hpp> #include <opencv2/aruco.hpp> using namespace std; using namespace cv; int main() { // 读取相机图像 Mat cameraImage = imread("camera.jpg"); // 读取机械臂姿态数据 vector<Mat> robotPoses; for (int i = 1; i <= 10; i++) { string filename = "robot" + to_string(i) + ".txt"; Mat pose = Mat::zeros(4, 4, CV_64F); ifstream fin(filename); for (int j = 0; j < 4; j++) { for (int k = 0; k < 4; k++) { fin >> pose.at<double>(j, k); } } robotPoses.push_back(pose); } // 读取相机姿态数据 vector<Mat> cameraPoses; for (int i = 0; i < 5; i++) { string filename = "camera" + to_string(i) + ".txt"; Mat pose = Mat::zeros(4, 4, CV_64F); ifstream fin(filename); for (int j = 0; j < 4; j++) { for (int k = 0; k < 4; k++) { fin >> pose.at<double>(j, k); } } cameraPoses.push_back(pose); } // 棋盘格参数 int boardWidth = 9; // 棋盘格宽度 int boardHeight = 6; // 棋盘格高度 float squareSize = 25.0f; // 棋盘格大小(毫米) // 棋盘格角点坐标 vector<vector<Point3f>> objectPoints; for (int i = 0; i < robotPoses.size(); i++) { vector<Point3f> obj; for (int j = 0; j < boardHeight; j++) { for (int k = 0; k < boardWidth; k++) { obj.push_back(Point3f(j * squareSize, k * squareSize, 0)); } } objectPoints.push_back(obj); } // 计算机械臂末端执行器和相机之间的位姿矩阵 vector<Mat> robotToCameraPoses; for (int i = 0; i < robotPoses.size(); i++) { Mat robotPose = robotPoses[i]; Mat cameraPose = cameraPoses[i]; Mat robotToCameraPose = cameraPose.inv() * robotPose; robotToCameraPoses.push_back(robotToCameraPose); } // 相机标定 vector<vector<Point2f>> imagePoints; vector<int> markerIds; vector<vector<Point2f>> markerCorners; Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250); aruco::detectMarkers(cameraImage, dictionary, markerCorners, markerIds); aruco::drawDetectedMarkers(cameraImage, markerCorners, markerIds); vector<Vec3d> rvecs, tvecs; aruco::estimatePoseSingleMarkers(markerCorners, squareSize, cameraMatrix, distCoeffs, rvecs, tvecs); for (int i = 0; i < markerIds.size(); i++) { vector<Point2f> corners = markerCorners[i]; imagePoints.push_back(corners); } // 手眼标定 Mat R, T; solveHandEye(objectPoints, imagePoints, robotToCameraPoses, R, T); // 输出结果 cout << "Hand-eye calibration matrix:" << endl << R << endl << T << endl; return 0; } ``` 在这个示例中,我们首先读取了机械臂和相机的姿态数据,然后定义了棋盘格的参数和角点坐标,并通过`aruco::detectMarkers`和`aruco::estimatePoseSingleMarkers`函数检测和计算出相机图像中的标记物的位姿矩阵。接着,我们计算机械臂末端执行器和相机之间的位姿矩阵,并使用`solveHandEye`函数对机械臂和相机之间的转换矩阵进行计算,并输出结果。 需要注意的是,这个示例仅供参考,具体的实现还需要根据实际情况进行调整和优化,例如相机标定的方法和标记物的选择等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值