1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
//--------------------------------【头文件、命名空间包含部分】----------------------------
// 描述:包含程序所使用的头文件和命名空间
//-------------------------------------------------------------------------------------
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
//--------------------------------【全局变量声明部分】-----------------------------------
// 描述:全局变量声明
//-------------------------------------------------------------------------------------
//原图,原图的灰度版,目标图
Mat g_srcImage, g_srcGrayImage,g_dstImage;
//Canny边缘检测相关变量
Mat g_cannyDetectedEdges;
int g_cannyLowThreshold=1;//TrackBar位置参数
//Sobel边缘检测相关变量
Mat g_sobelGradient_X, g_sobelGradient_Y;
Mat g_sobelAbsGradient_X, g_sobelAbsGradient_Y;
int g_sobelKernelSize=1;//TrackBar位置参数
//Scharr滤波器相关变量
Mat g_scharrGradient_X, g_scharrGradient_Y;
Mat g_scharrAbsGradient_X, g_scharrAbsGradient_Y;
//--------------------------------【全局函数声明部分】-----------------------------------
// 描述:全局函数声明
//-------------------------------------------------------------------------------------
static void ShowHelpText( );
static void on_Canny(int, void*);//Canny边缘检测窗口滚动条的回调函数
static void on_Sobel(int, void*);//Sobel边缘检测窗口滚动条的回调函数
void Scharr( );//封装了Scharr边缘检测相关代码的函数
//-------------------------------【main( )函数】-----------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始
//-------------------------------------------------------------------------------------
int main( int argc, char** argv )
{
//改变console字体颜色
system("color 2F");
//显示欢迎语
ShowHelpText();
//载入原图
g_srcImage = imread("1.jpg");
if( !g_srcImage.data ) { printf("Oh,no,读取srcImage错误~! \n"); return false; }
//显示原始图
namedWindow("【原始图】");
imshow("【原始图】", g_srcImage);
// 创建与src同类型和大小的矩阵(dst)
g_dstImage.create( g_srcImage.size(), g_srcImage.type() );
// 将原图像转换为灰度图像
cvtColor( g_srcImage, g_srcGrayImage, COLOR_BGR2GRAY );
// 创建显示窗口
namedWindow( "【效果图】Canny边缘检测", WINDOW_AUTOSIZE );
namedWindow( "【效果图】Sobel边缘检测", WINDOW_AUTOSIZE );
// 创建trackbar
createTrackbar( "参数值:", "【效果图】Canny边缘检测", &g_cannyLowThreshold, 120, on_Canny );
createTrackbar( "参数值:", "【效果图】Sobel边缘检测", &g_sobelKernelSize, 3, on_Sobel );
// 调用回调函数
on_Canny(0, 0);
on_Sobel(0, 0);
//调用封装了Scharr边缘检测代码的函数
Scharr( );
//轮询获取按键信息,若按下Q,程序退出
while((char(waitKey(1)) != 'q')) {}
return 0;
}
//--------------------------------【ShowHelpText( )函数】--------------------------------
// 描述:输出一些帮助信息
//-------------------------------------------------------------------------------------
static void ShowHelpText()
{
//输出欢迎信息和OpenCV版本
printf("\n\n\t\t\t非常感谢购买《OpenCV3编程入门》一书!\n");
printf("\n\n\t\t\t此为本书OpenCV3版的第60个配套示例程序\n");
printf("\n\n\t\t\t 当前使用的OpenCV版本为:" CV_VERSION );
printf("\n\n ----------------------------------------------------------------------------\n");
//输出一些帮助信息
printf( "\n\n\t运行成功,请调整滚动条观察图像效果~\n\n"
"\t按下“q”键时,程序退出。\n");
}
//----------------------------------【on_Canny( )函数】----------------------------------
// 描述:Canny边缘检测窗口滚动条的回调函数
//-------------------------------------------------------------------------------------
void on_Canny(int, void*)
{
// 先使用 3x3内核来降噪
blur( g_srcGrayImage, g_cannyDetectedEdges, Size(3,3) );
// 运行我们的Canny算子
//void cvCanny(
// const CvArr* image, //第一个参数表示输入图像,必须为单通道灰度图
// CvArr* edges, //第二个参数表示输出的边缘图像,为单通道黑白图
// double threshold1,
// double threshold2, //第三个参数和第四个参数表示阈值,这二个阈值中当中的小阈值用来控制边缘连接,
// 大的阈值用来控制强边缘的初始分割即如果一个像素的梯度大与上限值,则被认为
// 是边缘像素,如果小于下限阈值,则被抛弃。如果该点的梯度在两者之间则当这个
// 点与高于上限值的像素点连接时我们才保留,否则删除。
// int aperture_size = 3 //第五个参数表示Sobel 算子大小,默认为3即表示一个3*3的矩阵。Sobel 算子与
// 高斯拉普拉斯算子都是常用的边缘算子
// );
Canny( g_cannyDetectedEdges, g_cannyDetectedEdges, g_cannyLowThreshold, g_cannyLowThreshold*3, 3 );
//先将g_dstImage内的所有元素设置为0
g_dstImage = Scalar::all(0);
//使用Canny算子输出的边缘图g_cannyDetectedEdges作为掩码,来将原图g_srcImage拷到目标图g_dstImage中
g_srcImage.copyTo( g_dstImage, g_cannyDetectedEdges);
//显示效果图
imshow( "【效果图】Canny边缘检测", g_dstImage );
imshow( "g_cannyDetectedEdges", g_cannyDetectedEdges);
}
//----------------------------------【on_Sobel( )函数】----------------------------------
// 描述:Sobel边缘检测窗口滚动条的回调函数
//-------------------------------------------------------------------------------------
void on_Sobel(int, void*)
{
// 求 X方向梯度
//void Sobel(InputArray src, OutputArray dst, int ddepth,
// int dx, int dy, int ksize = 3,
//第四个参数,int类型dx,x 方向上的差分阶数。
//第五个参数,int类型dy,y方向上的差分阶数。
Sobel( g_srcImage, g_sobelGradient_X, CV_16S, 1, 0, (2*g_sobelKernelSize+1));
convertScaleAbs( g_sobelGradient_X, g_sobelAbsGradient_X );//计算绝对值,并将结果转换成8位
//显示效果图
imshow("【效果图】Sobel边缘检测x", g_sobelAbsGradient_X);
// 求Y方向梯度
Sobel( g_srcImage, g_sobelGradient_Y, CV_16S, 0, 1, (2*g_sobelKernelSize+1));
convertScaleAbs( g_sobelGradient_Y, g_sobelAbsGradient_Y );//计算绝对值,并将结果转换成8位
imshow("【效果图】Sobel边缘检测y", g_sobelAbsGradient_Y);
// 合并梯度
//void addWeighted(InputArray src1, double alpha, InputArray src2,
// double beta, double gamma, OutputArray dst, int dtype = -1);
//dst = src1*alpha + src2*beta + gamma;
addWeighted( g_sobelAbsGradient_X, 0.5, g_sobelAbsGradient_Y, 0.5, 0, g_dstImage );
//显示效果图
imshow("【效果图】Sobel边缘检测", g_dstImage);
}
//-----------------------------------【Scharr( )函数】----------------------------------
// 描述:封装了Scharr边缘检测相关代码的函数
//-------------------------------------------------------------------------------------
void Scharr( )
{
// 求 X方向梯度
Scharr( g_srcImage, g_scharrGradient_X, CV_16S, 1, 0);
//void convertScaleAbs(InputArray src, OutputArray dst,
// double alpha = 1, double beta = 0);
//先缩放元素再取绝对值,最后转换格式为8bit型
convertScaleAbs( g_scharrGradient_X, g_scharrAbsGradient_X );//计算绝对值,并将结果转换成8位
//显示效果图
imshow("【效果图】Scharr滤波器x", g_scharrAbsGradient_X);
// 求Y方向梯度
Scharr( g_srcImage, g_scharrGradient_Y, CV_16S, 0, 1);
convertScaleAbs( g_scharrGradient_Y, g_scharrAbsGradient_Y );//计算绝对值,并将结果转换成8位
imshow("【效果图】Scharr滤波器y", g_scharrAbsGradient_Y);
// 合并梯度
addWeighted( g_scharrAbsGradient_X, 0.5, g_scharrAbsGradient_Y, 0.5, 0, g_dstImage );
//显示效果图
imshow("【效果图】Scharr滤波器", g_dstImage);
}
|