我是靠谱客的博主 细腻舞蹈,最近开发中收集的这篇文章主要介绍OpenCV 边缘检测之Sobel算子Sobel算子(索贝尔算子)相关API代码案例,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

  • Sobel算子(索贝尔算子)
    • Sobel算子定义:
    • Sobel算子作用:
    • Sobel卷积因子
    • Sobel卷积计算公式:
  • 相关API
    • Sobel()
    • convertScaleAbs()
    • addWeighted()
  • 代码案例
    • 用API
    • 一大神自己写的

Sobel算子(索贝尔算子)

Sobel算子定义:

Sobel 算子是一个离散的一阶微分算子,用来计算图像灰度函数的近似梯度。

在空间域上Sobel算子很容易实现,执行速度快,对部分噪声具有平滑作用,还能够提供较为精确的边缘方向信息,缺点是边缘定位精度不够高。边缘是指一个物体与另一个物体的分界处,一般边缘内外处都会有灰度值上的差异,Sobel算子就是通过像素点空间邻域内上下,左右相邻点的灰度加权运算,求取物体边缘。

Sobel算子作用:

索贝尔算子是计算机视觉领域的一种重要处理方法。主要用于获得数字图像的一阶梯度,常见的应用和物理意义是边缘检测。索贝尔算子是把图像中每个像素的上下左右四领域的灰度值加权差,在边缘处达到极值从而检测边缘。

索贝尔算子主要用作边缘检测。在技术上,它是一离散性差分算子,用来运算图像亮度函数的梯度之近似值。在图像的任何一点使用此算子,将会产生对应的梯度矢量或是其法矢量。

索贝尔算子不但产生较好的检测效果,而且对噪声具有平滑抑制作用,但是得到的边缘较粗,且可能出现伪边缘。

Sobel卷积因子

经典Sobel的卷积因子为:
在这里插入图片描述

Sobel卷积计算公式:

对于待检测边缘的图像I,分别在水平(X)方向和垂直方向(Y)方向求导,方法是分别图像I与卷积核Gx和Gy进行卷积,公式表述如下:
在这里插入图片描述

图像的每一个像素的横向及纵向梯度近似值可用以下的公式结合,来计算梯度的大小(G即为Sobel求得的梯度图像)。
在这里插入图片描述
(或者用下面简单粗暴的方法计算G
在这里插入图片描述)
然后可用以下公式计算梯度方向。
在这里插入图片描述
在以上例子中,如果以上的角度θ等于零,即代表图像该处拥有纵向边缘,左方较右方暗。

相关API

Sobel()

函数功能:

  • 应用于图像边缘检测

函数原型:

dst = cv2.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]])

必选参数(前四个是必须的参数):

  1. src - 需要处理的图像
  2. ddepth - 图像的深度,-1表示采用的是与原图像相同的深度。目标图像的深度必须大于等于原图像的深度
  3. dx - 对x轴方向求导的阶数,一般为0、1、2,其中0表示这个方向上没有求导
  4. dy - 对y轴方向求导的阶数,一般为0、1、2,其中0表示这个方向上没有求导

其后是可选的参数:

  1. dst - 目标图像
  2. ksize - Sobel算子的大小,必须为1、3、5、7
  3. scale - 缩放导数的比例常数,默认情况下没有伸缩系数
  4. delta - 可选增量, 将会加到最终的dst中,同样,默认情况下没有额外的值加到dst中
  5. borderType - 图像边界的模式。这个参数默认值为cv2.BORDER_DEFAULT

说明:

在经过处理后,需要用convertScaleAbs()函数将其转回原来的uint8形式,否则将无法显示图像,而只是一副灰色的窗口。

convertScaleAbs()

函数功能:

  • 实现将原图片转换为uint8类型

函数原型:

dst = cv2.convertScaleAbs(src[, dst[, alpha[, beta]]])   

参数:

  • src - 源图像
  • dst - 输出图像

可选参数

  • alpha是伸缩系数
  • beta是加到结果上的一个值,结果返回uint8类型的图片

例如下面用法,转化XY方向:

absX=cv2.convertScaleAbs(x)   # 转回uint8
absY=cv2.convertScaleAbs(y)

addWeighted()

由于Sobel算子是在两个方向计算的,最后还需要用cv2.addWeighted(…)函数将其组合起来

函数功能:

  • 实现以不同的权重将两幅图片叠加,对于不同的权重,叠加后的图像会有不同的透明度

函数原型为:

dst = cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]])   

参数:

  • src1 - 第一张图片
  • alpha - 是第一幅图片中元素的权重
  • src2 - 第二张图片
  • beta - 是第二幅图片中元素的权重
  • gamma - 是加到最后结果上的一个值

代码案例

用API

在这里插入图片描述

#include <iostream>
#include <math.h>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/highgui/highgui_c.h>  

using namespace cv;
using namespace std;

