您现在的位置是:首页 >技术交流 >opencv_c++学习(十七)网站首页技术交流

opencv_c++学习(十七)

小小小~ 2024-06-17 11:28:21
简介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:列滤波器系数的输出矩阵,尺寸为ksize
1。
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;
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。