Python +OpenCV CH10:图像梯度

本文介绍了Python结合OpenCV库进行图像梯度处理的方法,包括Sobel算子、Scharr算子和Laplacian算子的基础理论与代码实践。Sobel算子用于计算图像的x和y方向梯度,Scharr算子提供更精确的梯度计算,而Laplacian算子则通过二阶导数检测图像边缘。文章通过实例展示了各种算子的使用和效果对比。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 sobel理论基础

1.1 基础理论

目的: 利用卷积核,计算不同方向上的梯度.

  • x方向有无边界: 右边- 左边
    在这里插入图片描述
    计算点P5 x方向上的梯度. 根据距离,对卷积核设置不同的系数
    在这里插入图片描述
  • y方向有无边界:下边 - 上边
    在这里插入图片描述
    与x方向类似, 计算点P5 y方向上的梯度.
    在这里插入图片描述
  • 计算近似梯度
    在这里插入图片描述
    进一步简化
    在这里插入图片描述
    对图中点P5,进行梯度计算:
    示例

2 sobel算子及其函数使用

2.1 基础理论

  • 计算梯度

dst=cv2.Sobel(src, ddepth, dx, dy, [ksize])
其中,参数:
・src – 输入图像;
・ddepth– 图像深度;
  → -1,表示和原图像深度一致,但是计算梯度值时会出现负数,自动截断为0,导致信息丢失
  → cv2.CV_64F,改变输出的数据类型,设置的更高,使之允许存在负数. 在后续操作中绝对值后,再转换为np.uint8类型  
・dx – x方向;
  → [dx=1,dy=0]
・dy – y方向;
  → [dx=0,dy=1]
・ [ksize] – 核大小;
  → 须为奇数(如1,3,5),默认为3
  → -1时,自动转换为scharr算子

  • 修正梯度结果(负数转正)

dst = cv2.convertScaleAbs(src[,alpha[,beta]])
dst = cv2.convertScaleAbs(src) 简化版
将原始图像转换为256色位图,表示对负数取绝对值 dst = 调整(原始图像*alpha系数 + beta修正值)

在这里插入图片描述

  • 计算sobel
    有2种方式.
    ・方式1不太严谨,往往会得到错误的结果
    ・所以一般采用方式2: 分别计算出x,y方向的梯度后相加
    在这里插入图片描述

方式2 借用cv2.addWeighted函数计算 x,y 两幅图像的权重和

dst= cv2.addWeighted(src1,alpha,src2,beta,gamma)
其中,参数:
・dst– 计算结果;
・src1 – 源图像1;
・alpha– 源图像1系数;
・src2 – 源图像2;
・beta– 源图像2系数;
・gamma– 修正值;

2.2 代码示例

import cv2
import numpy as np
o = cv2.imread('image\\sobel4.bmp',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(o,cv2.CV_64F,1,0,ksize=3)
sobely = cv2.Sobel(o,cv2.CV_64F,0,1,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)   # 转回uint8  
sobely = cv2.convertScaleAbs(sobely)  
sobelxy =  cv2.addWeighted(sobelx,0.5,sobely,0.5,0)   # x,y方向两幅图像的权重和 dx + dy 
sobelxy11=cv2.Sobel(o,cv2.CV_64F,1,1,ksize=3)      #  dx=1 ,dy =1 
cv2.imshow("original",o)
cv2.imshow("x",sobelx)
cv2.imshow("y",sobely)
cv2.imshow("xy",sobelxy)
cv2.imshow("xy11",sobelxy11)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果

在这里插入图片描述

● 示例2
sobelxy11=cv2.Sobel(o,cv2.CV_64F,1,1,ksize=3)
dx=1 ,dy =1 经常会被忽略,容易出错. 无法正常提取到边界
在这里插入图片描述

3 scharr算子函数及其使用

3.1 基础理论

  • 目的: 使用3*3sobel算子时,并不够精确. scharr算子计算梯度效果更好
  • 相当于sobel算子的改进,但是卷积核的系数不一样
  • 运算强度,速度完全等价
    在这里插入图片描述
  • cv2.Scharr函数

dst= cv2.Scharr(src, ddepth, dx, dy)
其中,参数:
・dst– 计算结果;
・src – 源图像;
・ddepth– 图像深度;
  → -1时,表示和原图深度一致,但计算梯度时出现负数,自动截断为0,导致信息丢失 ,鉴于此
    → a) 深度先设置为, cv2.CV_64F 数据类型(可保存负值) 详细官方文档

