1. 程式人生 > >5.4.4 邊緣檢測-拉普拉斯運算元

5.4.4 邊緣檢測-拉普拉斯運算元

拉普拉斯運算元是一個二階邊緣運算元,即梯度的散度。拉普拉斯運算元的實現也是通過模板實現。常用的拉普拉斯模板定義如下:

                                                           

拉普拉斯運算元計算影象的二階導數,對於影象噪聲比較敏感。拉普拉斯運算元的結果為標量,表示邊緣的寬度。但是它常產生雙畫素寬邊緣,而且不能提供方向資訊,因此較少直接用於邊緣檢測。在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