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



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

VTK 边缘检测_Sobel算子_强制类型转换

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

1 #include <vtkAutoInit.h>
2 VTK_MODULE_INIT(vtkRenderingOpenGL);
3
4 #include <vtkSmartPointer.h>
5 #include <vtkJPEGReader.h>
6 #include <vtkImageSobel2D.h>
7 #include <vtkImageExtractComponents.h>
8 #include <vtkImageMathematics.h>
9 #include <vtkImageData.h>
10 #include <vtkImageShiftScale.h>
11 #include <vtkImageActor.h>
12 #include <vtkRenderer.h>
13 #include <vtkRenderWindow.h>
14 #include <vtkRenderWindowInteractor.h>
15 #include <vtkInteractorStyleImage.h>
16
17 int main()
18 {
19 vtkSmartPointer<vtkJPEGReader> reader =
20 vtkSmartPointer<vtkJPEGReader>::New();
21 reader->SetFileName("lena.jpg");
22 reader->Update();
23
24 vtkSmartPointer<vtkImageSobel2D> sobelFilter =
25 vtkSmartPointer<vtkImageSobel2D>::New();
26 sobelFilter->SetInputConnection(reader->GetOutputPort());//包含横向和竖向边缘
27
28 //提取X向边缘成分
29 vtkSmartPointer<vtkImageExtractComponents> xSobel =
30 vtkSmartPointer<vtkImageExtractComponents>::New();
31 xSobel->SetComponents(0);//提取第一成分即X向梯度
32 xSobel->SetInputConnection(sobelFilter->GetOutputPort());
33 xSobel->Update();
34
35 vtkSmartPointer<vtkImageMathematics> absFilter =
36 vtkSmartPointer<vtkImageMathematics>::New();
37 absFilter->SetOperationToAbsoluteValue();//将属性设置为绝对值模式
38 absFilter->SetInputConnection(xSobel->GetOutputPort());
39 absFilter->Update();
40
41 double xRange[2];
42 absFilter->GetOutput()->GetScalarRange(xRange);
43
44 vtkSmartPointer<vtkImageShiftScale> xShiftScale =
45 vtkSmartPointer<vtkImageShiftScale>::New();
46 xShiftScale->SetOutputScalarTypeToUnsignedChar();//强制类型转换 方便显示
47 xShiftScale->SetScale(255 / xRange[1]);//设置属性
48 xShiftScale->SetInputConnection(absFilter->GetOutputPort());
49 xShiftScale->Update();
50
51 //提取Y向边缘成分
52 vtkSmartPointer<vtkImageExtractComponents> ySobel =
53 vtkSmartPointer<vtkImageExtractComponents>::New();
54 ySobel->SetComponents(1);
55 ySobel->SetInputConnection(sobelFilter->GetOutputPort());
56 ySobel->Update();
57
58 vtkSmartPointer<vtkImageMathematics> absYsobel =
59 vtkSmartPointer<vtkImageMathematics>::New();
60 absYsobel->SetOperationToAbsoluteValue();
61 absYsobel->SetInputConnection(ySobel->GetOutputPort());
62 absYsobel->Update();
63
64 double yRange[2];
65 absYsobel->GetOutput()->GetScalarRange(yRange);
66
67 vtkSmartPointer<vtkImageShiftScale> yShiftScale =
68 vtkSmartPointer<vtkImageShiftScale>::New();
69 yShiftScale->SetOutputScalarTypeToUnsignedChar();
70 yShiftScale->SetScale(255 / yRange[1]);
71 yShiftScale->SetInputConnection(absYsobel->GetOutputPort());
72 yShiftScale->Update();
73
74 vtkSmartPointer<vtkImageActor> origActor =
75 vtkSmartPointer<vtkImageActor>::New();
76 origActor->SetInputData(reader->GetOutput());
77
78 vtkSmartPointer<vtkImageActor> xSobelActor =
79 vtkSmartPointer<vtkImageActor>::New();
80 xSobelActor->SetInputData(xShiftScale->GetOutput());
81
82 vtkSmartPointer<vtkImageActor> ySobelActor =
83 vtkSmartPointer<vtkImageActor>::New();
84 ySobelActor->SetInputData(yShiftScale->GetOutput());
85 /
86 double origView[4] = { 0, 0, 0.33, 1 };
87 double xSobelView[4] = { 0.33, 0, 0.66, 1 };
88 double ySobelView[4] = { 0.66, 0, 1, 1 };
89 vtkSmartPointer<vtkRenderer> origRender =
90 vtkSmartPointer<vtkRenderer>::New();
91 origRender->SetViewport(origView);
92 origRender->AddActor(origActor);
93 origRender->ResetCamera();
94 origRender->SetBackground(1, 0, 0);
95
96 vtkSmartPointer<vtkRenderer> xSobelRender =
97 vtkSmartPointer<vtkRenderer>::New();
98 xSobelRender->SetViewport(xSobelView);
99 xSobelRender->AddActor(xSobelActor);
100 xSobelRender->ResetCamera();
101 xSobelRender->SetBackground(0, 1, 0);
102
103 vtkSmartPointer<vtkRenderer> ySobelRender =
104 vtkSmartPointer<vtkRenderer>::New();
105 ySobelRender->SetViewport(ySobelView);
106 ySobelRender->AddActor(ySobelActor);
107 ySobelRender->ResetCamera();
108 ySobelRender->SetBackground(0, 0, 1);
109 //
110 vtkSmartPointer<vtkRenderWindow> rw =
111 vtkSmartPointer<vtkRenderWindow>::New();
112 rw->AddRenderer(origRender);
113 rw->AddRenderer(xSobelRender);
114 rw->AddRenderer(ySobelRender);
115 rw->SetSize(960, 320);
116 rw->SetWindowName("Edge by Soebl");
117
118 vtkSmartPointer<vtkRenderWindowInteractor> rwi =
119 vtkSmartPointer<vtkRenderWindowInteractor>::New();
120 vtkSmartPointer<vtkInteractorStyleImage> style =
121 vtkSmartPointer<vtkInteractorStyleImage>::New();
122 rwi->SetInteractorStyle(style);
123 rwi->SetRenderWindow(rw);
124 rwi->Initialize();
125 rwi->Start();
126
127 return 0;
128 }

该例中计算利用Sobel算子计算图像的梯度图像,然后提取X方向的梯度分量和Y方向的梯度分量。

由于计算Sobel算子的值可能存在负值,因此利用vtkImageMathematics对各个分量图像计算绝对值,再由vtkImageShiftScale将图像的数值范围调节到0-255之间再显示。

执行结果如下:

VTK 边缘检测_Sobel算子_属性设置_02