【C++】【Ctrl+CV即可食用】三维点拟合空间直线

前景概述

网上三维点拟合空间直线的代码很多 大多数都是python或者matlab 这里贴一个C++的代码 原目的是拟合出直线之后任取两个点手动计算一下斜率

数学原理

最小二乘拟合直线方程:
x − x 0 m = y − y 0 n = z − z 0 p \frac {x - x_0}m = \frac {y - y_0}n = \frac {z - z_0}p mxx0=nyy0=pzz0
等价转换后:
x = m p ( z − z 0 ) + x 0 = k 1 z + b 1 x = \frac mp(z - z_0) + x_0 = k_1z + b_1 x=pm(zz0)+x0=k1z+b1
y = n p ( z − z 0 ) + y 0 = k 2 z + b 2 y = \frac np(z - z_0) + y_0 = k_2z + b_2 y=pn(zz0)+y0=k2z+b2
其中:
k 1 = m p , b 1 = x 0 − m p z 0 , k 2 = n p , b 2 = y 0 − n p z 0 k_1 = \frac mp,b_1 = x_0 - \frac mpz_0, k_2 = \frac np, b_2 = y_0 - \frac npz_0 k1=pm,b1=x0pmz0,k2=pn,b2=y0pnz0
求出以上四个值就可以指定z值计算出x和y了

C++代码

double sum_x  = 0.;
double sum_y  = 0.;
double sum_z  = 0.;
double sum_xz = 0.;
double sum_yz = 0.;
double sum_z2 = 0.;
for (size_t i = 0; i < point3_vector.size(); ++i)
{
    sum_x += point3_vector[i].x;
    sum_y += point3_vector[i].y;
    sum_z += point3_vector[i].z;
    sum_xz += point3_vector[i].x * point3_vector[i].z;
    sum_yz += point3_vector[i].y * point3_vector[i].z;
    sum_z2 += point3_vector[i].z * point3_vector[i].z;
}
size_t n = point3_vector.size();

double        den = n * sum_z2 - sum_z * sum_z;
double        k1  = (n * sum_xz - sum_x * sum_z) / den;
double        b1  = (sum_x - k1 * sum_z) / n;
double        k2  = (n * sum_yz - sum_y * sum_z) / den;
double        b2  = (sum_y - k2 * sum_z) / n;

清楚明了 就不注释了 亲测准确放心使用

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面是一个示例的C++程序,演示了如何使用OpenCV实现您描述的RGBD图像处理过程: ```cpp #include <opencv2/opencv.hpp> #include <iostream> cv::Point2f intersectLines(cv::Point2f p1, cv::Point2f p2, cv::Point2f p3, cv::Point2f p4) { cv::Point2f intersection; cv::Vec4f line1(p1.x, p1.y, p2.x, p2.y); cv::Vec4f line2(p3.x, p3.y, p4.x, p4.y); cv::Point2f intersectionPoint; cv::intersectLines(line1, line2, intersectionPoint); return intersectionPoint; } int main() { // 读取RGB图像和深度图像 cv::Mat colorImage = cv::imread("color_image.jpg"); cv::Mat depthImage = cv::imread("depth_image.jpg", cv::IMREAD_GRAYSCALE); // 滤波 cv::GaussianBlur(colorImage, colorImage, cv::Size(5, 5), 0); // 自适应二值化 cv::Mat binaryImage; cv::adaptiveThreshold(depthImage, binaryImage, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY_INV, 11, 2); // 腐蚀和膨胀 cv::Mat erodedImage, dilatedImage; cv::erode(binaryImage, erodedImage, cv::Mat(), cv::Point(-1, -1), 2); cv::dilate(erodedImage, dilatedImage, cv::Mat(), cv::Point(-1, -1), 2); // 边缘检测 cv::Mat edges; cv::Canny(dilatedImage, edges, 50, 150); // 直线拟合 std::vector<cv::Vec4i> lines; cv::HoughLinesP(edges, lines, 1, CV_PI / 180, 50, 50, 10); // 提取直线的交像素坐标 cv::Point2f intersection; if (lines.size() >= 2) { cv::Point2f p1(lines[0][0], lines[0][1]); cv::Point2f p2(lines[0][2], lines[0][3]); cv::Point2f p3(lines[1][0], lines[1][1]); cv::Point2f p4(lines[1][2], lines[1][3]); intersection = intersectLines(p1, p2, p3, p4); } // 根据彩色和深度图计算交三维坐标 cv::Vec3f point3D; if (!depthImage.empty() && !colorImage.empty()) { cv::Point point2D(static_cast<int>(intersection.x), static_cast<int>(intersection.y)); ushort depthValue = depthImage.at<ushort>(point2D.y, point2D.x); cv::Vec3b colorValue = colorImage.at<cv::Vec3b>(point2D.y, point2D.x); float depthInMeters = static_cast<float>(depthValue) / 1000.0; point3D[0] = intersection.x * depthInMeters; point3D[1] = intersection.y * depthInMeters; point3D[2] = depthInMeters; std::cout << "Intersection 3D coordinates: (" << point3D[0] << ", " << point3D[1] << ", " << point3D[2] << ")" << std::endl; } return 0; } ``` 在这个示例中,我们首先使用`cv::imread`函数读取RGB图像和深度图像。然后,我们按照您描述的过程对图像进行滤波、自适应二值化、腐蚀膨胀、边缘检测和直线拟合的操作。接下来,我们提取直线的交像素坐标,并利用彩色和深度图像计算交三维坐标。 请注意,您需要将程序中的`color_image.jpg`和`depth_image.jpg`替换为您自己的RGB和深度图像文件路径。此外,还需要确保您的RGB和深度图像分辨率相同。 希望这个示例对您有所帮助!如果您有任何其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

铃灵狗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值