首页 > 编程语言 >畸变矫正、透视变换加速(OpenCV C++)

畸变矫正、透视变换加速(OpenCV C++)

时间:2022-10-23 20:12:43浏览次数:72  
标签:fs Mat C++ distortion transMat OpenCV 畸变 intrinsic matrix

前两周,同事和我说检测时间超时,其中对图像做畸变矫正和投影变换就要花费25ms(3000×3000的图)。而此时我们已经用上了文章opencv图像畸变矫正加速、透视变换加速方法总结中的方法。突然我想到了我去年笔记OpenCV笔记(10) 相机模型与标定中的一个函数cv::undistortPoints(),对感兴趣点进行畸变矫正。在应用之前,需要测试下两种方法计算出来的点的差值,即remap和undistortPoints的不同。结论:对全图进行畸变矫正,再找点 VS 找点后,对点进行畸变矫正,两者的差值小于0.1个像素,可行!同样的方法可以运用在投影变换上。在尺寸测量方面,这样可以节省掉畸变矫正和投影变换的时间。

1 只对感兴趣的点进行畸变矫正

// 读取相机参数文件
FileStorage fs("D:/distortionLens.xml", FileStorage::READ);
Mat intrinsic_matrix = Mat(3, 3, CV_32FC1, Scalar::all(0));
Mat distortion_coeffs = Mat(1, 5, CV_32FC1, Scalar::all(0));
fs["intrinsic_matrix"] >> intrinsic_matrix;
fs["distortion_coeffs"] >> distortion_coeffs;
Mat mapx = Mat(s, CV_32FC1);
Mat mapy = Mat(s, CV_32FC1);
// 根据内参和畸变系数,建立查找表
//intrinsic_matrix = getOptimalNewCameraMatrix(intrinsic_matrix, distortion_coeffs, s, 1, s, 0);
initUndistortRectifyMap(intrinsic_matrix, distortion_coeffs, Mat(),
intrinsic_matrix, s, CV_32FC1, mapx, mapy);
// 方法1:畸变矫正后找角点
Mat distortionMat;
remap(src, distortionMat, mapx, mapy, INTER_CUBIC);
vector<Point2f> distortPoints;
findChessboardCornersSB(src, Size(21, 21), distortPoints, 64);
// 方法2:找角点后畸变矫正
vector<Point2f> oriPoints, sparsePoints;
findChessboardCornersSB(src, Size(21, 21), oriPoints, 64);
undistortPoints(oriPoints, sparsePoints, intrinsic_matrix, distortion_coeffs, Mat(), intrinsic_matrix);
// 打印比较
cout << "     原图找角点     " << "\t" << "  原图remap后找角点  " << "\t" << "  对原图角点矫正  " << endl;
for (int i = 0; i < sparsePoints.size(); i++) {
    cout << oriPoints[i] << "\t" << distortPoints[i] << "\t" << sparsePoints[i] << "\t" << "差值:" << distortPoints[i] - sparsePoints[i] << endl;
}

部分数据如下所示,可以看出,两者差值小于0.1个像素,加速10ms完成,接下来再对投影变换加速一下。

2 只对感兴趣的点进行投影变换

// 读取变换矩阵
fs = FileStorage("D:/transMat.txt", FileStorage::READ);
Mat transMat = Mat(3, 3, CV_32FC1, Scalar::all(0));
fs["transMat"] >> transMat;
	
// 方法1:进行透视变换后找角点
Mat warpMat;
warpPerspective(src, warpMat, transMat, s, INTER_LINEAR, BORDER_CONSTANT, Scalar(255));
vector<Point2f> warpPoints;
findChessboardCornersSB(warpMat,Size(21, 21), warpPoints, 64);
// 方法2:找角点后进行透视变换
vector<Point2f> outPoints;
for (int i = 0; i < oriPoints.size(); i++) {
	Mat_<double> oriPoint(3, 1);
	oriPoint(0, 0) = oriPoints[i].x;
	oriPoint(1, 0) = oriPoints[i].y;
	oriPoint(2, 0) = 1;
	Mat dstPoints = transMat * oriPoint;
	double a1 = dstPoints.at<double>(0, 0);
	double a2 = dstPoints.at<double>(1, 0);
	double a3 = dstPoints.at<double>(2, 0);
	outPoints.push_back(Point2f(a1 * 1.0 / a3, a2 * 1.0 / a3));
}
//打印 cout << " 原图找角点 " << "\t" << " 原图透视变换后找角点 " << "\t" << " 对原图角点变换 " << endl; for (int i = 0; i < sparsePoints.size(); i++) { cout << oriPoints[i] << "\t" << warpPoints[i] << "\t" << outPoints[i] << "\t" << "差值:" << distortPoints[i] - sparsePoints[i] << endl; }

 

3 合并

3.1 读取文件

void GetMap()
{
	FileStorage fs(path+"distortionLens.xml", FileStorage::READ);
	if (fs.isOpened())
	{
		intrinsic_matrix = Mat(3, 3, CV_64FC1, Scalar::all(0));
		distortion_coeffs = Mat(1, 5, CV_64FC1, Scalar::all(0));
		fs["intrinsic_matrix"] >> intrinsic_matrix;
		fs["distortion_coeffs"] >> distortion_coeffs;
	}
	fs = FileStorage(path+"transMat.txt", FileStorage::READ);
	if (fs.isOpened())
	{
		transMat = Mat(3, 3, CV_64FC1, Scalar::all(0));
		fs["transMat"] >> transMat;
	}
}

3.2 变换感兴趣点

void remapPoints(vector<Point2f>& points) {
	for (int i = 0; i < points.size(); i++) {
		Mat_<double> oriPoint(3, 1);
		oriPoint(0, 0) = points[i].x;
		oriPoint(1, 0) = points[i].y;
		oriPoint(2, 0) = 1;
		Mat dstPoint = transMat * oriPoint;
		double a1 = dstPoint.at<double>(0, 0);
		double a2 = dstPoint.at<double>(1, 0);
		double a3 = dstPoint.at<double>(2, 0);
		points[i] = Point2f(a1 * 1.0 / a3, a2 * 1.0 / a3);
	}
	undistortPoints(points, points, intrinsic_matrix, distortion_coeffs, Mat(), intrinsic_matrix);

}

 

标签:fs,Mat,C++,distortion,transMat,OpenCV,畸变,intrinsic,matrix
From: https://www.cnblogs.com/Fish0403/p/16801563.html

相关文章

  • c/c++背景颜色和字体颜色
    https://blog.csdn.net/weixin_59266315/article/details/124482907?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIS......
  • c++算法竞赛常用板子集合(持续更新)
    前言本文主要包含算法竞赛一些常用的板子,码风可能不是太好,还请见谅。后续会继续补充没有的板子。当然我太菜了有些可能写不出来T^T稍微有些分类但不多,原谅我QwQ建议Ct......
  • C/C++抽红包系统
    C/C++抽红包系统(二)抽红包系统程序设计要求:1)都有菜单页,有用户登录和退出环节,有退出系统菜单项;2)采用结构体数组变量完成数据的储存(用动态分配结构体数组或单向链......
  • C++OOP课设
    C++OOP课设您的第一个任务是编写一个代码示例,该示例集成并演示了C++中OOP的以下方面:●通过使用多个类进行继承。这应该包括作为一个例子的多重继承,这在现实世界中并不一......
  • 实验三:数组、指针与现代C++
    实验任务五task.cpp#include"info.h"#include<iostream>#include<string>#include<vector>usingnamespacestd;intmain(){constintcapacity=100;v......
  • 实验3 数组、指针与现代C++标准库
    任务五info.hpp1#pragmaonce2#include<iostream>3#include<string>4#include<iomanip>5usingnamespacestd;6classinfo7{8public:9......
  • 实验三 数组、指针与现代C++标准库
    实验五代码:Info.hpp1#pragmaonce23#include<iostream>4#include<string>5#include<iomanip>67usingstd::string;8usingstd::cout;9us......
  • C/C++ 一维数组和二维数组参数传递的几种方式
    一维数组:#include<iostream>#include<windows.h>#include<string>usingnamespacestd;//在以下几种方法中,ages都不是真正的数组,实际上是一个指针int*agesint......
  • c++dump
    //Minidump.h#pragmaonceclassCMinidump{public: CMinidump(); ~CMinidump(); staticvoidCreateDumpFile(LPCSTRlpstrDumpFilePathName,EXCEPTION_POINTERS......
  • MD5 哈希加密算法 - C++ 实现
    MD5加密算法-C++实现写在前头:还在学习中!整个文档写的很匆忙,肯定还有很多不周到的地方.欢迎在评论中提出你的宝贵意见!!算法背景BackgroundMD5消息摘要算法......