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

opencv remap inverse 这里的x,y是dst下的,所以我没法在知道src的x,y下得到该点在dst的位置.

opencv remap inverse

dst(x,y)=src(mapx(x,y),mapy(x,y))

这里的x,y是dst下的,所以我没法在知道src的x,y下得到该点在dst的位置.自行畸变校正,误差太大.

        cv::Mat ImgLeftToTrack, ImgRightToTrack;
        if (mSettings && mSettings->mbNeedToRectify) {
            cv::Mat MXL = mSettings->Map1X;
            cv::Mat MYL = mSettings->Map1Y;
            cv::Mat MXR = mSettings->Map2X;
            cv::Mat MYR = mSettings->Map2Y;
            cv::remap(ImgLeft, ImgLeftToTrack, MXL, MYL, cv::INTER_LINEAR, cv::BORDER_CONSTANT, 0);
            cv::remap(ImgRight, ImgRightToTrack, MXR, MYR, cv::INTER_LINEAR, cv::BORDER_CONSTANT, 0);
            cv::Mat DistCoef = mSettings->GetCamera1DistoCoef();
            float K1 = DistCoef.at<float>(0, 0),
                    K2 = DistCoef.at<float>(1, 0),
                    P1 = DistCoef.at<float>(2, 0),
                    P2 = DistCoef.at<float>(3, 0);
            for (int i = 0; i < vTarsInLeft.size(); i++) {
                cv::KeyPoint &kp = vTarsInLeft[i];
                float dOx = kp.pt.x * 1.0 / ImgLeftToTrack.cols, dOy = kp.pt.y * 1.0 / ImgLeftToTrack.rows;
                float dR = sqrt((dOx - 0.5) * (dOx - 0.5) + (dOy - 0.5) * (dOy - 0.5));
                kp.pt.x = (dOx * (1 + K1 * dR * dR + K2 * dR * dR * dR * dR) + 2 * P1 * dOx * dOy +
                           P2 * (dR * dR + 2 * dOx * dOx)) * ImgLeftToTrack.cols;
                kp.pt.y = (dOy * (1 + K1 * dR * dR + K2 * dR * dR * dR * dR) + 2 * P2 * dOx * dOy +
                           P1 * (dR * dR + 2 * dOy * dOy)) * ImgLeftToTrack.rows;
                cout << K1 << " " << K2 << " " << P1 << " " << P2 << " " << dR << " " << kp.pt.x << " " << kp.pt.y
                     << endl;
            }
        }

在这里插入图片描述

在这里插入图片描述

OpenCV’s remap() uses a real-valued index grid to sample a grid of values from an image using bilinear interpolation, and returns the grid of samples as a new image.

To be precise, let:

A = an image
X = a grid of real-valued X coords into the image.
Y = a grid of real-valued Y coords into the image.
B = remap(A, X, Y)
Then for all pixel coordinates i, j,

B[i, j] = A(X[i, j], Y[i, j])
Where the round-braces notation A(x, y) denotes using bilinear interpolation to solve for the pixel value of image A using float-valued coords x and y.

My question is: given an index grid X, Y, how can I generate an “inverse grid” X^-1, Y^-1 such that:

X(X^-1[i, j], Y^-1[i, j]) = i
Y(X^-1[i, j], Y^-1[i, j]) = j
And

X^-1(X[i, j], Y[i, j]) = i
Y^-1(X[i, j], Y[i, j]) = j
For all integer pixel coordinates i, j?

FWIW, the image and index maps X and Y are the same shape. However, there is no a priori structure to the index maps X and Y. For example, they’re not necessarily affine or rigid transforms. They may even be uninvertible, e.g. if X, Y maps multiple pixels in A to the same exact pixel coordinate in B. I’m looking for ideas for a method that will find a reasonable inverse map if one exists.

The solution need not be OpenCV-based, as I’m not using OpenCV, but another library that has a remap() implementation. While any suggestions are welcome, I’m particularly keen on something that’s “mathematically correct”, i.e. if my map M is perfectly invertible, the method should find the perfect inverse, within some small margin of machine precision.

opencv
math
image-processing
remap
bilinear-interpolation
Share
Improve this question
Follow
edited Feb 2, 2017 at 11:32
asked Jan 17, 2017 at 17:17
user avatar
SuperElectric
16.2k99 gold badges4848 silver badges6464 bronze badges
Add a comment
11 Answers
Sorted by:

Highest score (default)

11

Well I just had to solve this remap inversion problem myself and I’ll outline my solution.

