基於OpenCV的三維數據點的曲面重構_MySurefaceReconstruction


在Opencv中有個Viz模塊,可以顯示三維物體,還可以實現三維動畫,本來是很好的東東,但是里面的函數、類的說明太過簡單,始終不得要領。不過其中一個擴展功能非常好,就是你可以在vtk中設計自己的模型類,在Opencv中的Viz3d窗口中顯示。

在這里我用vtk中的vtkSurfaceReconstructionFilter類,這是一個對空間點擬合曲面的函數,重新封裝了該函數,創建了自己的類:MySurfaceReconstruction,該類可以直接在Viz中的Viz3d窗口中顯示。

本程序中所需要的頭文件如下:

#ifndef INITIAL_OPENGL
#define INITIAL_OPENGL
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL)
VTK_MODULE_INIT(vtkInteractionStyle)
#endif

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/viz/vizcore.hpp>
#include <opencv2/viz/viz3d.hpp>
#include <opencv2/viz/widget_accessor.hpp>
using namespace cv;
using namespace std;

#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkSmartPointer.h"
#include "vtkProperty.h"
#include "vtkPoints.h"
#include "vtkCellArray.h"
#include "vtkSurfaceReconstructionFilter.h"
#include "vtkContourFilter.h"

 

 

下面是該類的代碼:

class MySurfaceReconstruction:public viz::Widget3D
{
public:
    MySurfaceReconstruction(const Mat&src, const viz::Color color = viz::Color::white());

};
MySurfaceReconstruction::MySurfaceReconstruction(const Mat &src, const viz::Color color)
{

    vtkSmartPointer<vtkPoints>m_Points=vtkSmartPointer<vtkPoints>::New();
    vtkSmartPointer<vtkCellArray>vertices=vtkSmartPointer<vtkCellArray>::New();
    int numOfpixs=0;
    for(int i=0;i<src.rows;i++)
    {
        for(int j=0;j<src.cols;j++)
        {
            double x=j,y=i;
            double z=src.at<double>(i,j);
            m_Points->InsertPoint(numOfpixs,x,y,z);  //_加入點信息
            vertices->InsertNextCell(numOfpixs);     //_加入細胞頂點信息----用於渲染點集
            vertices->InsertCellPoint(numOfpixs);
            numOfpixs ++;
        }
    }

    vtkSmartPointer<vtkPolyData>points=vtkSmartPointer<vtkPolyData>::New();
    points->SetPoints(m_Points);
    vtkSmartPointer<vtkSurfaceReconstructionFilter>surf=vtkSmartPointer<vtkSurfaceReconstructionFilter>::New();
    surf->SetInputData(points);

    vtkSmartPointer<vtkContourFilter>contour=vtkSmartPointer<vtkContourFilter>::New();
    contour->SetInputConnection(surf->GetOutputPort());
    contour->SetValue(0,0.0);

    vtkSmartPointer<vtkPolyDataMapper>pointMapper=vtkSmartPointer<vtkPolyDataMapper>::New();
    pointMapper->SetInputConnection(contour->GetOutputPort());
    vtkSmartPointer<vtkActor>actor=vtkSmartPointer<vtkActor>::New();
    actor->SetMapper(pointMapper);
    // Store this actor in the widget in order that visualizer can access it
    viz::WidgetAccessor::setProp(*this, actor);
    // Set the color of the widget. This has to be called after WidgetAccessor.
    setColor(color);

}

為了方便測試,自定義了一個高斯分布函數:

//*9. 獲取二維高斯卷積核
Mat Gaussian_kernel(int kernel_size, double sigma)
{
    int c = (kernel_size) / 2;
    Mat kernel(kernel_size, kernel_size, CV_64FC1);
    double s = 2 * sigma*sigma;
    for (int i = 0; i < kernel_size; i++)
    {
        for (int j = 0; j < kernel_size; j++)
        {
            double x = j - c;
            double y=i - c;
            kernel.ptr<double>(i)[j] = exp(-(x*x+y*y)/s) ;
        }
    }
    Scalar sumOfKernel= cv::sum(kernel);//求kernel的所有像素值之和
    kernel /=sumOfKernel[0];//歸一化,避免卷積過程中增大總能量
    return kernel;
}

 

 下面是測試程序,通過上面的高斯函數創建一個高斯分布二維矩陣mat,作為MySurfaceReconstruction類的初始輸入,MySurfaceReconstruction可以將mat轉化成Widget3d類物體,並通過Viz3d顯示。

 


int
main() { /// Create a window viz::Viz3d myWindow("Creating Widgets"); /// Create a triangle widget cv::Mat mat=Gaussian_kernel(15,1); mat *=10; MySurfaceReconstruction tw(mat, viz::Color::red()); /// Show widget in the visualizer window myWindow.showWidget("my surface", tw); /// Start event loop myWindow.spin(); return 0; }

 下面是運行結果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM