第18课 Soble算子——提取边缘

1. 卷积应用——图像边缘提取

  • 边缘是什么 – 是像素值发生跃迁的地方,是图像的显著特征之一,在图像特征提取、对象检测、模式识别等方面都有重要的作用。
  • 如何捕捉(提取边缘) —— 对图像求它的一阶导数
    delta = f(x) – f(x-1), delta越大,说明像素在X方向变化越大,边缘信号越强。
  • 用Sobel算子,卷积操作。
    在这里插入图片描述

2.Soble算子

  • Soble算子是离散微分算子(discrete differentiation operator),用来计算图像灰度的近似梯度
  • Soble算子功能集合高斯平滑和微分求导,又被称为一阶微分算子,求导算子,在水平和垂直两个方向上求导,得到图像X方向与Y方向梯度图像在这里插入图片描述
  • 求取导数的近似值,kernel=3时不是很准确,OpenCV使用改进版本Scharr函数,算子如下:
  • 在这里插入图片描述

3. 相关API

3.1 cv::Sobel ()

cv::Sobel (
InputArray Src // 输入图像
OutputArray dst// 输出图像,大小与输入图像一致
int depth // 输出图像深度. 
Int dx.  // X方向,几阶导数
int dy // Y方向,几阶导数. 
int ksize, SOBEL算子kernel大小,必须是1、3、5、7、
double scale  = 1//输出结果的倍数
double delta = 0//输出结果加上一个值
int borderType = BORDER_DEFAULT
)

在这里插入图片描述

  • 输出深度须大于或等于输入深度。
  • 以下为用cv::Sobel()输出的结果。其中dst1是用addWeighted()融合出来的结果,dst是采用各像素值相加融合出来的结果,符合公式。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

3.2 cv::Scharr()

  • 为cv::Sobel()的改进版,处理后的边缘更明显,用法与cv::Sobel()一致。
cv::Scharr (
InputArray Src // 输入图像
OutputArray dst// 输出图像,大小与输入图像一致
int depth // 输出图像深度. 
Int dx.  // X方向,几阶导数
int dy // Y方向,几阶导数. 
double scale  = 1
double delta = 0
int borderType = BORDER_DEFAULT
)
  • 以下为用cv::Scharr()输出的结果。其中dst1是用addWeighted()融合出来的结果,dst是采用各像素值相加融合出来的结果,符合公式。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

3.3 其他API

  • GaussianBlur( src, dst, Size(3,3), 0, 0, BORDER_DEFAULT );
  • cvtColor( src, gray, COLOR_RGB2GRAY );
  • addWeighted( A, 0.5,B, 0.5, 0, AB);
  • convertScaleAbs(A, B)// 计算图像A的像素绝对值,输出到图像B

在这里插入图片描述

4.边缘提取步骤

  1. 输入图像imread();
  2. 高斯模糊滤波GaussianBlur();
  3. 转化为灰度图像cvtColor();
  4. 分别提取水平和竖直边缘Sobel()或Scharr();
  5. 融合addWeighted()或各个像素值相加。

5.例程

#include<opencv2/opencv.hpp>
#include<iostream>

using namespace cv;

int main() {
	Mat src, dst;
	src = imread("D:/resource/images/face.jpg");

	if (src.empty()) {
		printf("The image could not be loaded....");
		return -1;
	}

	imshow("input image", src);



	Mat blur_image, gray_image, SobelX_image, SobelY_image;

	GaussianBlur(src, blur_image, Size(3, 3), 0);

	cvtColor(blur_image, gray_image, COLOR_BGR2GRAY);

	//Scharr(gray_image, SobelX_image, CV_16S, 1, 0);
	//Scharr(gray_image, SobelY_image, CV_16S, 0, 1);
	Sobel(gray_image, SobelX_image, CV_16S, 1, 0);
	Sobel(gray_image, SobelY_image, CV_16S, 0, 1);
	
	convertScaleAbs(SobelX_image, SobelX_image);
	convertScaleAbs(SobelY_image, SobelY_image);

	imshow("Sobel水平梯度", SobelX_image);
	imshow("Sobel竖直梯度", SobelY_image);

	Mat dst1;
	addWeighted(SobelX_image, 0.5, SobelY_image, 0.5, 0, dst1);
	imshow("dst1", dst1);

	dst = Mat(SobelX_image.size(), SobelX_image.type());
	std::cout << src.type();
	for (int row = 0; row < SobelY_image.rows; row++)
	{
		for (int col = 0; col < SobelX_image.cols; col++)
		{
			int xg = SobelX_image.at<uchar>(row, col);
			int yg = SobelY_image.at<uchar>(row, col);
			int xy = xg + yg;
			dst.at<uchar>(row, col) = saturate_cast<uchar>(xy);
		}
	}
	imshow("dst", dst);

	waitKey(0);
	return 0;

}
发布了31 篇原创文章 · 获赞 12 · 访问量 2771

猜你喜欢

转载自blog.csdn.net/weixin_42877426/article/details/104227963
今日推荐