→ b) cv2.convertScaleAbs(dst) 对a)结果取绝对值后,再转换为np.uint8类型 
・dx – x方向: [dx=1,dy=0]
・dy – y方向: [dx=0,dy=1]

  • 两个方向梯度
    ・与sobel类似,两个方向梯度 = dx + dy
      → scharrxy = cv2.addWeighted(scharrx,0.5,scharry,0.5,0)
    ・满足条件: dx>=0 且 dy >=0 且 dx + dy ==1

3.2 代码示例

  • x方向梯度
import cv2
import numpy as np
o = cv2.imread('image\\scharr.bmp', cv2.IMREAD_GRAYSCALE)
scharrx = cv2.Scharr(o, cv2.CV_64F, 1, 0) #1,0表示x方向
scharrx = cv2.convertScaleAbs(scharrx) #转回uint8
cv2.imshow("original", o)
cv2.imshow("x", scharrx)
cv2.waitkey()
cv2.destroyAllWindows()

运行结果
在这里插入图片描述

  • y方向梯度
import cv2
import numpy as np
o = cv2.imread('image\\scharr.bmp', cv2.IMREAD_GRAYSCALE)
scharry = cv2.Scharr(o, cv2.CV_64F, 0, 1) #1,0表示x方向
scharry = cv2.convertScaleAbs(scharry) #转回uint8
cv2.imshow("original", o)
cv2.imshow("y", scharry)
cv2.waitkey()
cv2.destroyAllWindows()

运行结果
在这里插入图片描述

  • 两个方向梯度
    使用函数 cv2.addWeighted(scharrx, alpha, scharry, beta, gamma)
scharrxy = cv2.addweighted(scharrx, 0.5, scharry, 0.5, 0)

运行结果
在这里插入图片描述
scharrscharr是sobel算子的进化版, 用sobel算子也能达到scharr算子的效果.
在这里插入图片描述

4 sobel算子和scharr算子的比较

4.1 基础理论

  • sobel算子系数:1,2,1 ; scharr算子3,10,3 ;
  • 临近的像素点权重值更高, 所以scharr算子要比sobel算子拥有更高的精确度

4.2 代码示例

示例

import cv2
import numpy as np
o = cv2.imread('image\\lena.bmp', cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(o, cv2.CV_64F, 1, 0, ksize=3)
sobely = cv2.Sobel(o, cv2.CV_64F, 0, 1, ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.convertScaleAbs(sobey)
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)

scharrx = cv2.Scharr(o,cv2.CV_64F,1,0)
scharry = cv2.Scharr(o,cv2.CV_64F,0,1)
scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.convertScaleAbs(scharry)
scharrxy = cv2.addWeighted(scharrx,0.5,scharry,0.5,0)

cv2.imshow("original",o)
cv2.imshow("sobelxy",sobelxy)
cv2.imshow("scharrxy",scharrxy)
cv2.waitkey()
cv2.destoryAllWindows()

运行结果
sobel和scharr算子比较

  • scharr算子把比较细小的边界也检测出来
  • sobel算子仅检测出了比较重的边界, 仅把差值大的像素点检测出来
  • 根据不同的应用场景,选择不同的算子

5 laplacian算子及使用

5.1 基础理论

  • 拉普拉斯算子类似于二阶sobel倒数,OpenCV里调用sobel算子来计算拉普拉斯算子
  • 使用公式
    在这里插入图片描述
  • 使用卷积核
    在这里插入图片描述
    在这里插入图片描述
  • 和sobel算子,scharr算子的比较

在这里插入图片描述
具体含义
在这里插入图片描述

  • cv2.Laplacian函数

dst= cv2.Laplacian(src,ddepth)
其中,参数:
・dst– 计算结果;
・src – 源图像;
・ddepth– 图像深度;
  →通常设置为-1, 表示和原图像一致
  →为了防止出现负值时的截断, 可用cv2.CV_64F

5.2 代码示例

示例

import cv2
import numpy as np
o = cv2.imread('image\\lena.bmp', cv2.IMREAD_GRAYSCALE)
laplacian= cv2.Laplacian(o, cv2.CV_64F)
laplacian= cv2.convertScaleAbs(laplacian)
cv2.imshow("original",o)
cv2.imshow("laplacian",laplacian)
cv2.waitkey()
cv2.destoryAllWindows()

结果1
在这里插入图片描述
结果2
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值