int main(int argc, char** argv) 
{
	Mat src, dst;
	src = imread("./test2.jpg");
	if (!src.data) {
		printf("could not load image...n");
		return -1;
	}

	char INPUT_TITLE[] = "input image";
	char OUTPUT_TITLE[] = "sobel-demo";
	namedWindow(INPUT_TITLE, CV_WINDOW_AUTOSIZE);
	// namedWindow(OUTPUT_TITLE, CV_WINDOW_AUTOSIZE);
	imshow(INPUT_TITLE, src);

	Mat gray_src;
	GaussianBlur(src, dst, Size(3, 3), 0, 0);
	cvtColor(dst, gray_src, CV_BGR2GRAY);
	// imshow("gray image", gray_src);

	Mat xgrad, ygrad;
	// Scharr(gray_src, xgrad, CV_16S, 1, 0);
	// Scharr(gray_src, ygrad, CV_16S, 0, 1);
	Sobel(gray_src, xgrad, CV_16S, 1, 0, 3);
	Sobel(gray_src, ygrad, CV_16S, 0, 1, 3);
	convertScaleAbs(xgrad, xgrad);
	convertScaleAbs(ygrad, ygrad);
	imshow("xgrad", xgrad);
	imshow("ygrad", ygrad);

	Mat xygrad = Mat(xgrad.size(), xgrad.type());
	printf("type : %dn", xgrad.type());
	int width = xgrad.cols;
	int height = ygrad.rows;
	for (int row = 0; row < height; row++) 
	{
		for (int col = 0; col < width; col++) 
		{
			int xg = xgrad.at<uchar>(row, col);
			int yg = ygrad.at<uchar>(row, col);
			int xy = xg + yg;
			xygrad.at<uchar>(row, col) = saturate_cast<uchar>(xy);
		}
	}

	addWeighted(xgrad, 0.5, ygrad, 0.5, 0, xygrad);
	imshow("xygrad", xygrad);

	waitKey(0);
	return 0;
}

一大神自己写的

在这里插入图片描述

#include <iostream>
#include <math.h>
#include <opencv2/opencv.hpp>
#include<opencv2/highgui.hpp>
#include <opencv2/highgui/highgui_c.h>  

using namespace cv;
using namespace std;

int main()
{
	Mat m_img = imread("./test2.jpg");
	Mat src(m_img.rows, m_img.cols, CV_8UC1, Scalar(0));
	cvtColor(m_img, src, CV_RGB2GRAY);

	Mat dstImage(src.rows, src.cols, CV_8UC1, Scalar(0));
	for (int i = 1; i < src.rows - 1; i++)
	{
		for (int j = 1; j < src.cols - 1; j++)
		{
			dstImage.data[i*dstImage.step + j] = sqrt((src.data[(i - 1)*src.step + j + 1]
				+ 2 * src.data[i*src.step + j + 1]
				+ src.data[(i + 1)*src.step + j + 1]
				- src.data[(i - 1)*src.step + j - 1] - 2 * src.data[i*src.step + j - 1]
				- src.data[(i + 1)*src.step + j - 1])*(src.data[(i - 1)*src.step + j + 1]
					+ 2 * src.data[i*src.step + j + 1] + src.data[(i + 1)*src.step + j + 1]
					- src.data[(i - 1)*src.step + j - 1] - 2 * src.data[i*src.step + j - 1]
					- src.data[(i + 1)*src.step + j - 1]) + (src.data[(i - 1)*src.step + j - 1] + 2 * src.data[(i - 1)*src.step + j]
						+ src.data[(i - 1)*src.step + j + 1] - src.data[(i + 1)*src.step + j - 1]
						- 2 * src.data[(i + 1)*src.step + j]
						- src.data[(i + 1)*src.step + j + 1])* (src.data[(i - 1)*src.step + j - 1] + 2 * src.data[(i - 1)*src.step + j]
							+ src.data[(i - 1)*src.step + j + 1] - src.data[(i + 1)*src.step + j - 1]
							- 2 * src.data[(i + 1)*src.step + j]
							- src.data[(i + 1)*src.step + j + 1]));

		}

	}
	Mat grad_y(src.rows, src.cols, CV_8UC1, Scalar(0));
	{
		for (int i = 1; i < src.rows - 1; i++)
		{
			for (int j = 1; j < src.cols - 1; j++)
			{
				grad_y.data[i*grad_y.step + j] = abs((src.data[(i - 1)*src.step + j + 1]
					+ 2 * src.data[i*src.step + j + 1]
					+ src.data[(i + 1)*src.step + j + 1]
					- src.data[(i - 1)*src.step + j - 1] - 2 * src.data[i*src.step + j - 1]
					- src.data[(i + 1)*src.step + j - 1]));
			}
		}
	}
	Mat grad_x(src.rows, src.cols, CV_8UC1, Scalar(0));
	{
		for (int i = 1; i < src.rows - 1; i++)
		{
			for (int j = 1; j < src.cols - 1; j++)
			{
				grad_x.data[i*grad_x.step + j] = sqrt((src.data[(i - 1)*src.step + j - 1] + 2 * src.data[(i - 1)*src.step + j]
					+ src.data[(i - 1)*src.step + j + 1] - src.data[(i + 1)*src.step + j - 1]
					- 2 * src.data[(i + 1)*src.step + j]
					- src.data[(i + 1)*src.step + j + 1])* (src.data[(i - 1)*src.step + j - 1] + 2 * src.data[(i - 1)*src.step + j]
						+ src.data[(i - 1)*src.step + j + 1] - src.data[(i + 1)*src.step + j - 1]
						- 2 * src.data[(i + 1)*src.step + j]
						- src.data[(i + 1)*src.step + j + 1]));
			}
		}
	}
	imshow("ԭͼ", src);
	imshow("gradient", dstImage);
	imshow("Vertical gradient", grad_y);
	imshow("Horizontal gradient", grad_x);

	waitKey(0);
	return 0;
}

最后

以上就是细腻舞蹈为你收集整理的OpenCV 边缘检测之Sobel算子Sobel算子(索贝尔算子)相关API代码案例的全部内容,希望文章能够帮你解决OpenCV 边缘检测之Sobel算子Sobel算子(索贝尔算子)相关API代码案例所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部