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之间再显示。执行结果如下:
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.
原文:http://blog.csdn.net/shenziheng1/article/details/54747853