opencv 4.4
vs2017
代码是借用人家的,具体哪篇也忘了~
程序运行后按Y键持续检测角点直到输出
角点找不到的原因分析 这里设置标定板的角点数错误,行列应该设置为你标定板最大格数-1,我的标定板是7行10列这里就设置(6,9)
另外还有可能标定板离的太近
Size patternsize = Size(6,9); /* 标定板上每行、列的角点数 */
另外个容易出问题的地方在这里 COLOR_RGB2GRAY,由于opencv版本的变化这里可能会报错,老的版本可能是cv::CV_RGB2GRAY,主体意思就是把传进来的图片变成灰度图
cvtColor(imageInput, gray, COLOR_RGB2GRAY);
#include "pch.h"
#include
#include
#include "opencv2/opencv_modules.hpp"
#include
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include
#include "opencv2/stitching/detail/autocalib.hpp"
#include "opencv2/stitching/detail/blenders.hpp"
#include "opencv2/stitching/detail/timelapsers.hpp"
#include "opencv2/stitching/detail/camera.hpp"
#include "opencv2/stitching/detail/exposure_compensate.hpp"
#include "opencv2/stitching/detail/matchers.hpp"
#include "opencv2/stitching/detail/motion_estimators.hpp"
#include "opencv2/stitching/detail/seam_finders.hpp"
#include "opencv2/stitching/detail/warpers.hpp"
#include "opencv2/stitching/warpers.hpp"
#include "opencv2/xfeatures2d.hpp"
#include
#include
#include
using namespace std;
using namespace cv;
using namespace cuda;
using namespace cv;
using namespace std;
int main() {
int image_count = 1; /* 图像数量 */
Size image_size; /* 图像的尺寸 */
Size patternsize = Size(6,9); /* 标定板上每行、列的角点数 */
vector> corner_all; /* 保存检测到的所有角点 */
VideoCapture capture;
capture.open(0);
// 原图像
Mat imageInput;// = imread("F://fisheye.png");
for (int i = 0; i < image_count;)
{
capture >> imageInput;
if (imageInput.empty())
{
cout << "empty image!!!\n";
return 0;
}
imshow("src", imageInput);
// 只是为了获得键盘而已
switch (waitKey(10))
{
case 'q':
return 0;
break;
case 'y':
break;
default:
continue;
break;
}
i++;
// 用于观察检验输出
printf("第%d张图片\t", i);
if (i == 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;
}
Mat gray;
cvtColor(imageInput, gray, COLOR_RGB2GRAY);
vector corner_single; /* 缓存每幅图像上检测到的角点 */
/* 提取角点 */
bool patternfound = findChessboardCornersSB(gray, patternsize, corner_single); //findChessboardCorners(gray, patternsize, corner_single);
// 如果找到了
if (patternfound)
{
/* 亚像素精确化 */
TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER , 100, 0.101);
cornerSubPix(gray, corner_single, Size(10, 10), Size(-1, -1), criteria);
corner_all.push_back(corner_single); //保存亚像素角点
/* 在图像上显示角点位置 */
drawChessboardCorners(gray, patternsize, corner_single, patternfound); //用于在图片中标记角点
imshow("drawChessboardCorners", gray); //显示图片
}
else
{
cout << "can not find chessboard corners!\n"; //找不到角点
i--;
continue;
}
cout << "\n******************\n";
}
int total = corner_all.size();
cout << "已收集的棋盘图个数:" << total << endl;
/***************************** 以下是摄像机标定 ************************************************/
cout << "\n[开始标定]>>>>>>\n";
Size square_size = Size(10, 10); /* 实际测量得到的标定板上每个棋盘格的大小 */
/* calibrateCamera的参数 */
vector> object_points; /* 保存标定板上角点的三维坐标 */
// imagePoints
// imageSize上面已经获得
Mat cameraMatrix = Mat(3, 3, CV_32FC1, Scalar::all(0)); /* 摄像机内参数矩阵 */
Mat distCoeffs = Mat(1, 5, CV_32FC1, Scalar::all(0)); /* 摄像机的5个畸变系数:k1,k2,p1,p2,k3 */
vector rvecs; /* 每幅图像的旋转向量 */
vector tvecs; /* 每幅图像的平移向量 */
/* 初始化标定板上角点的三维坐标 */
for (int count = 0; count < image_count; count++)
{
vector single_object_points;
// 每列
for (int i = 0; i < patternsize.height; i++)
{
// 每行
for (int j = 0; j < patternsize.width; j++)
{
Point3f realPoint;
/* 假设标定板放在世界坐标系中z=0的平面上 */
realPoint.x = i * square_size.width;
realPoint.y = j * square_size.height;
realPoint.z = 0;
single_object_points.push_back(realPoint);
}
}
object_points.push_back(single_object_points);
}
calibrateCamera(object_points, corner_all, image_size, cameraMatrix, distCoeffs, rvecs, tvecs);
cout << "[标定完成]\n";
/*********************************** 对标定结果进行评价 **********************************************/
cout << "\n[开始评价标定结果]>>>>>>\n";
//每张图片上总的角点数
int cornerNum = patternsize.width * patternsize.height;
double err_single = 0.0; /* 每幅图像的误差 */
double err_total = 0.0; /* 所有图像的误差的总和 */
double err_mean = 0.0; /* 所有图像的平均误差 */
vector imagePoints2; /* 保存重新计算得到的投影点 */
for (int i = 0; i < image_count; i++)
{
/* 通过得到的摄像机内外参数,对空间的三维点进行重新投影计算,得到新的投影点 */
projectPoints(object_points[i], rvecs[i], tvecs[i], cameraMatrix, distCoeffs, imagePoints2);
/* 计算新的投影点和旧的投影点之间的误差*/
// 每张图像的角点
vector corner_single = corner_all[i];
// 声明原结果的角点矩阵
Mat mat_corner_single = Mat(1, corner_single.size(), CV_32FC2);
// 声明评测结果的角点矩阵
Mat mat_imagePoints2 = Mat(1, imagePoints2.size(), CV_32FC2);
// 每个角点
for (int j = 0; j < corner_single.size(); j++)
{
// 给原结果的角点矩阵赋值
mat_corner_single.at(0, j) = Vec2f(corner_single[j].x, corner_single[j].y);
// 给评测结果的角点矩阵赋值
mat_imagePoints2.at(0, j) = Vec2f(imagePoints2[j].x, imagePoints2[j].y);
}
// 取2范数
err_single = norm(mat_imagePoints2, mat_corner_single, NORM_L2);
err_total += err_single;
}
// 平均误差
err_mean = err_total / cornerNum;
cout << "[总体平均误差]:" << err_mean << "像素" << endl;
cout << "[评价完成!]" << endl;
cout << "cameraMatrix:\n"
<< cameraMatrix << endl;
cout << "distCoeffs:\n"
<< distCoeffs << endl;
/************************ 显示定标结果 ******************************/
cout << "[矫正图像]>>>>>>" << endl;
Mat result;
undistort(imageInput, result, cameraMatrix, distCoeffs);
imshow("result", result);
waitKey();
return 0;
}
运行结果:
控制台输出结果图
相机原始图像
灰度后取角点并画出
输出结果信息
实际看到的输出结果还是畸变的 这里要再看了,代码只是验证大致矫正流程
另外是了下海康的鱼眼相机,也是可以的 效果emmmmm一般般 还有很多改进的地方