- 说在前面
操作系统:win10
vs 版本:2017
opencv版本:4.0.1
opencv-contrb版本:4.0.1
- 运行结果
- 主要函数
OpenCV: ArUco Marker Detection
calibrateCameraAruco(相机校准)
estimatePoseSingleMarkers (单标记姿态估计)
drawAxis(绘制坐标系轴)
- 代码-生成ChAruco (这里使用官方提供的代码,这里)
若使用visual studio,可在属性中添加参数("chboard.png" -w=5 -h=7 -sl=200 -ml=120 -d=10)
使用ChArUco原因:相机校准更加准确。
- 代码-校准相机并保存参数(这里使用官方提供的代码,这里)
若使用visual studio,可在属性中添加参数("camera.yml" -dp="detector_params.yml" -w=5 -h=7 -sl=0.04 -ml=0.02 -d=10)
detector_params.yml 官方也提供了,放在工作目录(源代码路径)下即可
%YAML:1.0
nmarkers: 1024
adaptiveThreshWinSizeMin: 3
adaptiveThreshWinSizeMax: 23
adaptiveThreshWinSizeStep: 10
adaptiveThreshWinSize: 21
adaptiveThreshConstant: 7
minMarkerPerimeterRate: 0.03
maxMarkerPerimeterRate: 4.0
polygonalApproxAccuracyRate: 0.05
minCornerDistance: 10.0
minDistanceToBorder: 3
minMarkerDistance: 10.0
minMarkerDistanceRate: 0.05
cornerRefinementMethod: 0
cornerRefinementWinSize: 5
cornerRefinementMaxIterations: 30
cornerRefinementMinAccuracy: 0.1
markerBorderBits: 1
perspectiveRemovePixelPerCell: 8
perspectiveRemoveIgnoredMarginPerCell: 0.13
maxErroneousBitsInBorderRate: 0.04
minOtsuStdDev: 5.0
errorCorrectionRate: 0.6
程序运行后,点一下窗口,按下“c”捕捉当前帧作为校准数据,大概10帧左右(多角度)就可以了;然后按下"esc"键退出并将结果保存至camera.yml。
- 代码-验证校准结果
#include <opencv2\highgui.hpp>
#include <opencv2\videoio.hpp>
#include <opencv2\aruco.hpp>
#include <opencv2\aruco\dictionary.hpp>
#include <opencv2\aruco\charuco.hpp>
#include <opencv2\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\opencv.hpp>
#include <vector>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
cv::VideoCapture inputVideo(1);//外置摄像头,自带摄像头请使用0
//VideoWriter writer("VideoTest.avi", VideoWriter::fourcc('M', 'J', 'P', 'G'), 25.0, Size(640, 480));
cv::Mat cameraMatrix, distCoeffs; // 相机参数
FileStorage fs("camera.yml", FileStorage::READ);//读取相机参数
if (!fs.isOpened())
{
cout << "Could not open the configuration file!" << endl;
exit(1);
}
fs["camera_matrix"] >> cameraMatrix;
fs["distortion_coefficients"] >> distCoeffs;
fs.release();
cout << cameraMatrix << endl;
cout << distCoeffs << endl;
Ptr<aruco::Dictionary> dictionary =
aruco::getPredefinedDictionary(cv::aruco::DICT_4X4_50);//创建字典
while (inputVideo.grab()) {
unsigned int i = 0;
cv::Mat image, imageCopy;
inputVideo.retrieve(image);
image.copyTo(imageCopy);
std::vector<int> ids;
std::vector<std::vector<cv::Point2f> > corners;
cv::aruco::detectMarkers(image, dictionary, corners, ids);// 检测markers
if (ids.size() > 0) {
cv::aruco::drawDetectedMarkers(imageCopy, corners, ids);
vector< Vec3d > rvecs, tvecs;//得到旋转矢量以及平移矢量
cv::aruco::estimatePoseSingleMarkers(corners, 100, cameraMatrix, distCoeffs, rvecs, tvecs);
for (i = 0; i < ids.size(); i++)
cv::aruco::drawAxis(imageCopy, cameraMatrix, distCoeffs, rvecs[i], tvecs[i], 50);// 画方向轴
//writer << imageCopy;
}
cv::imshow("out", imageCopy);
char key = (char)cv::waitKey(20);
if (key == 'b') break;
}
return 0;
}