图像中不连续的灰度值会产生边缘,图像的边缘检测是基于边界的图像分割方法的基础。分水岭算法通常是分割原图的梯度图像,而梯度实际上也反映图像的边缘信息
梯度算子对应于图像的一阶导数。图像的一阶导数一般是通过差分运算来近似的。VTK中可以用vtkImageCradient类计算图像梯度。
梯度是矢量,不能直接显示。使用vtkImageMagnitude对象来计算梯度矢量的2-范数,既矢量的模。利用vtkImageShiftScale将图像的数据范围调整到「0 255」然后显示。注意:彩色图像不能直接用来计算梯度,需要先转换为灰度图像。
#define HH 0
#ifndef HH
#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("C:/Users/Administrator/Pictures/1.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;
}
#else
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL)
VTK_MODULE_INIT(vtkInteractionStyle)
VTK_MODULE_INIT(vtkRenderingFreeType)
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL)
#include <vtkRenderer.h>
#include <vtkImageActor.h>
#include <vtkStructuredPoints.h>
#include <vtkSmartPointer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkPNGReader.h>
#include <vtkImageLuminance.h>
#include <vtkProperty.h>
#include <vtkImageGaussianSmooth.h>
#include <vtkImageCast.h>
#include <vtkImageGradient.h>
#include <vtkImageMagnitude.h>
#include <vtkImageNonMaximumSuppression.h>
#include <vtkImageConstantPad.h>
#include <vtkImageToStructuredPoints.h>
#include <vtkLinkEdgels.h>
#include <vtkThreshold.h>
#include <vtkGeometryFilter.h>
#include <vtkSubPixelPositionEdgels.h>
#include <vtkStripper.h>
#include <vtkPolyDataMapper.h>
#include <vtkCamera.h>
#include <vtkJPEGReader.h>
#include <vtkInteractorStyleImage.h>
#include <vtkImageShiftScale.h>
int main(int argc, char* argv[])
{
vtkSmartPointer<vtkJPEGReader> reader =
vtkSmartPointer<vtkJPEGReader>::New();
reader->SetFileName("C:/Users/Administrator/Pictures/1.jpg");
reader->Update();
vtkSmartPointer<vtkImageLuminance> luminanceFilter =
vtkSmartPointer<vtkImageLuminance>::New();
luminanceFilter->SetInputConnection(reader->GetOutputPort());
luminanceFilter->Update();
vtkSmartPointer<vtkImageGradient> gradientFilter =
vtkSmartPointer<vtkImageGradient>::New();
gradientFilter->SetInputConnection(luminanceFilter->GetOutputPort());
gradientFilter->SetDimensionality(2);
vtkSmartPointer<vtkImageMagnitude> magnitudeFilter =
vtkSmartPointer<vtkImageMagnitude>::New();
magnitudeFilter->SetInputConnection(gradientFilter->GetOutputPort());
magnitudeFilter->Update();
double range[2];
magnitudeFilter->GetOutput()->GetScalarRange(range);
vtkSmartPointer<vtkImageShiftScale> ShiftScale =
vtkSmartPointer<vtkImageShiftScale>::New();
ShiftScale->SetOutputScalarTypeToUnsignedChar();
ShiftScale->SetScale(255 / range[1]);
ShiftScale->SetInputConnection(magnitudeFilter->GetOutputPort());
ShiftScale->Update();
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> gradRenderer =
vtkSmartPointer<vtkRenderer>::New();
gradRenderer->SetViewport(gradviewport);
gradRenderer->AddActor(gradActor);
gradRenderer->ResetCamera();
gradRenderer->SetBackground(1.0, 1.0, 1.0);
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(gradRenderer);
renderWindow->SetSize(640, 320);
renderWindow->Render();
renderWindow->SetWindowName("ImageGradientExample");
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
vtkSmartPointer<vtkInteractorStyleImage> style =
vtkSmartPointer<vtkInteractorStyleImage>::New();
renderWindowInteractor->SetInteractorStyle(style);
renderWindowInteractor->SetRenderWindow(renderWindow);
renderWindowInteractor->Initialize();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
#endif