本文代码CSDN链接:
http://download.csdn.net/download/qq_30547073/10112583
对应的百度网盘链接:
链接:https://pan.baidu.com/s/1i5MRSbF 密码:ku8f
好嘞。
这一次手把手教大家搭建一个和CC一模一样的点云精简器老规矩,我们先上效果
所有源码按照规矩分享到百度网盘中供大家测试。release下的exe也是可以直接运行的。
希望大家发现问题后及时联系我,QQ 4987710226 希望共同学习。
链接:https://pan.baidu.com/s/1i5MRSbF 密码:ku8f
废话不多说,上核心代码
enum SimplifyModel
{
Random_Simplify,
Space_Simplify,
Octree_Simplify,
};
class qScarlet_CloudSimplifyFrm : public QWidget
{
Q_OBJECT
public:
explicit qScarlet_CloudSimplifyFrm(QWidget *parent = 0);
qScarlet_CloudSimplifyFrm(int CloudIndex ,int PtNum,QWidget *parent = 0);
//qScarlet_CloudSimplifyFrm(int in,QWidget *parent = 0);
void SetCloudIndex(int);
void SetCloudNum(int);
int GetCloudIndex();
int GetOrigionCloudNum();
int GetAfterRandomCloudNum();
SimplifyModel GetSimplifyMode();
signals:
void signal_OnOkBTClick_Random();
void signal_OnOkBTClick_Space();
void signal_OnOkBTClick_Octree();
public slots:
void slot_CurrentMethodChanged(int);
void slot_ThisCancel();
void slot_ThisApply();
void slot_SetRandomSimplifyPtNum(int);
private:
void start();
void CreateUpperPartWidget();
void CreateRandomPartWidget();
void CreateSpacePartWidget();
void CreateOctreePartWidget();
void CreateGroupPartLayOut();
void CreateOkCancelPartWidget();
QGroupBox*m_Sampling_parametersGroup;
QWidget *m_UppterPartWidget;
QLabel*m_Method_Label;
QComboBox*m_MethodSelector_Combobox;
QWidget *m_extent_RandomSimplifyWidget;
QLabel*m_None_Label;
QLabel*m_All_Label;
QSlider*m_NoneAll_Slider;
QLabel*m_RemainingPoints_Label;
QSpinBox*m_RemainingPoints_SpinBox;
QWidget *m_extent_SpaceSimplifyWidget;
QLabel*m_Large_Label;
QLabel*m_Small_Label;
QSlider*m_LargeSmall_Slider;
QLabel*m_MinSpaceBetweenPoints_Label;
QSpinBox*m_MinSpaceBetweenPoints_SpinBox;
QWidget *m_extent_OctreeSimplifyWidget;
QLabel*m_Min_Label;
QLabel*m_Max_Label;
QSlider*m_MinMax_Slider;
QLabel*m_Subdivision_Label;
QSpinBox*m_Subdivision_SpinBox;
QStringListModel *typeModel;
QWidget *m_OkCancelWidget;
QPushButton*m_ApplyBT;//Apply the method to cloud Simplify
QPushButton*m_CancelBT;//Cancel and not do anything on cloud
int m_CloudIndex;
int m_PtNum;
int m_PtNum_SimplifyRandom;
SimplifyModel m_SimplifyMode;
};
//下面是CPP文件,其实代码有很多是重复的,同学可以先看一下Layout部分的基本原理再来看代码:
qScarlet_CloudSimplifyFrm::qScarlet_CloudSimplifyFrm(QWidget *parent):
QWidget(parent)
{
start();
}
qScarlet_CloudSimplifyFrm::qScarlet_CloudSimplifyFrm(int CloudIndex ,int PtNum,QWidget *parent )
:m_CloudIndex(CloudIndex),m_PtNum(PtNum),QWidget(parent)
{
start();
}
void qScarlet_CloudSimplifyFrm::SetCloudIndex(int in_CloudIndex)
{
m_CloudIndex = in_CloudIndex;
}
void qScarlet_CloudSimplifyFrm::SetCloudNum(int in_CloudNum)
{
m_PtNum = in_CloudNum;
}
void qScarlet_CloudSimplifyFrm::slot_SetRandomSimplifyPtNum(int PtNumAfterSimplify)
{
m_PtNum_SimplifyRandom = PtNumAfterSimplify;
}
int qScarlet_CloudSimplifyFrm::GetCloudIndex()
{
return m_CloudIndex;
}
int qScarlet_CloudSimplifyFrm::GetOrigionCloudNum()
{
return m_PtNum;
}
int qScarlet_CloudSimplifyFrm::GetAfterRandomCloudNum()
{
return m_PtNum_SimplifyRandom;
}
SimplifyModel qScarlet_CloudSimplifyFrm::GetSimplifyMode()
{
return m_SimplifyMode;
}
void qScarlet_CloudSimplifyFrm::start()
{
CreateUpperPartWidget();
CreateRandomPartWidget();
CreateSpacePartWidget();
CreateOctreePartWidget();
CreateOkCancelPartWidget();
CreateGroupPartLayOut();
}
void qScarlet_CloudSimplifyFrm::CreateUpperPartWidget()
{
m_UppterPartWidget =new QWidget();
m_Method_Label = new QLabel("Method");
m_MethodSelector_Combobox =new QComboBox();
QGridLayout *UpperPart_GridLayout = new QGridLayout();
UpperPart_GridLayout->addWidget(m_Method_Label, 0, 0,1,1);
UpperPart_GridLayout->addWidget(m_MethodSelector_Combobox, 0, 1,1,3);
//UpperPart_GridLayout->setHorizontalSpacing(200);
m_UppterPartWidget->setLayout(UpperPart_GridLayout);
}
void qScarlet_CloudSimplifyFrm::CreateRandomPartWidget()
{
m_extent_RandomSimplifyWidget =new QWidget();
m_None_Label =new QLabel("None");
m_All_Label = new QLabel("All");
m_NoneAll_Slider = new QSlider(Qt::Orientation::Horizontal);
m_RemainingPoints_Label = new QLabel("Remaining Points");
m_RemainingPoints_SpinBox= new QSpinBox();
QGridLayout* RandomExtentLayout= new QGridLayout();;
RandomExtentLayout->addWidget(m_None_Label,0, 0,1,1);
RandomExtentLayout->addWidget(m_All_Label,0, 3,1,1);
RandomExtentLayout->addWidget(m_NoneAll_Slider,1, 0,1,4);
RandomExtentLayout->addWidget(m_RemainingPoints_Label,2, 0,1,1);
RandomExtentLayout->addWidget(m_RemainingPoints_SpinBox,2, 1,1,1);
m_extent_RandomSimplifyWidget->setLayout(RandomExtentLayout);
m_NoneAll_Slider->setRange(1,m_PtNum);
m_RemainingPoints_SpinBox->setRange(1,m_PtNum);
connect(m_NoneAll_Slider,SIGNAL(valueChanged(int)),m_RemainingPoints_SpinBox,SLOT(setValue(int )));
connect(m_NoneAll_Slider,SIGNAL(valueChanged(int)),this,SLOT(slot_SetRandomSimplifyPtNum(int)));
connect(m_RemainingPoints_SpinBox,SIGNAL(valueChanged(int)),m_NoneAll_Slider,SLOT(setValue(int)));
m_NoneAll_Slider->setValue(m_PtNum/2);
m_NoneAll_Slider->setSingleStep(m_PtNum/20);//set space
m_RemainingPoints_SpinBox->setSingleStep(m_PtNum/20);//set space
}
void qScarlet_CloudSimplifyFrm::CreateSpacePartWidget()
{
m_extent_SpaceSimplifyWidget =new QWidget();
m_Large_Label =new QLabel("Large");
m_Small_Label = new QLabel("Small");
m_LargeSmall_Slider = new QSlider(Qt::Orientation::Horizontal);
m_MinSpaceBetweenPoints_Label = new QLabel("Min Space Between Points");
m_MinSpaceBetweenPoints_SpinBox= new QSpinBox();
QGridLayout* SpaceExtentLayout= new QGridLayout();;
SpaceExtentLayout->addWidget(m_Large_Label,0, 0,1,1);
SpaceExtentLayout->addWidget(m_Small_Label,0, 3,1,1);
SpaceExtentLayout->addWidget(m_LargeSmall_Slider,1, 0,1,4);
SpaceExtentLayout->addWidget(m_MinSpaceBetweenPoints_Label,2, 0,1,1);
SpaceExtentLayout->addWidget(m_MinSpaceBetweenPoints_SpinBox,2, 1,1,1);
m_extent_SpaceSimplifyWidget->setLayout(SpaceExtentLayout);
}
void qScarlet_CloudSimplifyFrm::CreateOctreePartWidget()
{
m_extent_OctreeSimplifyWidget =new QWidget();
m_Min_Label =new QLabel("Min");
m_Max_Label = new QLabel("Max");
m_MinMax_Slider = new QSlider(Qt::Orientation::Horizontal);
m_Subdivision_Label = new QLabel("Subdivision level");
m_Subdivision_SpinBox= new QSpinBox();
QGridLayout* OctreeExtentLayout= new QGridLayout();
OctreeExtentLayout->addWidget(m_Min_Label,0, 0,1,1);
OctreeExtentLayout->addWidget(m_Max_Label,0, 3,1,1);
OctreeExtentLayout->addWidget(m_MinMax_Slider,1, 0,1,4);
OctreeExtentLayout->addWidget(m_Subdivision_Label,2, 0,1,1);
OctreeExtentLayout->addWidget(m_Subdivision_SpinBox,2, 1,1,1);
m_extent_OctreeSimplifyWidget->setLayout(OctreeExtentLayout);
}
void qScarlet_CloudSimplifyFrm::CreateOkCancelPartWidget()
{
m_OkCancelWidget =new QWidget();
m_ApplyBT = new QPushButton("Apply");
m_CancelBT = new QPushButton("Cancel");
QGridLayout* ApplyCancelLayout= new QGridLayout();
ApplyCancelLayout->addWidget(m_ApplyBT,0, 2,1,1);
ApplyCancelLayout->addWidget(m_CancelBT,0, 3,1,1);
m_OkCancelWidget->setLayout(ApplyCancelLayout);
connect(m_ApplyBT,SIGNAL(clicked()),this,SLOT(slot_ThisApply()));
connect(m_CancelBT,SIGNAL(clicked()),this,SLOT(slot_ThisCancel()));
}
void qScarlet_CloudSimplifyFrm::CreateGroupPartLayOut()
{
m_Sampling_parametersGroup = new QGroupBox("Sampling Parameters");
QVBoxLayout *AllWidgetLayout = new QVBoxLayout();
AllWidgetLayout->addWidget(m_UppterPartWidget);
AllWidgetLayout->addWidget(m_extent_RandomSimplifyWidget);
AllWidgetLayout->addWidget(m_extent_SpaceSimplifyWidget);
AllWidgetLayout->addWidget(m_extent_OctreeSimplifyWidget);
AllWidgetLayout->addWidget(m_OkCancelWidget);
m_Sampling_parametersGroup->setLayout(AllWidgetLayout);
//========at Last we set group box in the widget
QGridLayout* AllGridLayout= new QGridLayout();
AllGridLayout->addWidget(m_Sampling_parametersGroup);
this->setLayout(AllGridLayout);
//=======We add some item in combobx
QStringList MethodItems;
MethodItems << tr("Random") << tr("Space") << tr("Octree");
typeModel = new QStringListModel(MethodItems, this);
m_MethodSelector_Combobox->setModel(typeModel);
connect(m_MethodSelector_Combobox,SIGNAL(currentIndexChanged(int)),this,SLOT(slot_CurrentMethodChanged(int)));
m_MethodSelector_Combobox->setCurrentIndex(1);//=======we Set Another index to Init
m_MethodSelector_Combobox->setCurrentIndex(0);
m_NoneAll_Slider->setTickPosition(QSlider::TicksAbove); //draw clock tick above the slider
}
void qScarlet_CloudSimplifyFrm::slot_CurrentMethodChanged(int CurrentMethod)
{
QString CurrentQString = m_MethodSelector_Combobox->currentText();
//=====firstly we set all invisible
m_extent_RandomSimplifyWidget->setVisible(false);
m_extent_SpaceSimplifyWidget->setVisible(false);
m_extent_OctreeSimplifyWidget->setVisible(false);
if(CurrentQString == QString("Random"))
{
m_extent_RandomSimplifyWidget->setVisible(true);
m_SimplifyMode = SimplifyModel::Random_Simplify;
m_ApplyBT->setEnabled(true);
}
//We don't open these two functions for the time being
else if(CurrentQString == QString("Space"))
{
m_extent_SpaceSimplifyWidget->setVisible(true);
m_SimplifyMode = SimplifyModel::Space_Simplify;
m_ApplyBT->setEnabled(true);
}
else if(CurrentQString == QString("Octree"))
{
m_extent_OctreeSimplifyWidget->setVisible(true);
m_SimplifyMode = SimplifyModel::Octree_Simplify;
m_ApplyBT->setEnabled(false);
}
else
{
}
}
void qScarlet_CloudSimplifyFrm::slot_ThisApply()
{
switch(m_SimplifyMode)
{
case Random_Simplify:emit(signal_OnOkBTClick_Random()); break;
case Space_Simplify:emit(signal_OnOkBTClick_Space());break;
case Octree_Simplify:emit(signal_OnOkBTClick_Octree());break;
default:
break;
}
}
void qScarlet_CloudSimplifyFrm::slot_ThisCancel()
{
this->close();
}
界面和CC可以说毫无差别。
单击apply的时候要进行精简处理,那么连接的代码以及show窗体的代码如下:
void qscarlet_opencvMaster::on_actionCloudSimplification_triggered()
{
QModelIndex SelectedModelindex = treeView3D_GLES2->selectionModel()->currentIndex();
if(SelectedModelindex.column() == 0&&SelectedModelindex.parent().data().toString() == "Ninja")
{
std::vector<qScarlet_GLCloudEngin_ES2*> myCloudEnginVec = m_GLWidget_ES2->GetAllEngin();
int SelectedCloudIndex = SelectedModelindex.row();
qScarlet_GLCloudEngin_ES2* CurrentEngin = myCloudEnginVec[SelectedCloudIndex];
int PtNum = CurrentEngin->Get_PointNum();
m_CloudSimplifyFrm = new qScarlet_CloudSimplifyFrm(SelectedCloudIndex,PtNum);
connect(m_CloudSimplifyFrm,SIGNAL(signal_OnOkBTClick_Random()),this,SLOT(slot_ApplyCloudSimplification_Random()));
connect(m_CloudSimplifyFrm,SIGNAL(signal_OnOkBTClick_Space()),this,SLOT(slot_ApplyCloudSimplification_Space()));
connect(m_CloudSimplifyFrm,SIGNAL(signal_OnOkBTClick_Octree()),this,SLOT(slot_ApplyCloudSimplification_Octree()));
//and we hanve other signal to emit
m_CloudSimplifyFrm->setAttribute(Qt::WA_DeleteOnClose);//关闭立刻释放
m_CloudSimplifyFrm->show();
}
else
{
}
}
精简的原理很简单,主要是产生一定数量的随机数,然后将随机数对应的点云删除就行了。
对于具体精简,每个人的接口都不一样。。。。我这里就只放随机数产生器的代码:
为什么这样呢?因为rand()函数产生的最大随机数为32767,而点云可达上亿,如果想获得正确的精简效果就必须产生任意大小的随机数,普通的做法当然不行。下面就分享给大家任意数字大小的随机数产生器
//==超级随机数产生器
const double MinProb = 1.0 / (RAND_MAX + 1);
bool happened(double probability)//probability 0~1
{
if (probability <= 0)
{
return false;
}
if (probability<MinProb)
{
return rand() == 0 && happened(probability*(RAND_MAX + 1));
}
if (rand() <= probability*(RAND_MAX + 1))
{
return true;
}
return false;
}
//产生0~n-1之间的等概率随机数
long RandomEngin(long n)
{
int t = 0;
if (n <= RAND_MAX)
{
long r = RAND_MAX - (RAND_MAX + 1) % n;//尾数
t = rand();
while (t > r)
{
t = rand();
}
return t % n;
}
else
{
long r = n % (RAND_MAX + 1);//余数
if (happened((double)r / n))//取到余数的概率
{
return n - r + RandomEngin(r);
}
else
{
return rand() + RandomEngin(n / (RAND_MAX + 1))*(RAND_MAX + 1);
}
}
}