OpenCV图像锐化代码实现

举报
Y_K_C 发表于 2021/10/10 21:02:01 2021/10/10
【摘要】 声明:本文是OpenCV入门级别的技术分享,主要围绕图像预处理来进行学习,所用语言均为Python。

前面了解了一下图像锐化的方法及其理论基础,鉴于篇幅原因就没有给出代码实现,今天根据前面介绍的图像锐化的方法进行实战代码演练。

二、代码实现

1.Robert算子

image.png
根据公式我们得到了两个算子:
image.png
因此我们可以通过定义这两个算子,再通过锐化的API进行Robert算子锐化,具体如下:

import cv2 as cv
import numpy as np
path = "C:\\Users\\27914\\Desktop\\images\\test2.jpg"
image = cv.imread(path)
x = np.array([[-1,0],[0,1]],dtype=np.float32)#水平方向的算子
y = np.array([[0,-1],[1,0]],dtype=np.float32)#垂直方向的算子
gx = cv.filter2D(image,cv.CV_16S,x)
gy = cv.filter2D(image,cv.CV_16S,y)
absgx = cv.convertScaleAbs(gx)#求绝对值
absgy = cv.convertScaleAbs(gy)#求绝对值
result = cv.addWeighted(absgx,0.5,absgy,0.5,0)
cv.imshow("result",result)
cv.waitKey(0)
cv.destroyAllWindows()

Robert算子锐化实际上是卷积操作,因此我们使用OpenCV的卷积操作API——filter2D(),主要参数解释:
src:输入图像;
ddepth:图像深度,实际上是指图像数据类型,这里我附上一张图:
image.png
其中:U即是无符号整型(Unsigned int),S即是有符号整型(Signed int),F即是浮点型(Float),数字是位数。
convertScaleAbs():这个API是将传入的数据通过线性变换进行缩放,计算其绝对值并转化成八位,主要参数解释:
src:输入的矩阵;
alpha:缩放的系数,在这里就不进行过多的介绍了;
beta:偏置项
仅传入src即是对原来的数据求一个绝对值。
Robert算子法的效果:
image.png
锐化后:
image.png
可以看到图像是偏暗的,边缘的提取也不够精确。

2.Laplacian算子法

Laplacian算子:
image.png
OpenCV提供了API——Laplacian(),专门用于拉普拉斯算子锐化图像,由于其内部计算了图像的梯度,所以用到了sobel算子。Laplacian算子法代码实现非常简单,只不过Laplacian算子对噪声比较敏感,一般先将图像平滑后在进行Laplacian算子锐化:

import cv2 as cv
import numpy as np
path = "C:\\Users\\27914\\Desktop\\images\\test2.jpg"
image = cv.imread(path,cv.IMREAD_GRAYSCALE)
#拉普拉斯算子
image = cv.GaussianBlur(image,(0,0),3)
result = cv.Laplacian(image,cv.CV_16S,ksize=5,delta=100)
result = cv.convertScaleAbs(result)
cv.imshow("image",image)
cv.imshow("result",result)
cv.waitKey(0)
cv.destroyAllWindows()

模糊:
image.png
输出:
image.png
有尝试过通过定义Laplacian算子再进行卷积实现锐化,但是效果不太好,读者可自己尝试一下,过程与定义Robert算子差不多。
Laplacian()主要参数解释:
src:输入图像;
ddepth:图像深度,传入-1表示与原图的深度相同;
ksize:表示卷积核大小,只能为1,3,5,7
scale:表示缩放比例,默认不缩放;
delta:偏置项,最终会加到输出中;
borderType:判断图像边界的方法。

3.Prewitt算子法

image.png
由于OpenCV没有提供该算子的算法,但是我们可以通过自定义的方式进行锐化,由于Prewitt算子数量比较多,这里只用了两个方向的算子,其他方向的算子读者可以自行练习,代码如下:

