在Opencv中有个Viz模块,可以显示三维物体,还可以实现三维动画,本来是很好的东东,但是里面的函数、类的说明太过简单,始终不得要领。不过其中一个扩展功能非常好,就是你可以在vtk中设计自己的模型类,在Opencv中的Viz3d窗口中显示。
在Matla中有个plot3d()函数,可以三维显示二维图像,可是在Opencv中却无法实现。因此,在这里我用vtk中的vtkSurfaceReconstructionFilter类,这是一个对空间点拟合曲面的函数,重新封装了该函数,创建了自己的类:MySurfaceReconstruction,该类可以直接在Viz中的Viz3d窗口中显示。
下面是该类的代码:
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); }
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; }