使用OpenCV给图像去畸变
opencv
OpenCV: 开源计算机视觉库
项目地址:https://gitcode.com/gh_mirrors/opencv31/opencv
免费下载资源
·
-
相机畸变模型
我们计算畸变都是在归一化平面上进行的,下面的(x,y), (x_distort,y_distort)都是在归一化坐标,相机坐标(X,Y,Z)的归一化坐标(X/Z, Y/Z, 1)
1、径向畸变
由透镜形状引起的,畸变系数k1, k2, k3,畸变模型:
2、切向畸变
由镜片安装和成像平面不平行引起的,畸变系数p1, p2,切向畸变模型:
3、总的畸变模型
-
求解思路
我们得到的原图是畸变后的图像(x_distort,y_distort),要计算畸变之前的真实图像(x,y),不是用逆运算,太难麻烦了,而是计算真是图像畸变后会投影在哪,对应过去。先把原图像设置为一个空的图像,把一个个像素畸变投影过去,找到和畸变后图像像素点的对应关系(可以参考下面代码方法1理解)。 -
代码示例
注意,OpenCV畸变系数矩阵的默认顺序 [k1, k2, p1, p2, k3]
#include <opencv2/opencv.hpp> #include <chrono> using namespace std; int main(int argc, char **argv) { // 内参 double fx = 458.654, fy = 457.296, cx = 367.215, cy = 248.375; /**内参矩阵K * fx 0 cx * 0 fy cy * 0 0 1 */ // 畸变参数 double k1 = -0.28340811, k2 = 0.07395907, p1 = 0.00019359, p2 = 1.76187114e-05; cv::Mat image = cv::imread(argv[1], 0); // 图像是灰度图,CV_8UC1 int rows = image.rows, cols = image.cols; cv::Mat image_undistort = cv::Mat(rows, cols, CV_8UC1); // 方法1去畸变以后的图 cv::Mat image_undistort2 = cv::Mat(rows, cols, CV_8UC1); // 方法2 OpenCV去畸变以后的图 chrono::steady_clock::time_point t1 = chrono::steady_clock::now(); //! 方法1. 自己写计算去畸变后图像的内容 for (int v = 0; v < rows; v++) { for (int u = 0; u < cols; u++) { double x = (u - cx) / fx, y = (v - cy) / fy; //要求解的真实图,归一化平面上的坐标 double r = sqrt(x * x + y * y); double x_distorted = x * (1 + k1 * r * r + k2 * r * r * r * r) + 2 * p1 * x * y + p2 * (r * r + 2 * x * x); //畸变后归一化坐标 double y_distorted = y * (1 + k1 * r * r + k2 * r * r * r * r) + p1 * (r * r + 2 * y * y) + 2 * p2 * x * y; double u_distorted = fx * x_distorted + cx; //畸变后像素坐标,即原图 double v_distorted = fy * y_distorted + cy; // 投影赋值 if (u_distorted >= 0 && v_distorted >= 0 && u_distorted < cols && v_distorted < rows) //真实图畸变后仍然在图上的 { image_undistort.at<uchar>(v, u) = image.at<uchar>((int)v_distorted, (int)u_distorted); } else { image_undistort.at<uchar>(v, u) = 0; //这里最好用插值法 } } } chrono::steady_clock::time_point t2 = chrono::steady_clock::now(); chrono::duration<double> time_used = chrono::duration_cast<chrono::duration<double>>(t2 - t1); cout << "time = " << time_used.count() << endl; //! 方法2. OpenCV自带的undistort函数,更快速 cv::Mat K = cv::Mat::eye(3, 3, CV_32FC1); //内参矩阵 K.at<float>(0, 0) = fx; K.at<float>(1, 1) = fy; K.at<float>(0, 2) = cx; K.at<float>(1, 2) = cy; cv::Mat distort_coeffs = cv::Mat::zeros(1, 5, CV_32FC1); //畸变系数矩阵 顺序是[k1, k2, p1, p2, k3] distort_coeffs.at<float>(0, 0) = k1; distort_coeffs.at<float>(0, 1) = k2; distort_coeffs.at<float>(0, 2) = p1; distort_coeffs.at<float>(0, 3) = p2; cout << "K = " << endl << K << endl; cout << "distort_coeffs = " << endl << distort_coeffs << endl; t1 = chrono::steady_clock::now(); cv::undistort(image, image_undistort2, K, distort_coeffs); //去畸变 t2 = chrono::steady_clock::now(); time_used = chrono::duration_cast<chrono::duration<double>>(t2 - t1); cout << "time = " << time_used.count() << endl; // 展示去畸变后图像 cv::imshow("distorted", image); cv::imshow("undistorted", image_undistort); cv::imshow("image_undistort2", image_undistort2); cv::waitKey(0); return 0; }
GitHub 加速计划 / opencv31 / opencv
77.38 K
55.71 K
下载
OpenCV: 开源计算机视觉库
最近提交(Master分支:2 个月前 )
48668119
dnn: use dispatching for Winograd optimizations 1 天前
3dace76c
flann: remove unused hdf5 header 1 天前
更多推荐
已为社区贡献3条内容
所有评论(0)