import cv2 as cv
import numpy as np
path = "C:\\Users\\27914\\Desktop\\images\\test2.jpg"
image = cv.imread(path,cv.IMREAD_GRAYSCALE)
#Prewitt算子
prewitty = np.array([[1,1,1],[1,-2,1],[-1,-1,-1]],dtype=np.float32)
prewittx = np.array([[-1,1,1],[-1,-2,1],[-1,1,1]],dtype=np.float32)
gx = cv.convertScaleAbs(cv.filter2D(image,cv.CV_16S,prewittx))
gy = cv.convertScaleAbs(cv.filter2D(image,cv.CV_16S,prewitty))
result = cv.addWeighted(gx,0.5,gy,0.5,0)
cv.imshow("image",image)
cv.imshow("result",result)
cv.waitKey(0)
cv.destroyAllWindows()

输出如下:
image.png

4.Sobel算子

image.png image.png

OpenCV提供了该算子的API,所以写起来比较方便,本质上索贝尔算子是计算了图像的梯度,具体代码:

import cv2 as cv
import numpy as np
path = "C:\\Users\\27914\\Desktop\\images\\test2.jpg"
image = cv.imread(path,cv.IMREAD_GRAYSCALE)
#索贝尔算子
sobelx = cv.Sobel(image,cv.CV_16S,dx=1,dy=0,ksize=3)
sobely = cv.Sobel(image,cv.CV_16S,dx=0,dy=1,ksize=3)
sobelx = cv.convertScaleAbs(sobelx)
sobely = cv.convertScaleAbs(sobely)
result = cv.addWeighted(sobelx,0.5,sobely,0.5,0)
cv.imshow("image",image)
cv.imshow("result",result)
cv.waitKey(0)
cv.destroyAllWindows()

输出:
image.png
Sobel()主要参数解释:
src:输入图像;
ddepth:图像深度,传入-1表示与原图的深度相同;
dx:水平方向,可设为0或1,0表示不选则这个方向,1表示选择这个方向;
dy:垂直方向,可设为0或1,意义同上;
ksize:表示卷积核大小;
scale:表示缩放比例,默认不缩放;
delta:偏置项,最终会加到输出中;
borderType:判断图像边界的方法。

5.高通滤波法

我们通过定义H来实现锐化,代码如下:

import cv2 as cv
import numpy as np
path = "C:\\Users\\27914\\Desktop\\images\\test2.jpg"
image = cv.imread(path,cv.IMREAD_GRAYSCALE)
#高通滤波
H1 = np.array([[0,-1,0],[-1,5,-1],[0,-1,0]],dtype=np.float32)
H2 = np.array([[-1,-1,-1],[-1,9,-1],[-1,-1,-1]],dtype=np.float32)
H3 = np.array([[1,-2,1],[-2,5,-2],[1,-2,1]],dtype=np.float32)
H4 = np.array([[0,-2,0],[-2,19,-2],[0,-2,0]],dtype=np.float32)*(1/7)
H5 = np.array([[-2,-1,-2],[-1,6,-1],[-2,-1,-2]],dtype=np.float32)*(1/2)
result = cv.convertScaleAbs(cv.filter2D(image,cv.CV_16S,H5))
cv.imshow("image",image)
cv.imshow("result",result)
cv.waitKey(0)
cv.destroyAllWindows()

选择H5时,输出如下:
image.png

6.补充一个算子

Scharr算子是对Sobel算子的改进,Sobel算子对于图像中较弱的边缘提取效果比较差,因此提出了Scharr算子来弥补这一缺陷,具体的算子:
image.png
也是两个方向,OpenCV有相应的API——Scharr(),具体代码如下:

import cv2 as cv
import numpy as np
path = "C:\\Users\\27914\\Desktop\\images\\test2.jpg"
image = cv.imread(path,cv.IMREAD_GRAYSCALE)
#Scharr算子
scharrx = cv.Scharr(image,cv.CV_16S,dx=1,dy=0)
scharry = cv.Scharr(image,cv.CV_16S,dx=0,dy=1)
scharrx = cv.convertScaleAbs(scharrx)
scharry = cv.convertScaleAbs(scharry)
result = cv.addWeighted(scharrx,0.5,scharry,0.5,0)
cv.imshow("image",image)
cv.imshow("result",result)
cv.waitKey(0)
cv.destroyAllWindows()

输出:
image.png
Scharr()这个API与Sobel()差不多,只不过没有ksize这个参数,读者可以参考Sobel的参数解释。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。