OpenCV(python)一键入门--第十篇(图像梯度与锐化)

1:索贝尔算子

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

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

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

import cv2 as cv
import numpy as np
#获取梯度信息
#sobel算子--一种经典的图像梯度提取算子
#本质是图像空间域卷积
#与图像一阶导数相关
src = cv.imread("ma.jpg")
cv.imshow("input", src)

h, w = src.shape[:2]
x_grad = cv.convertScaleAbs(cv.Sobel(src, cv.CV_32F, 1, 0))
y_grad = cv.convertScaleAbs(cv.Sobel(src, cv.CV_32F, 0, 1))
cv.imshow("x_grad", x_grad)
cv.imshow("y_grad", y_grad)

dst = cv.convertScaleAbs(cv.add(x_grad, y_grad, dtype=cv.CV_16S))
cv.imshow("gradient", dst)

cv.waitKey(0)
cv.destroyAllWindows()

函数原型:

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

前四个是必须的参数:
第一个参数是需要处理的图像;
第二个参数是图像的深度,-1表示采用的是与原图像相同的深度。目标图像的深度必须大于等于原图像的深度;
dx和dy表示的是求导的阶数,0表示这个方向上没有求导,一般为0、1、2。

其后是可选的参数:

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

效果如下;

2:robert算子和prewitt算子

Robert算子,又称Roberts边缘检测算子,是一种利用局部差分算子寻找边缘的算子。


Robert算子图像处理后结果边缘不是很平滑。经分析,由于Robert算子通常会在图像边缘附近的区域内 产生较宽的响应,故采用上述算子检测的边缘图像常需做细化处理,边缘定位的精度不是很高。
import cv2 as cv
import numpy as np
#robert算子
#可以很好地检测图像的梯度边缘信息
#通过自定义滤波器算子实现
src = cv.imread("ma.jpg")
cv.namedWindow("input", cv.WINDOW_AUTOSIZE)
cv.imshow("input", src)

robert_x = np.array([[1, 0],[0, -1]], dtype=np.float32)
robert_y = np.array([[0, -1],[1, 0]], dtype=np.float32)

robert_grad_x = cv.convertScaleAbs(cv.filter2D(src,cv.CV_16S,robert_x))
robert_grad_y = cv.convertScaleAbs(cv.filter2D(src,cv.CV_16S,robert_y))

cv.imshow("robert x", robert_grad_x);
cv.imshow("robert y", robert_grad_y);

cv.waitKey(0)
cv.destroyAllWindows()

效果如图:

Prewitt算子是一种一阶微分算子的边缘检测,利用像素点上下、左右邻点的灰度差,在边缘处达到极值检测边缘,去掉部分伪边缘,对噪声具有平滑作用 。其原理是在图像空间利用两个方向模板与图像进行邻域卷积来完成的,这两个方向模板一个检测水平边缘,一个检测垂直边缘。

import cv2 as cv
import numpy as np
#prewitt算子
#可以很好地检测图像的梯度边缘信息
#通过自定义滤波器算子实现
src = cv.imread("ma.jpg")
cv.imshow("input", src)

prewitt_x = np.array([[-1, 0, 1], 
                      [-1, 0, 1], 
                      [-1, 0, 1]], dtype=np.float32)
prewitt_y = np.array([[-1, -1, -1],
                      [0, 0, 0], 
                      [1, 1, 1]], dtype=np.float32)

prewitt_grad_x = cv.convertScaleAbs(cv.filter2D(src, cv.CV_32F, prewitt_x))
prewitt_grad_y = cv.convertScaleAbs(cv.filter2D(src, cv.CV_32F, prewitt_y))

cv.imshow("prewitt x", prewitt_grad_x);
cv.imshow("prewitt y", prewitt_grad_y);

cv.waitKey(0)
cv.destroyAllWindows()

效果如图:

3:拉普拉斯算子

拉普拉斯算子(Laplace Operator)是n维欧几里德空间中的一个二阶微分算子,定义为梯度(▽f)的散度(▽·f)。拉普拉斯算子也可以推广为定义在黎曼流形上的椭圆型算子,称为拉普拉斯-贝尔特拉米算子

import cv2 as cv
import numpy as np
#拉普拉斯算子(二阶导数算子)
#求X,Y方向的二阶偏导数
#dx == f(x+1,y) + f(x-1,y) - 2f(x,y)
#dy == f(x,y+1) + f(x,y-1) - 2f(x,y)
#叠加后得到delta对应的二阶导数算子
#ps:拉普拉斯算子特别容易收到噪声干扰
#经常需要先将目标高斯模糊,再去边缘提取
#所以经常把这两步做个合并,叫LOG算子
image = cv.imread("ma.jpg")
cv.imshow("input", image)

h, w = image.shape[:2]
src = cv.GaussianBlur(image, (0, 0), 1)
dst = cv.Laplacian(src, cv.CV_32F, ksize=3, delta=127)
dst = cv.convertScaleAbs(dst)

cv.imshow("dst",dst)

cv.waitKey(0)
cv.destroyAllWindows()

效果如下:

3:图像锐化

卷积主要有三个功能:
1:图像模糊/去噪,
2:图像梯度/边缘发现
3:图像锐化/增强

其本质就是拉普拉斯滤波加原图权重叠加的输出,举个例子:
 -1,-1,-1         
 -1, C,-1        
 -1,-1,-1         

C>8,图像锐化,越接近8效果锐化越好
C=8,图像高通滤波
C值越大,图像锐化效果在减弱,中学像素作用在提升

示例代码如下:

import cv2 as cv
import numpy as np

src = cv.imread("ma.jpg")
cv.namedWindow("input", cv.WINDOW_AUTOSIZE)
cv.imshow("input", src)

sharpen_op = np.array([[0, -1, 0], 
                       [-1, 5, -1], 
                       [0, -1, 0]], dtype=np.float32)
sharpen_image = cv.filter2D(src, cv.CV_32F, sharpen_op)
sharpen_image = cv.convertScaleAbs(sharpen_image)#可实现图像增强等相关操作的快速运算
cv.imshow("sharpen_image", sharpen_image)

cv.imshow("sharpen_image",sharpen_image)

cv.waitKey(0)
cv.destroyAllWindows()

效果如下:(第一张是C取5的效果)

(第二张是C取9的效果)

(完)