5.4.2 边缘检测-sobel算子

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

Sobel算子也是一种常用的梯度算子。Sobel算子计算稍微复杂,它采用3x3的模板。计算时模板在图像上移动,并在每个位置上计算对应中心像素的梯度值。

VTK中vtkSobel2D计算图像的sobel算子,使用代码如下:

/*-------------------------------------sobel----------------------------------------------------------------------------*/
#include <vtkSmartPointer.h>
#include <vtkJPEGReader.h>
#include <vtkImageSobel2D.h> //
#include <vtkImageExtractComponents.h> //vtkImageExtractComponents提取各方向的梯度分量
#include <vtkImageMathematics.h> //对各个分量图像计算绝对值
#include <vtkImageData.h>
#include <vtkImageShiftScale.h> //数据范围调整数值范围到0-255
#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<vtkImageSobel2D> sobelFilter =	vtkSmartPointer<vtkImageSobel2D>::New();
	sobelFilter->SetInputConnection(reader->GetOutputPort());//包含横向和竖向边缘

	//提取X向边缘成分
	vtkSmartPointer<vtkImageExtractComponents> xSobel =	vtkSmartPointer<vtkImageExtractComponents>::New();
	xSobel->SetComponents(0);//提取第一成分即X向梯度
	xSobel->SetInputConnection(sobelFilter->GetOutputPort());
	xSobel->Update();

	vtkSmartPointer<vtkImageMathematics> absFilter = vtkSmartPointer<vtkImageMathematics>::New();
	//由于计算Sobel算子的值可能存在负值,因此利用vtkImageMathematics对各个分量图像计算绝对值,再由vtkImageShiftScale将图像的数值范围调节到0-255之间再显示
	absFilter->SetOperationToAbsoluteValue();//将属性设置为绝对值模式
	absFilter->SetInputConnection(xSobel->GetOutputPort());
	absFilter->Update();

	double xRange[2];
	absFilter->GetOutput()->GetScalarRange(xRange);

	vtkSmartPointer<vtkImageShiftScale> xShiftScale = vtkSmartPointer<vtkImageShiftScale>::New();
	xShiftScale->SetOutputScalarTypeToUnsignedChar();//强制类型转换 方便显示
	xShiftScale->SetScale(255 / xRange[1]);//设置属性
	xShiftScale->SetInputConnection(absFilter->GetOutputPort());
	xShiftScale->Update();

	//提取Y向边缘成分
	vtkSmartPointer<vtkImageExtractComponents> ySobel = vtkSmartPointer<vtkImageExtractComponents>::New();
	ySobel->SetComponents(1);//提取第二成分即y向梯度
	ySobel->SetInputConnection(sobelFilter->GetOutputPort());
	ySobel->Update();

	vtkSmartPointer<vtkImageMathematics> absYsobel = vtkSmartPointer<vtkImageMathematics>::New();
	absYsobel->SetOperationToAbsoluteValue();
	absYsobel->SetInputConnection(ySobel->GetOutputPort());
	absYsobel->Update();

	double yRange[2];
	absYsobel->GetOutput()->GetScalarRange(yRange);

	vtkSmartPointer<vtkImageShiftScale> yShiftScale =	vtkSmartPointer<vtkImageShiftScale>::New();
	yShiftScale->SetOutputScalarTypeToUnsignedChar();
	yShiftScale->SetScale(255 / yRange[1]);
	yShiftScale->SetInputConnection(absYsobel->GetOutputPort());
	yShiftScale->Update();
	////////////////////////////////////////////////////////////
	vtkSmartPointer<vtkImageActor> origActor =	vtkSmartPointer<vtkImageActor>::New();
	origActor->SetInputData(reader->GetOutput());

	vtkSmartPointer<vtkImageActor> xSobelActor =	vtkSmartPointer<vtkImageActor>::New();
	xSobelActor->SetInputData(xShiftScale->GetOutput());

	vtkSmartPointer<vtkImageActor> ySobelActor =	vtkSmartPointer<vtkImageActor>::New();
	ySobelActor->SetInputData(yShiftScale->GetOutput());
	/////////////////////////////////////////////////////////////
	double origView[4] = { 0, 0, 0.33, 1 };
	double xSobelView[4] = { 0.33, 0, 0.66, 1 };
	double ySobelView[4] = { 0.66, 0, 1, 1 };
	vtkSmartPointer<vtkRenderer> origRender =	vtkSmartPointer<vtkRenderer>::New();
	origRender->SetViewport(origView);
	origRender->AddActor(origActor);
	origRender->ResetCamera();
	origRender->SetBackground(1, 1, 1);

	vtkSmartPointer<vtkRenderer> xSobelRender =	vtkSmartPointer<vtkRenderer>::New();
	xSobelRender->SetViewport(xSobelView);
	xSobelRender->AddActor(xSobelActor);
	xSobelRender->ResetCamera();
	xSobelRender->SetBackground(1, 1, 1);

	vtkSmartPointer<vtkRenderer> ySobelRender =	vtkSmartPointer<vtkRenderer>::New();
	ySobelRender->SetViewport(ySobelView);
	ySobelRender->AddActor(ySobelActor);
	ySobelRender->ResetCamera();
	ySobelRender->SetBackground(1, 1, 1);
	//////////////////////////////////////////////
	vtkSmartPointer<vtkRenderWindow> rw = vtkSmartPointer<vtkRenderWindow>::New();
	rw->AddRenderer(origRender);
	rw->AddRenderer(xSobelRender);
	rw->AddRenderer(ySobelRender);
	rw->SetSize(960, 320);
	rw->SetWindowName("Edge by Soebl");

	vtkSmartPointer<vtkRenderWindowInteractor> rwi = vtkSmartPointer<vtkRenderWindowInteractor>::New();
	vtkSmartPointer<vtkInteractorStyleImage> style = vtkSmartPointer<vtkInteractorStyleImage>::New();
	rwi->SetInteractorStyle(style);
	rwi->SetRenderWindow(rw);
	rwi->Initialize();
	rwi->Start();

	return 0;
}

运行结果:

该例中计算利用Sobel算子计算图像的梯度图像,然后提取X方向的梯度分量和Y方向的梯度分量。
由于计算Sobel算子的值可能存在负值,因此利用vtkImageMathematics对各个分量图像计算绝对值,再由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

扫描二维码关注公众号,回复: 4211347 查看本文章

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

猜你喜欢

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