VTK——Canny算子

边缘检测算法——Canny算子
Canny算子是John Canny在20世纪80年代提出的一种多级边缘检测算法。John Canny研究了最优边缘的特性,即检测到的边缘要尽可能跟实际的边缘并尽可能的多。同时,要尽量减低噪声对边缘检测的干扰。计算步骤如下:
①.对原图像进行高斯平滑一消除图像中的噪声
②.采用查差分法近似计算图像每一个像素的梯度,并计算梯度的模值和风向
③.对梯度进行“非极大抑制”:图像边缘点梯度值通常在梯度方向是极大值,因此检测边缘需要将非极大值赋值0来抑制非边缘点。检测方法就是在一个局部窗口内,如果中心像素点的梯度不比梯度方向上相邻的两个像素值大,那么该中心像素点梯度值为0.
④.双阈值法检测边缘和连接边缘。取两个梯度阈值high和low,将梯度图像像素赋值为0得到边缘图像l1,该图像能够接近图像边缘但是可能会存在间断点;将梯度图像中小于low的像素赋值为0得到边缘图像l2,该图像中噪声干扰比较大,但是边缘信息更多。在连接边缘是时,以l1为基础,对零点进行边缘跟踪,如果跟踪过程中出现中断,则,从l2对应像素点及其邻域来寻找可以连接的边缘,直至结束。
在VTK中没有实现一个专门的类来做边缘Canny边缘检测。
实现代码`#include “Test.h”
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);

#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkImageShiftScale.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkRenderer.h>
#include <vtkImageActor.h>
#include <vtkJPEGReader.h>
#include <vtkImageCast.h>
#include <vtkImageGaussianSmooth.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 <vtkCamera.h>
#include <vtkProperty.h>
#include <vtkStripper.h>
#include <vtkPolyDataMapper.h>

int main(int argc, char* argv[])
{
//首先读入图片
vtkSmartPointer reader =
vtkSmartPointer::New();
reader->SetFileName(“data/Lena.jpg”);
reader->Update();

//图片类型转换
vtkSmartPointer<vtkImageCast> ic =
	vtkSmartPointer<vtkImageCast>::New();
ic->SetOutputScalarTypeToFloat();
ic->SetInputConnection(reader->GetOutputPort());
ic->Update();

//高斯算法实现图片平滑
vtkSmartPointer<vtkImageGaussianSmooth> gs =
	vtkSmartPointer<vtkImageGaussianSmooth>::New();
gs->SetInputData(ic->GetOutput());
gs->SetDimensionality(2);
gs->SetRadiusFactors(1, 1, 0);
gs->Update();

//计算图像的梯度和模值
vtkSmartPointer<vtkImageGradient> imgGradient =
	vtkSmartPointer<vtkImageGradient>::New();
imgGradient->SetInputData(gs->GetOutput());
imgGradient->SetDimensionality(2);
imgGradient->Update();


vtkSmartPointer<vtkImageMagnitude> imgMagnitude =
	vtkSmartPointer<vtkImageMagnitude>::New();
imgMagnitude->SetInputData(imgGradient->GetOutput());
imgMagnitude->Update();

//vtkImageNonMaximumSuppression将图片中的非局部峰值设置为0,输入和输出类型都是ImageData
//其中输入有两个,模型图像和向量图像,一个典型的应用就是输入梯度模值图像梯度图像对梯度做非极大值抑制
vtkSmartPointer<vtkImageNonMaximumSuppression> nonMax =
	vtkSmartPointer<vtkImageNonMaximumSuppression>::New();
nonMax->SetMagnitudeInputData(imgMagnitude->GetOutput());
nonMax->SetVectorInputData(imgGradient->GetOutput());
nonMax->SetDimensionality(2);
nonMax->Update();



//vtkImageConstantPad增加图像的大小,其输入好人输出都为VTKImageData。其中函数SetOutputNumberOfS阿炒腊肉Component是(3)用于设置输出图像的像素数据分个
//数,函数SetConstant(0)用于设置图像中扩大的区域像素值。而SetOutputWholeExtent()则用于设置输出图像的范围。这里的作用是将梯度图像像素的组分修改为3,方便下面vtkImageToStructuredPoints使用。
vtkSmartPointer<vtkImageConstantPad> pad =
	vtkSmartPointer<vtkImageConstantPad>::New();
pad->SetInputConnection(imgGradient->GetOutputPort());
pad->SetOutputNumberOfScalarComponents(3);
pad->SetConstant(0);
pad->Update();

//vtkImageToStructuredPoints将VTKImageData格式转换为规则点集。该类的输入类型VTKImageData,
//另外还有一个人可选的RGB三组分向量图像输入;输入类型是VTKStructuredData类型,导航输入向量图像时,向量图像像素数据回转为输入图像的对应点

vtkSmartPointer<vtkImageToStructuredPoints> i2sp1 =
	vtkSmartPointer<vtkImageToStructuredPoints>::New();
i2sp1->SetInputData(nonMax->GetOutput());
i2sp1->SetVectorInputData(pad->GetOutput());
i2sp1->Update();


//vtkLinkEdgels类根据点的相邻关系连接成连续的折线Polyline。其内部阈值变量GradientThreshold,
//可以用来排除输入点中梯度值小于该阈值的点。当使用vtkLinkEdgels进行Canny算子的双阈值边缘检测时,GradientThreshold可以用作较小的阈值。设置该阈值的函数是SetGradientThreshold(2)。

vtkSmartPointer<vtkLinkEdgels> imgLink =
	vtkSmartPointer<vtkLinkEdgels>::New();
imgLink->SetInputData(i2sp1->GetOutput());
imgLink->SetGradientThreshold(2);
imgLink->Update();


vtkSmartPointer<vtkThreshold> thresholdEdgels =
	vtkSmartPointer<vtkThreshold>::New();
thresholdEdgels->SetInputData(imgLink->GetOutput());
thresholdEdgels->ThresholdByUpper(10);
thresholdEdgels->AllScalarsOff();
thresholdEdgels->Update();


vtkSmartPointer<vtkGeometryFilter> gf =
	vtkSmartPointer<vtkGeometryFilter>::New();
gf->SetInputConnection(thresholdEdgels->GetOutputPort());
//gf->Update();//


vtkSmartPointer<vtkImageToStructuredPoints> i2sp =
	vtkSmartPointer<vtkImageToStructuredPoints>::New();
i2sp->SetInputData(imgMagnitude->GetOutput());
i2sp->SetVectorInputData(pad->GetOutput());
i2sp->Update();


vtkSmartPointer<vtkSubPixelPositionEdgels> spe =
	vtkSmartPointer<vtkSubPixelPositionEdgels>::New();
spe->SetInputConnection(gf->GetOutputPort());
spe->SetGradMapsData(i2sp->GetStructuredPointsOutput());
//spe->Update();//


vtkSmartPointer<vtkStripper> strip =
	vtkSmartPointer<vtkStripper>::New();
strip->SetInputConnection(spe->GetOutputPort());
//strip->Update();//


vtkSmartPointer<vtkPolyDataMapper> dsm =
	vtkSmartPointer<vtkPolyDataMapper>::New();
dsm->SetInputConnection(strip->GetOutputPort());
dsm->ScalarVisibilityOff();
//dsm->Update();//


vtkSmartPointer<vtkActor> planeActor =
	vtkSmartPointer<vtkActor>::New();
planeActor->SetMapper(dsm);
planeActor->GetProperty()->SetAmbient(1.0);
planeActor->GetProperty()->SetDiffuse(0.0);
planeActor->GetProperty()->SetColor(1.0, 0.0, 0.0);


vtkSmartPointer<vtkImageActor> originalActor =
	vtkSmartPointer<vtkImageActor>::New();
originalActor->SetInputData(reader->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(planeActor);
gradRenderer->ResetCamera();
gradRenderer->SetBackground(1.0, 1.0, 1.0);


vtkSmartPointer<vtkRenderWindow> renderWindow =
	vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->SetSize(900, 300);
renderWindow->AddRenderer(originalRenderer);
renderWindow->AddRenderer(gradRenderer);
renderWindow->Render();
renderWindow->SetWindowName("CannyExample");


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;

}`

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: vtk是一种图形库,用于可视化数据。在vtk中,“点”、“线”和“面”是常见的几何元素。下面是关于这些元素的一些示例: 1. 点(Point):点是空间中具有坐标位置的最基本的几何元素。在vtk中,我们可以创建一个或多个点,并指定它们的坐标。例如,我们可以创建一个点的集合,表示星空中的一些恒星的位置。每个点都有自己的坐标,可以在三维空间中进行可视化。 2. 线(Line):线是由两个或更多个连接起来的点组成的几何形状。在vtk中,我们可以使用点的坐标来创建一条直线。例如,我们可以创建一个由两个点组成的线,表示一条直线段的路径。这条直线可以用来表示一条河流的流程,或者是一辆车在道路上行驶的路径。 3. 面(Surface):面是由三个或更多个连接起来的点和线组成的几何形状。在vtk中,我们可以使用点的坐标和线的连接关系来创建一个面。例如,我们可以创建一个三角形的面,通过指定三个点的坐标来定义。这个三角形可以用来表示一个地面的形状,或者是一个房屋的屋顶的形状。 总之,vtk提供了一种便捷的方式来创建和可视化各种几何元素,包括点、线和面。通过使用vtk,我们可以将这些几何元素在三维空间中进行可视化,并用于表示和展示各种数据的形状和结构。 ### 回答2: VTK(Visualization Toolkit)是一个强大的图形可视化库,它提供了丰富的功能和工具,可以用于创建各种类型的图形对象和可视化效果。在VTK中,可以使用点、线和面作为基本的图形元素。 在VTK中,点是最简单的图形元素之一。它可以用于表示空间中的一个坐标点,具有位置属性。例如,我们可以使用VTK创建一个点的可视化效果,通过设置其位置和颜色来定义点的属性,从而实现对点的可视化表达。 线是由多个点连接而成的线段。在VTK中,可以使用一系列的点来创建一条线,并通过设置线的属性,如线宽、颜色、透明度等来实现线的可视化效果。例如,我们可以通过VTK创建一个由多个点组成的路径,用来表示动态的物体运动轨迹。 面是由多条连续的线组成的封闭区域。在VTK中,可以使用一系列的坐标点来定义一个封闭的多边形,并通过设置面的属性,如颜色、透明度、纹理等来实现面的可视化效果。例如,我们可以使用VTK创建一个立方体的可视化效果,通过定义六个面和对应的坐标点来表示立方体的各个面。 总结起来,VTK中的点、线和面都是用于表示图形对象的基本元素,可以通过设置它们的属性来实现各种形式的可视化效果。无论是单独使用还是组合使用,这些元素都为图形的创建和可视化提供了灵活和多样的选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

简 。单

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值