5.4.4 边缘检测-拉普拉斯算子

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kateyabc/article/details/83627692

拉普拉斯算子是一个二阶边缘算子,即梯度的散度。拉普拉斯算子的实现也是通过模板实现。常用的拉普拉斯模板定义如下:

                                                           

拉普拉斯算子计算图像的二阶导数,对于图像噪声比较敏感。拉普拉斯算子的结果为标量,表示边缘的宽度。但是它常产生双像素宽边缘,而且不能提供方向信息,因此较少直接用于边缘检测。在VTK中由vtkImageLaplacian实现。

#include <vtkAutoInit.h>
#include <vtkSmartPointer.h>
#include <vtkJPEGReader.h>
#include <vtkImageData.h>
#include <vtkImageLaplacian.h>
#include <vtkImageShiftScale.h>
#include <vtkImageActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>

int main()
{

	vtkSmartPointer<vtkJPEGReader> reader =	vtkSmartPointer<vtkJPEGReader>::New();
	reader->SetFileName("data\\lena-gray.jpg");
	reader->Update();

	vtkSmartPointer<vtkImageLaplacian> lapFilter =	vtkSmartPointer<vtkImageLaplacian>::New();
	lapFilter->SetInputConnection(reader->GetOutputPort());
	lapFilter->SetDimensionality(2);

	double range[2];
	lapFilter->GetOutput()->GetScalarRange(range); //得到灰度的最大值和最小值

	vtkSmartPointer<vtkImageShiftScale> ShiftScale = vtkSmartPointer<vtkImageShiftScale>::New();
	ShiftScale->SetOutputScalarTypeToUnsignedChar();
	ShiftScale->SetScale(255 / (range[1] - range[0])); //SetShift()设置偏移量,SetScale()用于设置放缩值
	ShiftScale->SetShift(-range[0]);
	ShiftScale->SetInputConnection(lapFilter->GetOutputPort());
	ShiftScale->Update();

	vtkSmartPointer<vtkImageActor> originalActor = vtkSmartPointer<vtkImageActor>::New();
	originalActor->SetInputData(reader->GetOutput());

	vtkSmartPointer<vtkImageActor> gradActor = vtkSmartPointer<vtkImageActor>::New();
	gradActor->SetInputData(ShiftScale->GetOutput());

	double originalViewport[4] = { 0.0, 0.0, 0.5, 1.0 };
	double gradviewport[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, 1.0, 1.0);

	vtkSmartPointer<vtkRenderer> gradRenderer = vtkSmartPointer<vtkRenderer>::New();
	gradRenderer->SetViewport(gradviewport);
	gradRenderer->AddActor(gradActor);
	gradRenderer->ResetCamera();
	gradRenderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderWindow> rw = vtkSmartPointer<vtkRenderWindow>::New();
	rw->AddRenderer(originalRenderer);
	rw->AddRenderer(gradRenderer);
	rw->SetSize(540, 320);
	rw->Render();
	rw->SetWindowName("Edge by Laplacian");

	vtkSmartPointer<vtkRenderWindowInteractor> rwi = vtkSmartPointer<vtkRenderWindowInteractor>::New();
	vtkSmartPointer<vtkInteractorStyleImage> style = vtkSmartPointer<vtkInteractorStyleImage>::New();

	rwi->SetInteractorStyle(style);
	rwi->SetRenderWindow(rw);
	rwi->Initialize();
	rwi->Start();

	return 0;
}

运行结果如下:

vtkImageLaplacian输入和输出数据都是vtkImageData,与梯度算子不同,该filter的输出图像像素为标量。函数SetDimensionality用于设置输入图像的维数,默认为2维。计算完毕后,利用vtkImageShiftScale将图像的数据范围变换至0-255之间。

参考资料:

1.《The Visualization Toolkit – AnObject-Oriented Approach To 3D Graphics (4th Edition)》
2. 张晓东, 罗火灵. VTK图形图像开发进阶[M]. 机械工业出版社, 2015.

所用软件:vtk7.0+visual studio 2013


注:此文知识学习笔记,仅记录完整程序和实现结果,具体原理参见:

https://blog.csdn.net/www_doling_net/article/details/8541534

https://blog.csdn.net/shenziheng1/article/category/6114053/4

猜你喜欢

转载自blog.csdn.net/kateyabc/article/details/83627692