您现在的位置是:首页 >技术交流 >opencv_c++学习(十七)网站首页技术交流
opencv_c++学习(十七)
一、边缘检测
左侧上面的曲线表示的是像素从左到右的变化,下面的曲线是上面曲线求导而得。
Sobel边缘检测算子:
Sobel(InputArray src, outputArray dst,int ddepth, int dx, int dy,
int ksize = 3, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT)
src:输入图像。
dst:输出图像,与输入图像具有相同的尺寸和通道数。
ddepth:输出图像的数据类型(深度),根据输入图像的数据类型不同拥有不同的取值范围(这里不推荐8U, 建议使用16S)。
dx:求导次数。
dy:求导次数。
ksize:算子尺寸大小。
scale:缩放系数,通过系数来调节梯度的大小。
delta:偏移量。
在Sobel边缘检测过程中,通常采用先行后列的边缘检测方式。
Schar边缘检测算子:
Scharr(lnputArray src, OutputArray dst,int ddepth, int dx, int dy, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT)
与Sobel算子不同,Schar算子的边缘提取相应更强,其余与Sobel相同。
生成边缘检测算子:
getDerivKernels(OutputArray kx, OutputArray ky, int dx, int dy, int ksize, normalize =, bool false, int ktype = cV_32F)
kx:行滤波器系数的输出矩阵,尺寸为ksize1。
ky:列滤波器系数的输出矩阵,尺寸为ksize1。
dx: X方向导数的阶次。
dy: Y方向导数的阶次。
ksize:滤波器的大小,可以选择的参数为FILTER_SCHARR,1,3,5或7。
normalize:是否对滤波器系数进行归一化的标志,默认值为false,表示不进行系数归一化。
ktype:滤波器系数类型,可以选择CV_32F或CV_64F,默认参数为CV_32F。
检测算子的应用案例:
int main() {
//读取图片
Mat src = imread("1.png", IMREAD_ANYCOLOR);
if (src.empty())
{
printf("不能打开空图片");
return -1;
}
Mat result_X, result_Y, result_XY;
//Sobel边缘检测的测试
//X方向的一阶段边缘检测,这个算子最小的核大小为3,当设置为1时会自动调整为3
Sobel(src, result_X, CV_16S, 1, 0, 1);
//从边缘检测算子我们可以看出,边缘检测算子求取数值可能为负值,因此我们需要求取其绝对值
convertScaleAbs(result_X, result_X);
//Y方向的一阶段边缘检测
Sobel(src, result_Y, CV_16S, 0, 1, 3);
convertScaleAbs(result_Y, result_Y);
//整合两个阶段的图像
result_XY = result_X + result_Y;
imshow("边缘检测", result_XY);
//Scalar边缘检测的测试
//X方向的一阶段边缘检测,这个算子最小的核大小为3,当设置为1时会自动调整为3
Scharr(src, result_X, CV_16S, 1, 0);
//从边缘检测算子我们可以看出,边缘检测算子求取数值可能为负值,因此我们需要求取其绝对值
convertScaleAbs(result_X, result_X);
//Y方向的一阶段边缘检测
Scharr(src, result_Y, CV_16S, 0, 1);
convertScaleAbs(result_Y, result_Y);
//整合两个阶段的图像
result_XY = result_X + result_Y;
imshow("边缘检测1", result_XY);
waitKey(0);
return 0;
}
Laplacian算子:
前面介绍边缘检测算法存在的问题:
分别计算两个方向边缘;
边缘与方向相关性较大;
Laplacian(lnputArray src, outputArray dst,int ddepth, int ksize = 1, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT)
src:输入原图像,可以是灰度图像和彩色图像。
dst:输出图像,与输入图像src具有相同的尺寸和通道数。
ddepth:输出图像的数据类型(深度),根据输入图像的数据类型不同拥有不同的取值范围。
ksize:滤波器的大小,必须为正奇数。
scale:对导数计算结果进行缩放的缩放因子,默认系数为1,不进行缩放。delta:偏值,在计算结果中加上偏值。
borderType:像素外推法选择标志。
Canny算子:
Canny(lnputArray image, OutputArray edges,double threshold1, double threshold2, int apertureSize = 3, bool L2gradient = false
image:输入图像,必须是CV_8U单通道或者三通道图像。
edges:输出图像,与输入图像具有相同尺寸的单通道图像,且数据类型为CV_8U。
threshold1:第一个滞后阈值。
threshold2:第二个滞后阈值。
apertureSize: Sobel算子的直径。
L2gradient:计算图像梯度幅值的标志。
两种边缘检测算子的案例:
int main() {
//读取图片
Mat src = imread("1.png", IMREAD_ANYCOLOR);
if (src.empty())
{
printf("不能打开空图片");
return -1;
}
Mat result, result_g, result_G;
//不滤波提取边缘
Laplacian(src, result, CV_16S, 3, 1, 0);
//取绝对值
convertScaleAbs(result, result);
//先滤波,再提取边缘
GaussianBlur(src, result_g, Size(3, 3), 5, 0);
Laplacian(result_g, result_G, CV_16S, 3, 1, 0);
convertScaleAbs(result_G, result_G);
imshow("result", result);
imshow("result_G", result_G);
Mat resultHigh, result_low, resultG;
//大阈值图像边缘检测
Canny(src, resultHigh, 100, 200, 3);
//小阈值图像边缘检测
Canny(src, result_low, 20,40, 3);
//先滤波,再提取边缘
GaussianBlur(src, result_g, Size(3, 3), 5, 0);
Canny(src, resultG, 100, 200, 3);
imshow("result", resultHigh);
imshow("result_low", result_low);
imshow("resultG", resultG);
waitKey(0);
return 0;
}