图像变换中的点变换小结
#include <opencv2/opencv.hpp> #include <iostream> // 20251105 透视变换逆变换 // 输入:透视变换后图片上一点 + 透视变换矩阵 // 输出:透视变换前图片上对应点 int perspInv(cv::Point2f centerPt, cv::Mat M, cv::Point2f& centerPt2) { cv::Mat srcT = cv::Mat::zeros(cv::Size(1, 1), CV_32FC2); srcT.at<cv::Vec2f>(0, 0)[0] = centerPt.x; srcT.at<cv::Vec2f>(0, 0)[1] = centerPt.y; cv::Mat M_inv; cv::invert(M, M_inv); cv::Mat srcT_inv; cv::perspectiveTransform(srcT, srcT_inv, M_inv); centerPt2.x = srcT_inv.at<cv::Vec3f>(0, 0)[0]; centerPt2.y = srcT_inv.at<cv::Vec3f>(0, 0)[1]; return 0; } void perspInv2(const cv::Point2f& centerPt, const cv::Mat& M, cv::Point2f& centerPt2) { cv::Mat M_inv; cv::invert(M, M_inv); std::vector<cv::Point2f> srcF{centerPt}, srcT; cv::perspectiveTransform(srcF, srcT, M_inv); centerPt2 = srcT[0]; } // 20251105 去畸变逆变换 // 输入:去畸变后图片上一点 + 相机参数 // 输出:去畸变前图片上对应点 int undistInv(cv::Point2f centerPt2, cv::Mat cameraMat, cv::Mat distCoeffs, cv::Point2f& centerPt3) { double cx = cameraMat.at<double>(0, 2); double cy = cameraMat.at<double>(1, 2); double fx = cameraMat.at<double>(0, 0); double fy = cameraMat.at<double>(1, 1); double k1 = distCoeffs.at<double>(0, 0); double k2 = distCoeffs.at<double>(0, 1); double k3 = distCoeffs.at<double>(0, 4); double p1 = distCoeffs.at<double>(0, 2); double p2 = distCoeffs.at<double>(0, 3); double xx = static_cast<double>(centerPt2.x); double yy = static_cast<double>(centerPt2.y); xx = (xx - cx) / fx; yy = (yy - cy) / fy; double rr = xx * xx + yy * yy; double xxx = xx * (1 + k1 * rr + k2 * rr * rr + k3 * rr * rr * rr) + 2 * p1 * xx * yy + p2 * (rr + 2 * xx * xx); double yyy = yy * (1 + k1 * rr + k2 * rr * rr + k3 * rr * rr * rr) + 2 * p2 * xx * yy + p1 * (rr + 2 * yy * yy); centerPt3.x = static_cast<double>(fx * xxx + cx); centerPt3.y = static_cast<double>(fy * yyy + cy); return 0; } // 20251106 透视变换逆变换+去畸变逆变换 // 输入:透视变换后图片上一点 + 透视变换矩阵 + 相机参数 // 输出:去畸变前图片上对应点 int perspInvAndUndistInv(cv::Point2f centerPt, cv::Mat cameraMat, cv::Mat distCoeffs, cv::Mat M, cv::Point2f& centerPt3) { cv::Mat srcT = cv::Mat::zeros(cv::Size(1, 1), CV_32FC2); srcT.at<cv::Vec2f>(0, 0)[0] = centerPt.x; srcT.at<cv::Vec2f>(0, 0)[1] = centerPt.y; cv::Mat M_inv; cv::invert(M, M_inv); cv::Mat srcT_inv; cv::perspectiveTransform(srcT, srcT_inv, M_inv); cv::Point2f centerPt2; centerPt2.x = srcT_inv.at<cv::Vec3f>(0, 0)[0]; centerPt2.y = srcT_inv.at<cv::Vec3f>(0, 0)[1]; double cx = cameraMat.at<double>(0, 2); double cy = cameraMat.at<double>(1, 2); double fx = cameraMat.at<double>(0, 0); double fy = cameraMat.at<double>(1, 1); double k1 = distCoeffs.at<double>(0, 0); double k2 = distCoeffs.at<double>(0, 1); double k3 = distCoeffs.at<double>(0, 4); double p1 = distCoeffs.at<double>(0, 2); double p2 = distCoeffs.at<double>(0, 3); double xx = static_cast<double>(centerPt2.x); double yy = static_cast<double>(centerPt2.y); xx = (xx - cx) / fx; yy = (yy - cy) / fy; double rr = xx * xx + yy * yy; double xxx = xx * (1 + k1 * rr + k2 * rr * rr + k3 * rr * rr * rr) + 2 * p1 * xx * yy + p2 * (rr + 2 * xx * xx); double yyy = yy * (1 + k1 * rr + k2 * rr * rr + k3 * rr * rr * rr) + 2 * p2 * xx * yy + p1 * (rr + 2 * yy * yy); centerPt3.x = static_cast<double>(fx * xxx + cx); centerPt3.y = static_cast<double>(fy * yyy + cy); return 0; } // 20251105 去畸变+透视变换 // 输入:去畸变前图片上一点 + 相机参数 // 输出:去畸变+透视变换后图片上对应点 int undistAndPersp(cv::Point2f centerPt3, cv::Mat cameraMat, cv::Mat distCoeffs, cv::Mat M, cv::Point2f& centerPt) { std::vector<cv::Point2f> fromPts; fromPts.push_back(centerPt3); std::vector<cv::Point2f> toPts; cv::undistortPoints(fromPts, toPts, cameraMat, distCoeffs, cv::Mat(), cameraMat); cv::Mat srcF = cv::Mat::zeros(cv::Size(1, 1), CV_32FC2); srcF.at<cv::Vec3f>(0, 0)[0] = toPts[0].x; srcF.at<cv::Vec3f>(0, 0)[1] = toPts[0].y; cv::Mat srcT; cv::perspectiveTransform(srcF, srcT, M); centerPt.x = srcT.at<cv::Vec3f>(0, 0)[0]; centerPt.y = srcT.at<cv::Vec3f>(0, 0)[1]; return 0; } // 透视点变换 void persp(const cv::Point2f& srcPt, const cv::Mat& M, cv::Point2f& dstPt) { // 合法性校验,避免perspectiveTransform崩溃 CV_Assert(M.type() == CV_64F && M.size() == cv::Size(3, 3)); std::vector<cv::Point2f> src{srcPt}, dst; cv::perspectiveTransform(src, dst, M); dstPt = dst[0]; } // 透视点变换2 void persp2(const cv::Point2f& srcPt, const cv::Mat& M, cv::Point2f& dstPt) { CV_Assert(M.type() == CV_64F && M.rows == 3 && M.cols == 3); const double* m = M.ptr<double>(); float x = srcPt.x; float y = srcPt.y; // 齐次坐标分母 double w = m[6] * x + m[7] * y + m[8]; if (std::abs(w) < 1e-9) { // 无穷远点,可自定义处理,这里置0 dstPt = cv::Point2f(0, 0); return; } double nx = m[0] * x + m[1] * y + m[2]; double ny = m[3] * x + m[4] * y + m[5]; dstPt.x = static_cast<float>(nx / w); dstPt.y = static_cast<float>(ny / w); } int main() { return 0; }