读书笔记之sobel 滤波器

本文详细介绍了Sobel算子的工作原理及其在图像边缘检测中的应用。通过两个3*3的线性滤波器,Sobel算子能够计算图像在水平和垂直方向上的梯度,从而有效地检测出图像的边缘。文章还提供了使用OpenCV实现Sobel算子的代码示例,并展示了如何通过梯度幅值的阈值化得到二值边缘分布图。

Sobel算子是一种典型的用于边缘检测的线性滤波器,它基于两个简单的3*3内核,内核结构如下图所示

水平方向:

-101
-202
-101

垂直方向:

-1-2-1
000
121

 

如果把图像看做二维函数,那么sobel算子就是图像在水平和垂直方向变化的速度。在数学属于中,这种速度称为梯度。它是一个二维向量,向量的元素是横竖两个方向的函数的一阶导数:

grad(I)=\left [ \frac{\partial I}{\partial x} , \frac{\partial I}{\partial y}\right ]^{T}

sobel算子在水平和垂直方向计算像素值的差分,得到图像梯度的近似值。它在像素周围的一定范围内进行运算,以减少噪声带来的影响。

使用水平方向和垂直方向滤波器检测边缘:

#include <iostream>
#include <iomanip>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
//#include "laplacianZC.h"

int main()
{
	// Read input image
	cv::Mat image = cv::imread("E:\\OpenCV\\OpenCV3源码\\images\\boldt.jpg", 0);
	if (!image.data)
		return 0;

	// Display the image
	cv::namedWindow("Original Image");
	cv::imshow("Original Image", image);

	// Compute Sobel X derivative
	cv::Mat sobelX;
	cv::Sobel(image,  // input
		sobelX,    // output
		CV_8U,     // image type
		1, 0,      // kernel specification
		3,         // size of the square kernel 
		0.4, 128); // scale and offset(偏移量)

				   // Display the image
	cv::namedWindow("Sobel X Image");
	cv::imshow("Sobel X Image", sobelX);

	// Compute Sobel Y derivative
	cv::Mat sobelY;
	cv::Sobel(image,  // input
		sobelY,    // output
		CV_8U,     // image type
		0, 1,      // kernel specification
		3,         // size of the square kernel 
		0.4, 128); // scale and offset

				   // Display the image
	cv::namedWindow("Sobel Y Image");
	cv::imshow("Sobel Y Image", sobelY);

因为梯度是一个二维向量,所以它有范数和方向。梯度向量的范数表示变化的振幅,计算时通常被当做欧几里得范数(也成L2范数):

\left | grad(I) \right |=^{\sqrt{(\frac{\partial I}{\partial x})^{2}+(\frac{\partial I}{\partial y})^{2}}}

但是在图像处理领域,通常把绝对值之和作为范数进行计算。这称为L1范数。

梯度向量总是指向变化最剧烈的方向。对于一幅图像来说,这意味着梯度方向与边缘垂直,从较暗区域指向较亮区域。梯度的角度用下面的公式计算:

∠grade(I)=arctan(-\frac{\partial I}{\partial y}/\frac{\partial I}{\partial x})

使用L1范数边缘检测:

	// Compute norm of Sobel
	cv::Sobel(image, sobelX, CV_16S, 1, 0);
	cv::Sobel(image, sobelY, CV_16S, 0, 1);
	cv::Mat sobel;
	//compute the L1 norm
	sobel = abs(sobelX) + abs(sobelY);

	double sobmin, sobmax;
	cv::minMaxLoc(sobel, &sobmin, &sobmax);
	std::cout << "sobel value range: " << sobmin << "  " << sobmax << std::endl;

	// Compute Sobel X derivative (7x7)
	cv::Sobel(image, sobelX, CV_8U, 1, 0, 7, 0.001, 128);

	// Display the image
	cv::namedWindow("Sobel X Image (7x7)");
	cv::imshow("Sobel X Image (7x7)", sobelX);

	// Print window pixel values
	for (int i = 0; i<12; i++) {
		for (int j = 0; j<12; j++)
			std::cout << std::setw(5) << static_cast<int>(sobel.at<short>(i + 79, j + 215)) << " ";
		std::cout << std::endl;
	}
	std::cout << std::endl;
	std::cout << std::endl;
	std::cout << std::endl;

	// Conversion to 8-bit image
	// sobelImage = -alpha*sobel + 255
	cv::Mat sobelImage;
	sobel.convertTo(sobelImage, CV_8U, -255. / sobmax, 255);

	// Display the image
	cv::namedWindow("Sobel Image");
	cv::imshow("Sobel Image", sobelImage);

threshold()函数用法:https://blog.youkuaiyun.com/u012566751/article/details/77046445

对梯度幅值进行阈值化,可得到一个二值边缘分布图。

// Apply threshold to Sobel norm (low threshold value)
	cv::Mat sobelThresholded;
	cv::threshold(sobelImage, sobelThresholded, 225, 255, cv::THRESH_BINARY);

	// Display the image
	cv::namedWindow("Binary Sobel Image (low)");
	cv::imshow("Binary Sobel Image (low)", sobelThresholded);

	// Apply threshold to Sobel norm (high threshold value)
	cv::threshold(sobelImage, sobelThresholded, 190, 255, cv::THRESH_BINARY);

	// Display the image
	cv::namedWindow("Binary Sobel Image (high)");
	cv::imshow("Binary Sobel Image (high)", sobelThresholded);

 

### Sobel滤波器的工作原理 Sobel滤波器是一种基于一阶导数的离散差分算子,用于计算图像中的水平和垂直方向上的梯度。这种梯度信息可以用来检测图像中的边缘位置[^2]。 #### 数学基础 Sobel算子的核心在于利用两个3×3大小的卷积核分别对输入图像进行水平和垂直方向上的卷积运算。这两个卷积核定义如下: 对于水平方向(Gx): ```plaintext [-1, 0, 1] [-2, 0, 2] [-1, 0, 1] ``` 对于垂直方向(Gy): ```plaintext [-1, -2, -1] [ 0, 0, 0] [ 1, 2, 1] ``` 通过对原始图像应用上述卷积核,可以获得每个像素点处沿X轴和Y轴的方向梯度值。最终的梯度幅值可通过以下公式计算得出: \[ G = \sqrt{G_x^2 + G_y^2} \] 为了简化计算过程,在实际应用中通常采用近似方式替代平方根操作: \[ G = |G_x| + |G_y| \] #### 实现方法 以下是使用Python结合OpenCV库实现Sobel滤波器的一个简单例子: ```python import cv2 import numpy as np from matplotlib import pyplot as plt # 加载并转换为灰度图像 image = cv2.imread('example.jpg', 0) # 应用Sobel算子 sobelx = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=3) # X方向梯度 sobely = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=3) # Y方向梯度 # 计算梯度幅度 gradient_magnitude = np.sqrt(sobelx**2 + sobely**2) gradient_magnitude = np.uint8(gradient_magnitude / gradient_magnitude.max() * 255) # 显示结果 plt.subplot(1, 3, 1), plt.imshow(image, cmap='gray') plt.title('Original'), plt.xticks([]), plt.yticks([]) plt.subplot(1, 3, 2), plt.imshow(gradient_magnitude, cmap='gray') plt.title('Gradient Magnitude'), plt.xticks([]), plt.yticks([]) plt.show() ``` 此代码片段展示了如何加载一幅图片、将其转化为灰度形式,并运用Sobel算子提取其中的边缘信息[^3]。 ### 预处理的重要性 在执行Sobel边缘检测前,往往需要先对图像做一定的预处理工作,比如降噪和平滑化处理。这是因为未经处理的原始数据可能含有较多随机噪声干扰,这些噪音会降低后续分析的质量。一种常见的做法就是先施加高斯模糊来减少高频成分的影响[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值