在Opencv中有个Viz模块,可以显示三维物体,还可以实现三维动画,本来是很好的东东,但是里面的函数、类的说明太过简单,始终不得要领。不过其中一个扩展功能非常好,就是你可以在vtk中设计自己的模型类,在Opencv中的Viz3d窗口中显示。
在这里我用vtk中的vtkSurfaceReconstructionFilter类,这是一个对空间点拟合曲面的函数,重新封装了该函数,创建了自己的类:MySurfaceReconstruction,该类可以直接在Viz中的Viz3d窗口中显示。
本程序中所需要的头文件如下:
#ifndef INITIAL_OPENGL#define INITIAL_OPENGL#includeVTK_MODULE_INIT(vtkRenderingOpenGL)VTK_MODULE_INIT(vtkInteractionStyle)#endif#include #include #include #include #include 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){ vtkSmartPointerm_Points=vtkSmartPointer ::New(); vtkSmartPointer vertices=vtkSmartPointer ::New(); int numOfpixs=0; for(int i=0;i (i,j); m_Points->InsertPoint(numOfpixs,x,y,z); //_加入点信息 vertices->InsertNextCell(numOfpixs); //_加入细胞顶点信息----用于渲染点集 vertices->InsertCellPoint(numOfpixs); numOfpixs ++; } } vtkSmartPointer points=vtkSmartPointer ::New(); points->SetPoints(m_Points); vtkSmartPointer surf=vtkSmartPointer ::New(); surf->SetInputData(points); vtkSmartPointer contour=vtkSmartPointer ::New(); contour->SetInputConnection(surf->GetOutputPort()); contour->SetValue(0,0.0); vtkSmartPointer pointMapper=vtkSmartPointer ::New(); pointMapper->SetInputConnection(contour->GetOutputPort()); vtkSmartPointer actor=vtkSmartPointer ::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(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;}
下面是运行结果: