Liszt_HistogramViewer / z_tof2pointcloud.cpp
JohnChiu's picture
add elegant algorithm
e1728fa
constexpr float PI = 3.14159265358979323846f;
void undistort_points_pinhole_cpp(
const std::vector<float> &K,
const std::vector<float> &D,
int num_points,
std::vector<float> &unit_vector)
{
std::vector<float> distorted(num_points * 2, 0.f);
std::vector<float> undistorted(num_points * 2, 0.f);
// Generate distorted points (same as original)
for (int y = 0; y < 48; ++y)
{
for (int x = 0; x < 120; ++x)
{
int idx = (y * 120 + x) * 2;
distorted[idx] = (x + 0.5f);
distorted[idx + 1] = (y + 0.5f);
}
}
unit_vector.resize(num_points * 3);
float fx = K[0];
float fy = K[4];
float cx = K[2];
float cy = K[5];
float k1 = D[0], k2 = D[1], p1 = D[2], p2 = D[3], k3 = D[4];
for (int idx = 0; idx < num_points; ++idx)
{
int idx_two = idx * 2;
int idx_three = idx * 3;
float u = distorted[idx_two + 0];
float v = distorted[idx_two + 1];
//---------------------------------------------------------
// Step 1: Normalize distorted coords
//---------------------------------------------------------
float xd = (u - cx) / fx;
float yd = (v - cy) / fy;
//---------------------------------------------------------
// Step 2: Iteratively solve undistorted x,y (Brown–Conrady)
//---------------------------------------------------------
float x = xd;
float y = yd;
for (int iter = 0; iter < 5; iter++)
{
float r2 = x * x + y * y;
float r4 = r2 * r2;
float r6 = r4 * r2;
float radial = 1 + k1 * r2 + k2 * r4 + k3 * r6;
float x_tangential = 2 * p1 * x * y + p2 * (r2 + 2 * x * x);
float y_tangential = p1 * (r2 + 2 * y * y) + 2 * p2 * x * y;
float x_est = (xd - x_tangential) / radial;
float y_est = (yd - y_tangential) / radial;
x = x_est;
y = y_est;
}
//---------------------------------------------------------
// Step 3: Convert to undistorted pixel coords
//---------------------------------------------------------
float u_und = fx * x + cx;
float v_und = fy * y + cy;
undistorted[idx_two + 0] = u_und;
undistorted[idx_two + 1] = v_und;
//---------------------------------------------------------
// Step 4: Compute camera-frame unit vector
//---------------------------------------------------------
float X = x;
float Y = y;
float Z = 1.0f;
float norm = std::sqrt(X * X + Y * Y + Z * Z);
//---------------------------------------------------------
// Optional ellipse mask (unchanged)
//---------------------------------------------------------
// float ra = 1.f / (cx - 3);
// float rb = 1.f / (cy + 4);
// float mask = ((u - cx)*(u - cx)*ra*ra +
// (v - cy)*(v - cy)*rb*rb - 1.f) < 0.f ? 1.f : 0.f;
float mask = 1;
unit_vector[idx_three + 0] = mask * (X / norm);
unit_vector[idx_three + 1] = mask * (Y / norm);
unit_vector[idx_three + 2] = mask * (Z / norm);
}
}
void tof_to_xyz(
const std::vector<float> &unit_vector,
const std::vector<float> &tof,
int num_points,
std::vector<float> &points3D)
{
points3D.resize(num_points * 3);
for (int i = 0; i < num_points; ++i)
{
int idx3 = i * 3;
float d = tof[i];
points3D[idx3 + 0] = unit_vector[idx3 + 0] * d;
points3D[idx3 + 1] = unit_vector[idx3 + 1] * d;
points3D[idx3 + 2] = unit_vector[idx3 + 2] * d;
}
}
void depth_to_xyz(
const std::vector<float> &unit_vector,
const std::vector<float> &depth,
int num_points,
std::vector<float> &points3D)
{
points3D.resize(num_points * 3);
for (int i = 0; i < num_points; ++i)
{
int idx3 = i * 3;
float d = depth[i];
points3D[idx3 + 0] = unit_vector[idx3 + 0]/ unit_vector[idx3 + 2] * d;
points3D[idx3 + 1] = unit_vector[idx3 + 1]/ unit_vector[idx3 + 2] * d;
points3D[idx3 + 2] = d;
}
}
int main()
{
int WIDTH = 40;
int HEIGHT = 30;
int num_points = WIDTH * HEIGHT;
std::vector<float> unit_vector(num_points * 3, 0.f);
std::vector<float> depth(num_points , 0.f);
std::vector<float> points3D(num_points * 3 , 0.f); // 改成 *3
// 内参
float fx = 37;
float fy = 37;
float cx = 20;
float cy = 15;
// 畸变参数
float k1 = 0.f;
float k2 = 0.f;
float p1 = 0.f;
float p2 = 0.f;
float k3 = 0.f;
std::vector<float> K = {fx , 0.f, cx , 0.f, fy , cy , 0.f, 0.f, 1.f};
std::vector<float> D = {k1, k2, p1, p2, k3};
// 生成 unit_vector
undistort_points_pinhole_cpp(K, D, num_points, unit_vector);
// 将 depth 转成相机坐标系
depth_to_xyz(unit_vector, depth, num_points, points3D);
return 0;
}