VTK修炼之道57:图形基本操作进阶_点云配准技术(LandMark标记点算法和坐标系显示方法)
生活随笔
收集整理的這篇文章主要介紹了
VTK修炼之道57:图形基本操作进阶_点云配准技术(LandMark标记点算法和坐标系显示方法)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1.點云配準
在計算機逆向工程中,通過三維掃描等實物數字化技術可以獲取各種點云數據。但是受到測量環境和設備的影響,再一次測量的情況下,難以獲取實物整體的點云數據,因此需要多次從不同角度進行測量。但不同的測量數據之間可能會存在平移錯誤或旋轉錯位等問題。這就需要使用點云配準技術來對測量點云數據進行局部配準和整合,以得到完整的模型數據。
另外,在外科手術導航技術中,圖像標記點技術與人體表面標記點的配準是一個關鍵步驟,對于手術定位的精度有著重要的影響。通常這需要使用基于標記點的配準技術。因此,點云配準及時對一組源點云數據應用一個空間變換,使得變換后的數據與目標點云數據能夠一一映射,使兩組數據之間的平均距離誤差最小。
2.LandMark配準實驗
VTKLandMarkTransform實現了片幾點配準算法,使得兩個點集在配準后的平均距離最小。通過SetSourceLandmarks()和SetTargetLandmarks()函數分別設置源標記點集和目標標記點集。需要注意的是,源標記點集和目標標記點集序號要對應。 基于標記點的配準算法如下所示: #include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL); VTK_MODULE_INIT(vtkRenderingFreeType); VTK_MODULE_INIT(vtkInteractionStyle);#include <vtkSmartPointer.h> #include <vtkPoints.h> #include <vtkLandmarkTransform.h> #include <vtkPolyData.h> #include <vtkVertexGlyphFilter.h> #include <vtkTransformPolyDataFilter.h> #include <vtkPolyDataMapper.h> #include <vtkActor.h> #include <vtkProperty.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkAxesActor.h> //研究一下坐標系顯示位置 #include <vtkOrientationMarkerWidget.h> int main() {vtkSmartPointer<vtkPoints> sourcePoints =vtkSmartPointer<vtkPoints>::New();double sourcePoint1[3] = { 0.5, 0, 0 };sourcePoints->InsertNextPoint(sourcePoint1);double sourcePoint2[3] = { 0, 0.5, 0 };sourcePoints->InsertNextPoint(sourcePoint2);double sourcePoint3[3] = { 0, 0, 0.5 };sourcePoints->InsertNextPoint(sourcePoint3);vtkSmartPointer<vtkPoints> targetPoints =vtkSmartPointer<vtkPoints>::New();double targetPoint1[3] = { 0.0, 0.0, 0.55 };targetPoints->InsertNextPoint(targetPoint1);double targetPoint2[3] = { 0.0, 0.55, 0.0 };targetPoints->InsertNextPoint(targetPoint2);double targetPoint3[3] = { -0.55, 0.0, 0.0 };targetPoints->InsertNextPoint(targetPoint3);//利用Landmark算法求變換矩陣vtkSmartPointer<vtkLandmarkTransform> landmarkTransform =vtkSmartPointer<vtkLandmarkTransform>::New();landmarkTransform->SetSourceLandmarks(sourcePoints);landmarkTransform->SetTargetLandmarks(targetPoints);landmarkTransform->SetModeToRigidBody(); //執行剛體配準landmarkTransform->Update();構造PolyData類型 進行圖形可視化vtkSmartPointer<vtkPolyData> source =vtkSmartPointer<vtkPolyData>::New();source->SetPoints(sourcePoints);vtkSmartPointer<vtkPolyData> target =vtkSmartPointer<vtkPolyData>::New();target->SetPoints(targetPoints);/vtkSmartPointer<vtkVertexGlyphFilter> sourceGlyphFilter =vtkSmartPointer<vtkVertexGlyphFilter>::New();sourceGlyphFilter->SetInputData(source);sourceGlyphFilter->Update();vtkSmartPointer<vtkVertexGlyphFilter> targetGlyphFilter =vtkSmartPointer<vtkVertexGlyphFilter>::New();targetGlyphFilter->SetInputData(target);targetGlyphFilter->Update();源數據施加配準變換矩陣vtkSmartPointer<vtkTransformPolyDataFilter> transformFilter =vtkSmartPointer<vtkTransformPolyDataFilter>::New();transformFilter->SetInputData(sourceGlyphFilter->GetOutput());transformFilter->SetTransform(landmarkTransform);transformFilter->Update();/vtkSmartPointer<vtkPolyDataMapper> sourceMapper =vtkSmartPointer<vtkPolyDataMapper>::New();sourceMapper->SetInputConnection(sourceGlyphFilter->GetOutputPort());vtkSmartPointer<vtkActor> sourceActor =vtkSmartPointer<vtkActor>::New();sourceActor->SetMapper(sourceMapper);sourceActor->GetProperty()->SetColor(1, 1, 0);sourceActor->GetProperty()->SetPointSize(10);vtkSmartPointer<vtkPolyDataMapper> targetMapper =vtkSmartPointer<vtkPolyDataMapper>::New();targetMapper->SetInputConnection(targetGlyphFilter->GetOutputPort());vtkSmartPointer<vtkActor> targetActor =vtkSmartPointer<vtkActor>::New();targetActor->SetMapper(targetMapper);targetActor->GetProperty()->SetColor(0, 1, 0);targetActor->GetProperty()->SetPointSize(10);vtkSmartPointer<vtkPolyDataMapper> solutionMapper =vtkSmartPointer<vtkPolyDataMapper>::New();solutionMapper->SetInputConnection(transformFilter->GetOutputPort());vtkSmartPointer<vtkActor> solutionActor =vtkSmartPointer<vtkActor>::New();solutionActor->SetMapper(solutionMapper);solutionActor->GetProperty()->SetColor(1, 0, 0);solutionActor->GetProperty()->SetPointSize(10);vtkSmartPointer<vtkRenderer> render =vtkSmartPointer<vtkRenderer>::New();render->AddActor(sourceActor);render->AddActor(targetActor);render->AddActor(solutionActor);render->SetBackground(0, 0, 0);vtkSmartPointer<vtkRenderWindow> rw =vtkSmartPointer<vtkRenderWindow>::New();rw->AddRenderer(render);rw->SetSize(480, 480);rw->SetWindowName("Regisration by Landmark");//設置坐標系顯示功能vtkSmartPointer<vtkAxesActor> axes =vtkSmartPointer<vtkAxesActor>::New();axes->SetScale(10);render->AddActor(axes);vtkSmartPointer<vtkRenderWindowInteractor> rwi =vtkSmartPointer<vtkRenderWindowInteractor>::New();rwi->SetRenderWindow(rw);/************************************************************/vtkSmartPointer<vtkOrientationMarkerWidget> widget =vtkSmartPointer<vtkOrientationMarkerWidget>::New();widget->SetOutlineColor(0.9300, 0.5700, 0.1300);widget->SetOrientationMarker(axes);widget->SetInteractor(rwi); //加入鼠標交互widget->SetViewport(0.0, 0.0, 0.3, 0.3); //設置顯示位置widget->SetEnabled(1);widget->InteractiveOn();//開啟鼠標交互/************************************************************/render->ResetCamera();rw->Render();rwi->Initialize();rwi->Start();return 0; }輸出結果:
黃色散點代表待配準點集;綠色散點代表金標準;紅色散點代表施加變換矩陣后的源數據點集。 vtkVertexGliphFilter類顯示點集!!!VTKTransformPolyDataFilter用來對源標記點進行變換來顯示配準后的點集,SetTransform()直接設置為vtkLandmarkTransform的變換結果。
2.VTKLandmarkTransform類
VTKLandmarkTransform類的使用比較簡單,只需要設定源標記點和目標標記點。SetModeToRigidBody()函數用于設置其配準變換類型為剛體變換,僅包括簡單的平移和旋轉(六個自由度)。此外還有一個更為廣泛應用的函數——SetModeToSimilarity,設置為相似變換,包括平移、旋轉和放縮變換(七個自由度)。以及SetModeToAffine()函數設置仿射變換。默認情況,就采用相似變換進行配準。3.vtkAxesActor類
有的時候,在顯示三維物體時,我們希望知道當前場景對應的坐標系位置或者方向,這樣在旋轉物體的時候,就能夠很清楚地看到當前正對這視野的是什么面xy平面,還是y軸等信息了。在vtk庫中有一個vtkAxesActor負責顯示坐標系,在查閱了vtk的wiki之后,找到了兩個示例,在這里將兩者結合起來,放在同一個例子中顯示,并用java代碼重寫。 其中,第一個示例:http://vtk.org/Wiki/VTK/Examples/Cxx/GeometricObjects/Axes 是直接將vtkAxesActor加入到renderer中進行顯示: //設置坐標系顯示功能vtkSmartPointer<vtkAxesActor> axes =vtkSmartPointer<vtkAxesActor>::New();axes->SetScale(10);render->AddActor(axes);
而第二個示例:
http://vtk.org/Wiki/VTK/Examples/Cxx/Visualization/DisplayCoordinateAxes 是以Widget的方式在一個獨立的視口中顯示,比較適合用來放在左下角指示當前的坐標系位置:
vtkSmartPointer<vtkOrientationMarkerWidget> widget =vtkSmartPointer<vtkOrientationMarkerWidget>::New();widget->SetOutlineColor(0.9300, 0.5700, 0.1300);widget->SetOrientationMarker(axes);widget->SetInteractor(rwi); //加入鼠標交互widget->SetViewport(0.0, 0.0, 0.3, 0.3); //設置顯示位置widget->SetEnabled(1);widget->InteractiveOn();//開啟鼠標交互
4.參看資料
1.《C++ primer》2.《The VTK User’s Guide – 11thEdition》
3. ?張曉東, 羅火靈. VTK圖形圖像開發進階[M]. 機械工業出版社, 2015.
總結
以上是生活随笔為你收集整理的VTK修炼之道57:图形基本操作进阶_点云配准技术(LandMark标记点算法和坐标系显示方法)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 不信不能雷倒你!超牛高考作文
- 下一篇: VTK修炼之道58:图形基本操作进阶_点