Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 0eede11

Browse files
committedFeb 20, 2024·
twist computation
1 parent a0516f5 commit 0eede11

File tree

3 files changed

+112
-1
lines changed

3 files changed

+112
-1
lines changed
 

‎modules/rgbd/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
set(the_description "RGBD algorithms")
22

3-
ocv_define_module(rgbd opencv_core opencv_calib3d opencv_imgproc OPTIONAL opencv_viz WRAP python)
3+
ocv_define_module(rgbd opencv_core opencv_tracking opencv_calib3d opencv_imgproc OPTIONAL opencv_viz WRAP python)
44

55
if(NOT HAVE_EIGEN)
66
message(STATUS "rgbd: Eigen support is disabled. Eigen is Required for Posegraph optimization")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#ifndef __OPENCV_RGBD_TWIST_HPP__
2+
#define __OPENCV_RGBD_TWIST_HPP__
3+
4+
#include "opencv2/video/tracking.hpp"
5+
6+
namespace cv
7+
{
8+
namespace rgbd
9+
{
10+
class CV_EXPORTS_W Twist
11+
{
12+
public:
13+
Twist();
14+
15+
cv::Vec6d compute(const cv::Mat& im0, const cv::Mat& im1, const cv::Mat depths0,
16+
const cv::Mat& K, const double dt);
17+
18+
private:
19+
void interactionMatrix(const cv::Mat& uv, const cv::Mat& depth, const cv::Mat& K, cv::Mat& J);
20+
21+
private:
22+
Ptr<DenseOpticalFlow> _optflow;
23+
Ptr<cv::Mat> _flow;
24+
};
25+
} // namespace rgbd
26+
} // namespace cv
27+
28+
#endif

‎modules/rgbd/src/twist.cpp

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
2+
#include "precomp.hpp"
3+
#include "opencv2/rgbd/twist.hpp"
4+
5+
namespace cv
6+
{
7+
namespace rgbd
8+
{
9+
10+
Twist::Twist()
11+
{
12+
_optflow = DISOpticalFlow::create(DISOpticalFlow::PRESET_MEDIUM);
13+
_flow = new cv::Mat();
14+
}
15+
16+
void Twist::interactionMatrix(const cv::Mat& uv, const cv::Mat& depth, const cv::Mat& K, cv::Mat& J)
17+
{
18+
CV_Assert(uv.cols == depth.cols);
19+
CV_Assert(depth.type() == CV_32F); // Validate depth input type
20+
21+
J.create(depth.cols * 2, 6, CV_32F);
22+
J.setTo(0);
23+
24+
cv::Mat Kinv;
25+
cv::invert(K, Kinv);
26+
27+
cv::Mat xy(3, 1, CV_32F);
28+
cv::Mat Jp(2, 6, CV_32F);
29+
for (int i = 0; i < uv.cols; i++)
30+
{
31+
const float z = depth.at<float>(i);
32+
if (cv::abs(z) < 0.001f)
33+
continue;
34+
35+
const cv::Point3f p(uv.at<float>(0, i), uv.at<float>(1, i), 1.0);
36+
37+
// convert to normalized image-plane coordinates
38+
xy = Kinv * cv::Mat(p);
39+
float x = xy.at<float>(0);
40+
float y = xy.at<float>(1);
41+
42+
// 2x6 Jacobian for this point
43+
Jp = (cv::Mat_<float>(2, 6) << -1 / z, 0.0, x / z, x * y, -(1 + x * x), y, 0.0, -1 / z,
44+
y / z, 1 + y * y, -x * y, -x);
45+
46+
Jp = K(cv::Rect(0, 0, 2, 2)) * Jp;
47+
48+
// push into Jacobian
49+
Jp.copyTo(J(cv::Rect(0, 2 * i, 6, 2)));
50+
}
51+
}
52+
53+
cv::Vec6d Twist::compute(const cv::Mat& im0, const cv::Mat& im1, const cv::Mat depths0, const cv::Mat& K,
54+
const double dt)
55+
{
56+
_optflow->calc(im0, im1, *_flow);
57+
58+
const int N = (im0.cols * im0.rows) * 0.1;
59+
cv::Mat uv(2, N, CV_32F);
60+
cv::Mat depth(1, N, CV_32F);
61+
cv::Mat flow(1, 2 * N, CV_32F);
62+
for (int i = 0; i < N; i++)
63+
{
64+
int x = rand() % im0.cols;
65+
int y = rand() % im0.rows;
66+
uv.at<float>(0, i) = x;
67+
uv.at<float>(1, i) = y;
68+
depth.at<float>(i) = depths0.at<float>(y, x);
69+
flow.at<float>(0, 2 * i) = _flow->at<cv::Point2f>(y, x).x;
70+
flow.at<float>(0, 2 * i + 1) = _flow->at<cv::Point2f>(y, x).y;
71+
}
72+
cv::Mat J;
73+
interactionMatrix(uv, depth, K, J);
74+
75+
cv::Mat Jinv;
76+
cv::invert(J, Jinv, cv::DECOMP_SVD);
77+
cv::Mat duv = flow / dt;
78+
cv::Mat twist = Jinv * duv.t();
79+
return twist;
80+
}
81+
82+
} // namespace rgbd
83+
} // namespace cv

0 commit comments

Comments
 (0)
Please sign in to comment.