【PCL】平面拟合

  • CMAKE配置
cmake_minimum_required(VERSION 3.16)
project(FridayLibrary)

set(CMAKE_CXX_STANDARD 14)


SET(BOOST_INCLUDE_DIR C:/Program\ Files/PCL\ 1.11.0/3rdParty/Boost/include)
SET(BOOST_LIBRARY_DIR C:/Program\ Files/PCL\ 1.11.0/3rdParty/Boost/lib)

set(PLC_ROOT        C:/Program\ Files/PCL\ 1.11.0)
set(PLC_INCLUDE_DIR C:/Program\ Files/PCL\ 1.11.0/include)
set(PLC_LIBRARY_DIR C:/Program\ Files/PCL\ 1.11.0/lib)

find_package(PCL REQUIRED)
if(PCL_FOUND)
    message ("PCL found")
else()
    message (FATAL_ERROR "Cannot find PCL")
endif(PCL_FOUND)
include_directories(${PLC_INCLUDE_DIR} ${BOOST_INCLUDE_DIR})
link_directories(${PLC_LIBRARY_DIR} ${BOOST_LIBRARY_DIR})


add_library(FridayLibrary SHARED library.cpp library.h)
target_link_libraries( FridayLibrary PRIVATE
        ${PCL_LIBRARIES}
        ${BOOST_LIBRARIES}
        )
  • PCL + C++平面拟合
pcl::PointXYZ points[36];
points[0].x = 0.2542060f, points[0].y = 0.1991714f, points[0].z = 2.0531f;
points[1].x = 0.3039878f, points[1].y = 0.1993848f, points[1].z = 2.0553f;
points[2].x = 0.3500631f, points[2].y = 0.2034014f, points[2].z = 2.0575f;
points[3].x = 0.4000528f, points[3].y = 0.2074261f, points[3].z = 2.0597f;
points[4].x = 0.4463278f, points[4].y = 0.2076477f, points[4].z = 2.0619f;
points[5].x = 0.4954670f, points[5].y = 0.2112333f, points[5].z = 2.0597f;
points[6].x = 0.2547508f, points[6].y = 0.2604488f, points[6].z = 2.0575f;
points[7].x = 0.2995513f, points[7].y = 0.2634172f, points[7].z = 2.051f;
points[8].x = 0.3458804f, points[8].y = 0.2677685f, points[8].z = 2.0553f;
points[9].x = 0.3958130f, points[9].y = 0.2680552f, points[9].z = 2.0575f;
points[10].x = 0.4415629f, points[10].y = 0.2718583f, points[10].z = 2.0575f;
points[11].x = 0.4916504f, points[11].y = 0.2759562f, points[11].z = 2.0597f;
points[12].x = 0.2512066f, points[12].y = 0.3254502f, points[12].z = 2.0597f;
points[13].x = 0.2963710f, points[13].y = 0.3285541f, points[13].z = 2.0553f;
points[14].x = 0.3458804f, points[14].y = 0.3285541f, points[14].z = 2.0553f;
points[15].x = 0.3928388f, points[15].y = 0.3334204f, points[15].z = 2.0619f;
points[16].x = 0.4425072f, points[16].y = 0.3372317f, points[16].z = 2.0619f;
points[17].x = 0.4883550f, points[17].y = 0.3372317f, points[17].z = 2.0619f;
points[18].x = 0.2471258f, points[18].y = 0.3897563f, points[18].z = 2.0575f;
points[19].x = 0.2922494f, points[19].y = 0.3889228f, points[19].z = 2.0531f;
points[20].x = 0.3420720f, points[20].y = 0.3931387f, points[20].z = 2.0553f;
points[21].x = 0.3881880f, points[21].y = 0.3973626f, points[21].z = 2.0575f;
points[22].x = 0.4391546f, points[22].y = 0.3986373f, points[22].z = 2.0641f;
points[23].x = 0.4840173f, points[23].y = 0.4015947f, points[23].z = 2.0597f;
points[24].x = 0.2430531f, points[24].y = 0.4501251f, points[24].z = 2.0553f;
points[25].x = 0.2925625f, points[25].y = 0.4539242f, points[25].z = 2.0553f;
points[26].x = 0.3386256f, points[26].y = 0.4582132f, points[26].z = 2.0575f;
points[27].x = 0.3894332f, points[27].y = 0.4596831f, points[27].z = 2.0641f;
points[28].x = 0.4353299f, points[28].y = 0.4634984f, points[28].z = 2.0641f;
points[29].x = 0.4840173f, points[29].y = 0.4663176f, points[29].z = 2.0597f;
points[30].x = 0.2395008f, points[30].y = 0.5152606f, points[30].z = 2.0575f;
points[31].x = 0.2893723f, points[31].y = 0.5196187f, points[31].z = 2.0597f;
points[32].x = 0.3344551f, points[32].y = 0.5185088f, points[32].z = 2.0553f;
points[33].x = 0.3860195f, points[33].y = 0.5251033f, points[33].z = 2.0663f;
points[34].x = 0.4315052f, points[34].y = 0.5283596f, points[34].z = 2.0641f;
points[35].x = 0.4812266f, points[35].y = 0.5283596f, points[35].z = 2.0641f;

pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);

cloud->width = 36;
cloud->height = 1;
cloud->is_dense = false;
cloud->points.resize(cloud->width * cloud->height);
for (size_t i = 0; i < cloud->points.size(); ++i)
{
    cloud->points[i].x = points[i].x;
    cloud->points[i].y = points[i].y;
    cloud->points[i].z = points[i].z;
}

Eigen::VectorXf oef;
const pcl::SampleConsensusModelPlane<pcl::PointXYZ>::Ptr model_p(new pcl::SampleConsensusModelPlane<pcl::PointXYZ>(cloud));
pcl::RandomSampleConsensus<pcl::PointXYZ> ransac(model_p);
ransac.setDistanceThreshold(.005);
ransac.computeModel();
ransac.getModelCoefficients(oef);

std::cout << "coef: " << std::endl << oef << std::endl;
  • C# 封装

头文件

#ifndef FRIDAYLIBRARY_LIBRARY_H
#define FRIDAYLIBRARY_LIBRARY_H
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/sample_consensus/ransac.h>
#include <pcl/sample_consensus/sac_model_plane.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
#include <pcl/point_cloud.h>
#include <pcl/registration/transformation_estimation_svd.h>
#include <vector>
#ifdef __DLL_BUILD
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C" {
#endif


/// <summary>
/// 通过一系列坐标点拟合平面(AX + BY + CX + D = 0)
/// </summary>
/// <param name="p_src_x">X坐标指针</param>
/// <param name="p_src_y">Y坐标指针</param>
/// <param name="p_src_z">Z坐标指针</param>
/// <param name="length">坐标点个数</param>
/// <param name="threshold">用于RANSAC拟合平面时的距离系数</param>
/// <param name="plane_coefficients">返回平面方程的系数[A,B,C,D]</param>
DLL_EXPORT void fit_plane(const float* p_src_x,
                          const float* p_src_y,
                          const float* p_src_z,
                          const size_t length,
                          const double threshold, float* plane_coefficients);
#ifdef __cplusplus
}
#endif
#endif //FRIDAYLIBRARY_LIBRARY_H

源文件

#define __DLL_BUILD
#include "library.h"



/// <summary>
/// 通过一系列坐标点拟合平面(AX + BY + CX + D = 0)
/// </summary>
/// <param name="p_src_x">X坐标指针</param>
/// <param name="p_src_y">Y坐标指针</param>
/// <param name="p_src_z">Z坐标指针</param>
/// <param name="length">坐标点个数</param>
/// <param name="threshold">用于RANSAC拟合平面时的距离系数</param>
/// <param name="plane_coefficients">返回平面方程的系数[A,B,C,D]</param>
void fit_plane(const float* p_src_x,
              const float* p_src_y,
              const float* p_src_z,
              const size_t length,
              const double threshold, float* plane_coefficients)
{
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);

	cloud->width = length;
	cloud->height = 1;
	cloud->is_dense = false;
	cloud->points.resize(cloud->width * cloud->height);
	for (size_t i = 0; i < length; ++i)
	{
		cloud->points[i].x = p_src_x[i];
		cloud->points[i].y = p_src_y[i];
		cloud->points[i].z = p_src_z[i];
	}

	const pcl::SampleConsensusModelPlane<pcl::PointXYZ>::Ptr model_p(new pcl::SampleConsensusModelPlane<pcl::PointXYZ>(cloud));
	pcl::RandomSampleConsensus<pcl::PointXYZ> ransac(model_p);
	ransac.setDistanceThreshold(threshold);
	ransac.setMaxIterations(1000);
	ransac.computeModel();

	Eigen::VectorXf coefficients;
	ransac.getModelCoefficients(coefficients);
	
	plane_coefficients[0] = coefficients[0];
	plane_coefficients[1] = coefficients[1];
	plane_coefficients[2] = coefficients[2];
	plane_coefficients[3] = coefficients[3];

}

C#调用

using System;
using System.IO;
using System.Runtime.InteropServices;

namespace ConsoleApp1
{
    internal class Program
    {
        public struct Buffer
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
            public byte[] DstAddr;
        }
        [DllImport("./FridayLibrary", CallingConvention = CallingConvention.Cdecl, EntryPoint = "fit_plane")]
        public static extern int FitPlane(float[] x, float[] y, float[] z, int length, double threshold, ref Buffer buf);


        static void Main(string[] args)
        {
            var x = new float[] {0.254206f ,
                        0.3039878f,
                        0.3500631f,
                        0.4000528f,
                        0.4463278f,
                        0.495467f ,
                        0.2547508f,
                        0.2995513f,
                        0.3458804f,
                        0.395813f ,
                        0.4415629f,
                        0.4916504f,
                        0.2512066f,
                        0.296371f ,
                        0.3458804f,
                        0.3928388f,
                        0.4425072f,
                        0.488355f ,
                        0.2471258f,
                        0.2922494f,
                        0.342072f ,
                        0.388188f ,
                        0.4391546f,
                        0.4840173f,
                        0.2430531f,
                        0.2925625f,
                        0.3386256f,
                        0.3894332f,
                        0.4353299f,
                        0.4840173f,
                        0.2395008f,
                        0.2893723f,
                        0.3344551f,
                        0.3860195f,
                        0.4315052f,
                        0.4812266f
                        };
            var y = new float[] {0.1991714f,
                        0.1993848f,
                        0.2034014f,
                        0.2074261f,
                        0.2076477f,
                        0.2112333f,
                        0.2604488f,
                        0.2634172f,
                        0.2677685f,
                        0.2680552f,
                        0.2718583f,
                        0.2759562f,
                        0.3254502f,
                        0.3285541f,
                        0.3285541f,
                        0.3334204f,
                        0.3372317f,
                        0.3372317f,
                        0.3897563f,
                        0.3889228f,
                        0.3931387f,
                        0.3973626f,
                        0.3986373f,
                        0.4015947f,
                        0.4501251f,
                        0.4539242f,
                        0.4582132f,
                        0.4596831f,
                        0.4634984f,
                        0.4663176f,
                        0.5152606f,
                        0.5196187f,
                        0.5185088f,
                        0.5251033f,
                        0.5283596f,
                        0.5283596f
                        };
            var z = new float[] {2.0531f,
                        2.0553f,
                        2.0575f,
                        2.0597f,
                        2.0619f,
                        2.0597f,
                        2.0575f,
                        2.051f ,
                        2.0553f,
                        2.0575f,
                        2.0575f,
                        2.0597f,
                        2.0597f,
                        2.0553f,
                        2.0553f,
                        2.0619f,
                        2.0619f,
                        2.0619f,
                        2.0575f,
                        2.0531f,
                        2.0553f,
                        2.0575f,
                        2.0641f,
                        2.0597f,
                        2.0553f,
                        2.0553f,
                        2.0575f,
                        2.0641f,
                        2.0641f,
                        2.0597f,
                        2.0575f,
                        2.0597f,
                        2.0553f,
                        2.0663f,
                        2.0641f,
                        2.0641f
                        };

            Buffer buf = new Buffer {DstAddr = new byte[128]};

            float[] coefficients = new float[4];
            var ret = FitPlane(x, y, z, z.Length, 0.005, ref buf);

            using (var stream = new MemoryStream(buf.DstAddr))
            {
                using (var reader = new BinaryReader(stream))
                {
                    var a = reader.ReadSingle();
                    var b = reader.ReadSingle();
                    var c = reader.ReadSingle();
                    var d = reader.ReadSingle();

                    Console.WriteLine($"{a}, {b}, {c}, {d}");
                }
            }

            Console.ReadKey();
        }
    }
}

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

zhy29563

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

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

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

打赏作者

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

抵扣说明:

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

余额充值