首页 > 其他 > 详细

VTK修炼之道33:边缘检测_Sobel算子

时间:2017-01-27 11:04:08      阅读:328      评论:0      收藏:0      [点我收藏+]

1.Sobel算子用于提取图像边缘

Sobel算子也是一种常用的梯度算子。Sobel算子计算稍微复杂,它采用3x3的模板。计算时模板在图像上移动,并在每个位置上计算对应中心像素的梯度值。
技术分享
VTK中vtkSobel2D计算图像的sobel算子,使用代码如下:
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL);

#include <vtkSmartPointer.h>
#include <vtkJPEGReader.h>
#include <vtkImageSobel2D.h>
#include <vtkImageExtractComponents.h>
#include <vtkImageMathematics.h>
#include <vtkImageData.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("lena.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();
	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);
	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, 0, 0);

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

	vtkSmartPointer<vtkRenderer> ySobelRender =
		vtkSmartPointer<vtkRenderer>::New();
	ySobelRender->SetViewport(ySobelView);
	ySobelRender->AddActor(ySobelActor);
	ySobelRender->ResetCamera();
	ySobelRender->SetBackground(0, 0, 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之间再显示。
执行结果如下:
技术分享

2.参看资料

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

VTK修炼之道33:边缘检测_Sobel算子

原文:http://blog.csdn.net/shenziheng1/article/details/54747853

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!