1.均值滤波
均值滤波是一种经常用到的平滑方法,其对应的模板各个像素的值为1。在VTK中没有直接实现均值滤波的类,但是我们可以通过图像卷积运算来实现。卷积运算通过vtkImageConvolve类实现。通过vtkImageConvolve类,只需要设置相应的卷积模板,便可以实现多种空域图像滤波。
下面代码说明了怎样使用vtkImageConvolve类来实现图像的均值滤波:
#include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL); #include <vtkSmartPointer.h> #include <vtkJPEGReader.h> #include <vtkImageCast.h> //图像数据类型转换为计算类型 #include <vtkImageData.h> #include <vtkImageConvolve.h> //图像卷积运行 #include <vtkImageShiftScale.h> //设置像素值范围 //#include <vtkImageMandelbrotSource.h> #include <vtkImageActor.h> #include <vtkRenderer.h> #include <vtkImageMandelbrotSource.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkInteractorStyleImage.h> int main() { vtkSmartPointer<vtkJPEGReader> reader = vtkSmartPointer<vtkJPEGReader>::New(); reader->SetFileName("lena.jpg"); reader->Update(); vtkSmartPointer<vtkImageCast> originalCastFilter = vtkSmartPointer<vtkImageCast>::New(); originalCastFilter->SetInputConnection(reader->GetOutputPort()); //建管线 originalCastFilter->SetOutputScalarTypeToFloat(); //设置属性 originalCastFilter->Update(); vtkSmartPointer<vtkImageConvolve> convolveFilter = vtkSmartPointer<vtkImageConvolve>::New(); convolveFilter->SetInputConnection(originalCastFilter->GetOutputPort()); //建管线 double kernel[25] = { 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04 }; convolveFilter->SetKernel5x5(kernel); convolveFilter->Update(); vtkSmartPointer<vtkImageCast> convCastFilter = vtkSmartPointer<vtkImageCast>::New(); convCastFilter->SetInputData(convolveFilter->GetOutput()); convCastFilter->SetOutputScalarTypeToUnsignedChar(); //转换为图像数据 convCastFilter->Update(); /// vtkSmartPointer<vtkImageActor> originalActor = vtkSmartPointer<vtkImageActor>::New(); originalActor->SetInputData(reader->GetOutput()); vtkSmartPointer<vtkImageActor> convolvedActor = vtkSmartPointer<vtkImageActor>::New(); convolvedActor->SetInputData(convCastFilter->GetOutput()); double leftViewport[4] = { 0.0, 0.0, 0.5, 1.0 }; double rightViewport[4] = { 0.5, 0.0, 1.0, 1.0 }; vtkSmartPointer<vtkRenderer> originalRenderer = vtkSmartPointer<vtkRenderer>::New(); originalRenderer->SetViewport(leftViewport); originalRenderer->AddActor(originalActor); originalRenderer->SetBackground(1.0, 1.0, 1.0); originalRenderer->ResetCamera(); vtkSmartPointer<vtkRenderer> convolvedRenderer = vtkSmartPointer<vtkRenderer>::New(); convolvedRenderer->SetViewport(rightViewport); convolvedRenderer->AddActor(convolvedActor); convolvedRenderer->SetBackground(1.0, 1.0, 1.0); convolvedRenderer->ResetCamera(); vtkSmartPointer<vtkRenderWindow> rw = vtkSmartPointer<vtkRenderWindow>::New();; rw->AddRenderer(originalRenderer); rw->AddRenderer(convolvedRenderer); rw->SetSize(640, 320); rw->Render(); rw->SetWindowName("Smooth by MeanFilter"); vtkSmartPointer<vtkRenderWindowInteractor> rwi = vtkSmartPointer<vtkRenderWindowInteractor>::New(); vtkSmartPointer<vtkInteractorStyleImage> style = vtkSmartPointer<vtkInteractorStyleImage>::New(); rwi->SetInteractorStyle(style); rwi->SetRenderWindow(rw); rwi->Initialize(); rwi->Start(); return 0; }
首先vtkJPEGReader对象读取一幅图像。考虑到进行卷积运算时数据范围的变化和精度要求,需要先将图像像素数据类型由unsigned char转换到float类型,该变换通过vtkImageCast实现,对应的设置函数SetOutputScalarTypeToFloat()。接下来需要定义卷积算子和卷积模板。vtkImageConvolve类实现图像的卷积运算,它需要两个输入。一个是需要进行卷积的图像,这里为vtkJPEGReader读取的图像数据,第二个是卷积模板数组。SetKernel5x5()函数接收一个5x5的卷积模板数组,即本例上定义的kernel数组。执行Update()后即可完成卷积运算。需要注意的是,卷积模板对应的系数之和应该为1,否则需要对计算结果进行归一化处理。另外该类中还定义了3x3和7x7的卷积模板设置函数,使用过程是一样的。卷积完成以后,再次通过vtkImageCast将float数据类型转换为unsigned char进行图像显示。均值滤波的结果如下:
2.高斯滤波
高斯平滑的原理类似于均值滤波。均值滤波模板的系数都是一样的,而高斯平滑则是需要根据像素与模板中心的距离来定义权重。权重的计算方法是采用高斯分布,离中心越远,权重越小。
下面是一个利用Gauss滤波进行图像平滑的实例:
#include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL); #include <vtkSmartPointer.h> #include <vtkJPEGReader.h> #include <vtkImageCast.h> #include <vtkImageData.h> #include <vtkImageGaussianSmooth.h> #include <vtkImageActor.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkInteractorStyleImage.h> //#include <vtkImageEllipsoidSource.h> int main() { vtkSmartPointer<vtkJPEGReader> reader = vtkSmartPointer<vtkJPEGReader>::New(); reader->SetFileName("lena.jpg"); reader->Update(); vtkSmartPointer<vtkImageGaussianSmooth> gaussianSmoothFilter = vtkSmartPointer<vtkImageGaussianSmooth>::New(); gaussianSmoothFilter->SetInputConnection(reader->GetOutputPort()); gaussianSmoothFilter->SetDimensionality(2); gaussianSmoothFilter->SetRadiusFactor(5); //设置模板范围 gaussianSmoothFilter->SetStandardDeviation(3);//正态分布/高斯分布标准差 gaussianSmoothFilter->Update(); vtkSmartPointer<vtkImageActor> originalActor = vtkSmartPointer<vtkImageActor>::New(); originalActor->SetInputData(reader->GetOutput()); vtkSmartPointer<vtkImageActor> smoothedActor = vtkSmartPointer<vtkImageActor>::New(); smoothedActor->SetInputData(gaussianSmoothFilter->GetOutput()); double originalViewport[4] = { 0.0, 0.0, 0.5, 1.0 }; double smoothedViewport[4] = { 0.5, 0.0, 1.0, 1.0 }; vtkSmartPointer<vtkRenderer> originalRenderer = vtkSmartPointer<vtkRenderer>::New(); originalRenderer->SetViewport(originalViewport); originalRenderer->AddActor(originalActor); originalRenderer->ResetCamera(); originalRenderer->SetBackground(1.0, 0, 0); vtkSmartPointer<vtkRenderer> gradientMagnitudeRenderer = vtkSmartPointer<vtkRenderer>::New(); gradientMagnitudeRenderer->SetViewport(smoothedViewport); gradientMagnitudeRenderer->AddActor(smoothedActor); gradientMagnitudeRenderer->ResetCamera(); gradientMagnitudeRenderer->SetBackground(1.0, 1.0, 1.0); vtkSmartPointer<vtkRenderWindow> rw = vtkSmartPointer<vtkRenderWindow>::New(); rw->AddRenderer(originalRenderer); rw->AddRenderer(gradientMagnitudeRenderer); rw->SetSize(640, 320); rw->SetWindowName("Smooth by Gaussian"); vtkSmartPointer<vtkRenderWindowInteractor> rwi = vtkSmartPointer<vtkRenderWindowInteractor>::New(); vtkSmartPointer<vtkInteractorStyleImage> style = vtkSmartPointer<vtkInteractorStyleImage>::New(); rwi->SetInteractorStyle(style); rwi->SetRenderWindow(rw); rwi->Initialize(); rwi->Start(); return 0; }
vtkImageGaussianSmooth类默认是执行三维高斯滤波;SetDimensionality()根据需要设置相应的维数;SetRadiusFactor()用于设置高斯模板的大小,当超出该模板的范围时,系数取0;SetStandardDeviation()用于设置高斯分布函数的标准差。高斯平滑效果如下所示:
3.中值滤波
vtkImageHybridMedian2D实现了对二维图像的中值滤波。其实现原理是,采用一个5x5的模板,逐次将模板中心对应于图像的每个像素上,将模板图像覆盖的像素的中值作为当前像素的输出值。
#include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL); #include <vtkSmartPointer.h> #include <vtkJPEGReader.h> #include <vtkImageData.h> #include <vtkImageCast.h> #include <vtkImageHybridMedian2D.h> #include <vtkImageActor.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkInteractorStyleImage.h> int main(int argc, char* argv[]) { vtkSmartPointer<vtkJPEGReader> reader = vtkSmartPointer<vtkJPEGReader>::New(); reader->SetFileName("lena.jpg"); reader->Update(); vtkSmartPointer<vtkImageHybridMedian2D> hybridMedian = vtkSmartPointer<vtkImageHybridMedian2D>::New(); hybridMedian->SetInputData(reader->GetOutput()); hybridMedian->Update(); /// vtkSmartPointer<vtkImageActor> originalActor = vtkSmartPointer<vtkImageActor>::New(); originalActor->SetInputData(reader->GetOutput()); vtkSmartPointer<vtkImageActor> hybridMedianActor = vtkSmartPointer<vtkImageActor>::New(); hybridMedianActor->SetInputData(hybridMedian->GetOutput()); / double originalViewport[4] = { 0.0, 0.0, 0.5, 1.0 }; double hybridMedianViewport[4] = { 0.5, 0.0, 1.0, 1.0 }; vtkSmartPointer<vtkRenderer> originalRenderer = vtkSmartPointer<vtkRenderer>::New(); originalRenderer->SetViewport(originalViewport); originalRenderer->AddActor(originalActor); originalRenderer->ResetCamera(); originalRenderer->SetBackground(1.0,0,0); vtkSmartPointer<vtkRenderer> hybridMedianRenderer = vtkSmartPointer<vtkRenderer>::New(); hybridMedianRenderer->SetViewport(hybridMedianViewport); hybridMedianRenderer->AddActor(hybridMedianActor); hybridMedianRenderer->ResetCamera(); hybridMedianRenderer->SetBackground(1.0, 1.0, 1.0); // vtkSmartPointer<vtkRenderWindow> rw = vtkSmartPointer<vtkRenderWindow>::New(); rw->AddRenderer(originalRenderer); rw->AddRenderer(hybridMedianRenderer); rw->SetSize(640, 320); rw->Render(); rw->SetWindowName("MedianFilterExample"); vtkSmartPointer<vtkRenderWindowInteractor> rwi = vtkSmartPointer<vtkRenderWindowInteractor>::New(); vtkSmartPointer<vtkInteractorStyleImage> style = vtkSmartPointer<vtkInteractorStyleImage>::New(); rwi->SetInteractorStyle(style); rwi->SetRenderWindow(rw); rwi->Initialize(); rwi->Start(); return 0; }
该类使用非常简单,不需要用户设置任何参数。该方法能够有效的保持图像边缘,并对于椒盐噪声有较好的抑制作用。对于三维图像,则使用vtkImageHybridMedian3D类。
执行结果如下:
4.各向异性扩散滤波
标签:__,滤波器,rw,1.0,VTK,0.04,vtkSmartPointer,New,include From: https://blog.51cto.com/u_15926338/5980094高斯平滑方法在平滑噪声的同时,模糊了图像的重要边缘图像。
各向异性滤波是一种基于偏微分方程的滤波技术,建立于热量的各向异性扩散理论。
各向异性滤波在图像的平坦区域选择大尺度平滑,而边缘区域则选择小尺度的平滑,在抑制噪声的同时保持了图像的边缘信息。
vtkImageAnisotropicDiffusion2D(vtkImageAnisotropicDiffusion3D)实现图像各向异性扩散滤波,代码如下:
#include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL); #include <vtkSmartPointer.h> #include <vtkJPEGReader.h> #include <vtkImageCast.h> #include <vtkImageAnisotropicDiffusion2D.h> #include <vtkImageActor.h> #include <vtkCamera.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkInteractorStyleImage.h> int main() { vtkSmartPointer<vtkJPEGReader> reader = vtkSmartPointer<vtkJPEGReader>::New(); reader->SetFileName("lena.jpg"); vtkSmartPointer<vtkImageAnisotropicDiffusion2D> diffusion = vtkSmartPointer<vtkImageAnisotropicDiffusion2D>::New(); diffusion->SetInputConnection(reader->GetOutputPort()); diffusion->SetNumberOfIterations(100); diffusion->SetDiffusionThreshold(5); //小于该阈值扩散 diffusion->Update(); / vtkSmartPointer<vtkImageActor> originalActor = vtkSmartPointer<vtkImageActor>::New(); originalActor->SetInputData(reader->GetOutput()); vtkSmartPointer<vtkImageActor> diffusionActor = vtkSmartPointer<vtkImageActor>::New(); diffusionActor->SetInputData(diffusion->GetOutput()); double leftViewport[4] = { 0.0, 0.0, 0.5, 1.0 }; double rightViewport[4] = { 0.5, 0.0, 1.0, 1.0 }; vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New(); vtkSmartPointer<vtkRenderer> leftRenderer = vtkSmartPointer<vtkRenderer>::New(); leftRenderer->SetViewport(leftViewport); leftRenderer->AddActor(originalActor); leftRenderer->SetBackground(1.0, 0, 0); leftRenderer->SetActiveCamera(camera); leftRenderer->ResetCamera(); vtkSmartPointer<vtkRenderer> rightRenderer = vtkSmartPointer<vtkRenderer>::New(); rightRenderer->SetViewport(rightViewport); rightRenderer->SetBackground(1.0, 1.0, 1.0); rightRenderer->AddActor(diffusionActor); rightRenderer->SetActiveCamera(camera); / vtkSmartPointer<vtkRenderWindow> rw = vtkSmartPointer<vtkRenderWindow>::New(); rw->AddRenderer(leftRenderer); rw->AddRenderer(rightRenderer); rw->SetSize(640, 320); rw->SetWindowName("Smooth by AnistropicFilter"); vtkSmartPointer<vtkRenderWindowInteractor> rwi = vtkSmartPointer<vtkRenderWindowInteractor>::New(); vtkSmartPointer<vtkInteractorStyleImage> style = vtkSmartPointer<vtkInteractorStyleImage>::New(); rwi->SetInteractorStyle(style); rwi->SetRenderWindow(rw); rwi->Initialize(); rwi->Start(); return 0; }
vtkImageAnisotropicDiffusion2D类通过迭代方法实现。
其中SetNumberOfIterations()用于设置迭代的次数;
各向异性扩散滤波原理是在梯度较小的像素处进行较大幅度扩散,而在大梯度处则只进行细微的扩散。因此需要设置一个扩算的阈值DiffusionThreshold,这个阈值与图像的梯度有关。SetDiffusionThreshold()即是用来设置扩散阈值。该类中还有一个梯度标志GradientMagnitudeThreshold,用来设置梯度算子。当该标志开时梯度通过中心差分方法计算;当标志为关时,需要单独处理每个相邻像素。当像素与相邻像素梯度小于DiffusionThreshold时进行扩散处理。
下图是进行各向异性扩散滤波处理的结果: