本文代碼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);
}
}
}