当前位置: 首页 > news >正文

图像变换中的点变换小结

#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; }
http://www.jsqmd.com/news/1208132/

相关文章:

  • 深圳劳力士回收价格查询及各大回收平台实测排行(2026年7月最新) - 劳力士官方服务中心
  • ISO IEC 42001-2023 人工智能管理体系文件全套模板word
  • 2026南昌律师推荐|政企法务民商纠纷专业律师 - 信息热点
  • LevelUI实战项目:使用图形界面工具构建高效键值存储应用的10个步骤
  • 标准迭代升级!一文读懂Qi1.3与Qi2.0的核心区别
  • WMPageController常见问题解决方案:从基础到高级的10个技巧
  • 仲景中医AI:基于诊疗行为分解策略的中医大语言模型技术深度解析
  • autoDocstring安全最佳实践:保护代码文档的3个重要原则
  • 2026年7月最新——聊城靠谱防水公司推荐:实测对比后的客观结论 - 吉林同城获客
  • 劳力士中国官方售后服务中心|官方地址与客服热线权威信息通知(2026年7月更新) - 劳力士服务中心
  • Tropos多语言支持教程:如何为天气应用添加国际化支持
  • Andersen Consulting新增协作成员机构Smartbridge,进一步拓展咨询服务布局
  • 佛山本地轻法式高端全案设计2026业主口碑综合实力排行榜 - 十大品牌排行榜
  • 携号转网查询接口:短信营销精准触达的“破壁”利器
  • 乌鲁木齐新疆特产店怎么选?疆礼记新疆特产选购避坑指南 - 百航
  • 从零开始看懂计算机发展史,算盘到晶体管的演变逻辑
  • Chatterbox-TTS-Server:2024年最值得尝试的开源TTS服务,一键搭建AI语音生成平台
  • Bonsai-27B-mlx-1bit开发者指南:自定义模型训练与微调最佳实践
  • Timeliner插件开发教程:如何扩展动画时间线功能
  • 小程序毕设选题推荐:物资采购点单登记系统的设计与实现 基于 SpringBoot + 微信小程序的仓库库存点单申领小程序【附源码、mysql、文档、调试+代码讲解+全bao等】
  • 使用STM32操作独立按键控制 AT24C02 计数并用数码管显示
  • 本地部署LLM大模型:从数据安全到成本可控的实战指南
  • 上海劳力士回收小知识:保卡、表盒、票据到底能加多少价?上门还是到店更划算? - 商业每日快报
  • 2026年7月芝柏全国官方售后维修网点大全|热线电话门店地址预约养护一站式指南 - 博客万
  • DeepSeek-OCR Client部署完全手册:Windows/Linux/macOS跨平台安装配置终极指南
  • Upscayl终极指南:如何用免费开源AI工具让你的模糊图片变高清
  • 2026年7月最新——抚州靠谱防水公司推荐:实测对比后的客观结论 - 吉林同城获客
  • 江诗丹顿中国官方售后服务中心|官方地址与售后服务电话权威信息公告(2026年7月更新) - 江诗丹顿服务中心
  • Linux系统进阶:内核机制与性能调优实战指南
  • WSL2部署大模型:GPU加速与开发环境配置指南