Given X, Y for the remap() function that does the following:

B[i, j] = A(X[i, j], Y[i, j])
I computed Xinv, Yinv that can be used by the remap() function to invert the process:

A[x, y] = B(Xinv[x,y],Yinv[x,y])
First I build a KD-Tree for the 2D point set {(X[i,j],Y[i,j]} so I can efficiently find the N nearest neighbors to a given point (x,y). I use Euclidian distance for my distance metric. I found a great C++ header lib for KD-Trees on GitHub.

Then I loop thru all the (x,y) values in A’s grid and find the N = 5 nearest neighbors {(X[i_k,j_k],Y[i_k,j_k]) | k = 0 … N-1} in my point set.

If distance d_k == 0 for some k then Xinv[x,y] = i_k and Yinv[x,y] = j_k, otherwise…

Use Inverse Distance Weighting (IDW) to compute an interpolated value:

let weight w_k = 1 / pow(d_k, p) (I use p = 2)
Xinv[x,y] = (sum_k w_k * i_k)/(sum_k w_k)
Yinv[x,y] = (sum_k w_k * j_k)/(sum_k w_k)
Note that if B is a W x H image then X and Y are W x H arrays of floats. If A is a w x h image then Xinv and Yinv are w x h arrays for floats. It is important that you are consistent with image and map sizing.

Works like a charm! My first version I tried brute forcing the search and I never even waited for it to finish. I switched to a KD-Tree then I started to get reasonable run times. I f I ever get time I would like to add this to OpenCV.

The second image below is use remap() to remove the lens distortion from the first image. The third image is a result of inverting the process.

enter image description here enter image description here enter image description here

相关文章:

  • 温故知新(十三)——CAN
  • 如何跳出forEach循环
  • 大咖论道|银行核心系统国产分布式数据库选型思考
  • 简单5分钟,将lowcode低代码融入到你的中后台管理系统
  • token、cookie、session
  • 强大多云混合多K8S集群管理平台Rancher入门实战
  • 学习编程的第二十四天
  • 第五十一周总结——对象遍历方法
  • java计算机毕业设计民宿预订管理系统设计与实现源码+数据库+系统+lw文档+mybatis+运行部署
  • 渗透测试-微信小程序-公众号测试经验总结
  • innodb存储引擎学习–备份
  • 《nginx》二、nginx反向代理
  • FastAPI 学习之路(三十一)CORS(跨域资源共享)
  • pytorch数据增强
  • ROS1云课→14可视化交互
  • python3.6+scrapy+mysql 爬虫实战
  • 4. 路由到控制器 - Laravel从零开始教程
  • Angularjs之国际化
  • ES学习笔记(12)--Symbol
  • Java 23种设计模式 之单例模式 7种实现方式
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • JavaScript 一些 DOM 的知识点
  • React组件设计模式(一)
  • Twitter赢在开放,三年创造奇迹
  • vue脚手架vue-cli
  • Zsh 开发指南(第十四篇 文件读写)
  • 阿里云Kubernetes容器服务上体验Knative
  • 给github项目添加CI badge
  • 精彩代码 vue.js
  • 微信如何实现自动跳转到用其他浏览器打开指定页面下载APP
  • 限制Java线程池运行线程以及等待线程数量的策略
  • 携程小程序初体验
  • 学习ES6 变量的解构赋值
  • 用jquery写贪吃蛇
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • 如何用纯 CSS 创作一个菱形 loader 动画
  • ​LeetCode解法汇总1410. HTML 实体解析器
  • ​决定德拉瓦州地区版图的关键历史事件
  • #QT(串口助手-界面)
  • $con= MySQL有关填空题_2015年计算机二级考试《MySQL》提高练习题(10)
  • $jQuery 重写Alert样式方法
  • (03)光刻——半导体电路的绘制
  • (1)安装hadoop之虚拟机准备(配置IP与主机名)
  • (附源码)spring boot公选课在线选课系统 毕业设计 142011
  • (附源码)计算机毕业设计SSM疫情社区管理系统
  • (论文阅读11/100)Fast R-CNN
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)
  • (转)es进行聚合操作时提示Fielddata is disabled on text fields by default
  • (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
  • (转载)hibernate缓存
  • .bat批处理(九):替换带有等号=的字符串的子串
  • .MSSQLSERVER 导入导出 命令集--堪称经典,值得借鉴!
  • .net Application的目录
  • .NET CF命令行调试器MDbg入门(四) Attaching to Processes
  • .net core 6 集成和使用 mongodb