最近想对OpenCV进行系统学习,看到网上这份教程写得不错,于是跟着来学习实践一下。
【[email protected], youcans 的 OpenCV 例程, https://youcans.blog.csdn.net/article/details/125112487】
程序仓库:https://github.com/zstar1003/OpenCV-Learning
边界扩充顾名思义就是扩大图像的边界。
OpenCV 中提供了函数 cv.copyMakeBorder 进行边界扩充方式。
cv.copyMakeBorder(src, top, bottom, left, right, borderType[, dst[, value]]) → dst
参数说明:
示例程序:
"""
图像边界扩充
"""
import cv2
import matplotlib.pyplot as plt
import numpy as np
img = cv2.imread("../img/xdu.jpg") # 读取彩色图像(BGR)
top = bottom = left = right = 50
imgReplicate = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_REPLICATE)
imgReflect = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_REFLECT)
imgReflect101 = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_REFLECT_101)
imgWrap = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_WRAP)
imgConstant = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=(200, 200, 200))
plt.figure(figsize=(9, 6))
plt.subplot(231), plt.axis([-50, 562, -50, 562]), plt.title('ORIGINAL'), plt.axis('off')
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.subplot(232), plt.axis('off'), plt.title('REPLICATE')
plt.imshow(cv2.cvtColor(imgReplicate, cv2.COLOR_BGR2RGB))
plt.subplot(233), plt.axis('off'), plt.title('REFLECT')
plt.imshow(cv2.cvtColor(imgReflect, cv2.COLOR_BGR2RGB))
plt.subplot(234), plt.axis('off'), plt.title('REFLECT_101')
plt.imshow(cv2.cvtColor(imgReflect101, cv2.COLOR_BGR2RGB))
plt.subplot(235), plt.axis('off'), plt.title('WRAP')
plt.imshow(cv2.cvtColor(imgWrap, cv2.COLOR_BGR2RGB))
plt.subplot(236), plt.axis('off'), plt.title('CONSTANT')
plt.imshow(cv2.cvtColor(imgConstant, cv2.COLOR_BGR2RGB))
plt.show()
二维卷积在计算机计算机视觉中非常常见,简单来说,就是定义一个卷积核矩阵,再将矩阵旋转180度(为了简化也可以不旋转),然后和图像各窗口相乘相加。
OpenCV 中提供了函数cv.filter2D
来实现二维卷积运算。
cv.filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]]) → dst
参数说明:
示例程序:
"""
图像二维卷积
"""
import cv2
import matplotlib.pyplot as plt
import numpy as np
img = cv2.imread("../img/lena.jpg", flags=0) # # flags=0 读取为灰度图像
kernel = np.array([[-1, -1, -1], [-1, 9, -1], [-1, -1, -1]]) # Gx + j*Gy
kFlip = cv2.flip(kernel, -1) # 将卷积核旋转180度
# 使用函数filter2D算出same卷积
imgConv1 = cv2.filter2D(img, -1, kFlip,
anchor=(0, 0), borderType=cv2.BORDER_CONSTANT)
imgConv2 = cv2.filter2D(img, -1, kFlip,
anchor=(0, 0), borderType=cv2.BORDER_REFLECT)
plt.figure(figsize=(9, 6))
plt.subplot(131), plt.axis('off'), plt.title('Original'), plt.axis('off')
plt.imshow(img, cmap='gray', vmin=0, vmax=255)
plt.subplot(132), plt.axis('off'), plt.title('cv2.filter2D (BORDER_CONSTANT)')
plt.imshow(np.absolute(imgConv1), cmap='gray', vmin=0, vmax=255)
plt.subplot(133), plt.axis('off'), plt.title('cv2.filter2D (BORDER_REFLECT)')
plt.imshow(np.absolute(imgConv2), cmap='gray', vmin=0, vmax=255)
plt.tight_layout()
plt.show()
低通滤波,可以抑制图像中的灰度突变,使图像变得模糊。
主要用于:
高斯核的数学表达式为:
OpenCV 提供了cv.GaussianBlur
函数实现高斯核低通滤波器,cv.getGaussianKernel
函数可以计算一维高斯滤波器的系数。
cv.GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]]) → dst
cv.getGaussianKernel(ksize, sigma[, ktype]) → retval
参数说明:
中值滤波是一种非线性滤波方法,是基于统计排序方法的滤波器。中值滤波法将像素点的邻域内的所有像素点灰度值的中值作为该像素点的灰度值。
中值滤波对于消除图像中的椒盐噪声非常有效。(椒盐噪声也称为脉冲噪声,是随机出现的白点或者黑点,通常是由于影像讯号受到干扰而产生,如脉冲干扰、图像扫描)
OpenCV 提供了cv.medianBlur
函数实现中值滤波算法。
cv.medianBlur(src, ksize[, dst]) → dst
参数说明:
示例程序:
"""
中值滤波
"""
import cv2
import matplotlib.pyplot as plt
import numpy as np
img = cv2.imread("../img/lena.jpg", flags=0)
imgMedianBlur1 = cv2.medianBlur(img, 3)
imgMedianBlur2 = cv2.medianBlur(img, 7)
plt.figure(figsize=(9, 6))
plt.subplot(131), plt.axis('off'), plt.title("Original")
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.subplot(132), plt.axis('off'), plt.title("cv2.medianBlur(size=3)")
plt.imshow(cv2.cvtColor(imgMedianBlur1, cv2.COLOR_BGR2RGB))
plt.subplot(133), plt.axis('off'), plt.title("cv2.medianBlur(size=7)")
plt.imshow(cv2.cvtColor(imgMedianBlur2, cv2.COLOR_BGR2RGB))
plt.tight_layout()
plt.show()
图像锐化的目的是增强图像的灰度跳变部分,使模糊的图像变得清晰。图像锐化也称为高通滤波,通过和增强高频,衰减和抑制低频。
钝化掩蔽指的是从原始图像中减去一幅平滑处理的钝化图像,也可以实现图像锐化效果。
公式如下:
当k>1时,实现高提升滤波;当k=1时,实现钝化掩蔽;k<1时,减弱钝化掩蔽。
钝化掩蔽的实现过程是:
(1)对原始图像进行平滑处理,得到平滑图像;
(2)从原始图像中减去平滑图像,产生掩蔽模板;
(3)将原始图像与掩蔽模板加权相加,得到钝化掩蔽。
示例代码:
"""
钝化掩蔽
"""
import cv2
import matplotlib.pyplot as plt
import numpy as np
img = cv2.imread("../img/lena.jpg", flags=0)
# 对原始图像进行平滑,GaussianBlur(img, size, sigmaX)
imgGauss = cv2.GaussianBlur(img, (5, 5), sigmaX=5)
imgGaussNorm = cv2.normalize(imgGauss, dst=None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX)
# 掩蔽模板:从原始图像中减去平滑图像
imgMask = img - imgGaussNorm
passivation1 = img + 0.6 * imgMask # k<1 减弱钝化掩蔽
imgPas1 = cv2.normalize(passivation1, None, 0, 255, cv2.NORM_MINMAX)
passivation2 = img + imgMask # k=1 钝化掩蔽
imgPas2 = cv2.normalize(passivation2, None, 0, 255, cv2.NORM_MINMAX)
passivation3 = img + 2 * imgMask # k>1 高提升滤波
imgPas3 = cv2.normalize(passivation3, None, 0, 255, cv2.NORM_MINMAX)
plt.figure(figsize=(10, 7))
titleList = ["1. Original", "2. GaussSmooth", "3. MaskTemplate",
"4. Passivation(k=0.5)", "5. Passivation(k=1.0)", "6. Passivation(k=2.0)"]
imageList = [img, imgGauss, imgMask, imgPas1, imgPas2, imgPas3]
for i in range(6):
plt.subplot(2, 3, i + 1), plt.title(titleList[i]), plt.axis('off')
plt.imshow(imageList[i], 'gray', vmin=0, vmax=255)
plt.tight_layout()
plt.show()
图像锐化主要增强图像的灰度跳变部分,主要的图像梯度算子有:Roberts、Prewitt、Sobel、Laplacian、Scharr。
相关理论在我之前的博文【计算机视觉】基础图像知识点整理中整理过,这里不再赘述。
OpenCV提供了拉普拉斯算子cv.Laplacian
来实现
cv.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]]) → dst
参数说明:
示例代码:
"""
Laplacian算子
"""
import cv2
import matplotlib.pyplot as plt
import numpy as np
img = cv2.imread("../img/lena.jpg", flags=0)
# 使用 cv2.Laplacian 实现 Laplace 卷积算子
imgLaplace2 = cv2.Laplacian(img, -1, ksize=3)
imgRecovery = cv2.add(img, imgLaplace2) # 恢复原图像
# 二值化边缘图再卷积
ret, binary = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_TRIANGLE)
imgLaplace3 = cv2.Laplacian(binary, cv2.CV_64F)
imgLaplace3 = cv2.convertScaleAbs(imgLaplace3)
plt.figure(figsize=(9, 6))
plt.subplot(131), plt.axis('off'), plt.title("Original")
plt.imshow(img, cmap='gray', vmin=0, vmax=255)
plt.subplot(132), plt.axis('off'), plt.title("cv.Laplacian")
plt.imshow(imgLaplace2, cmap='gray', vmin=0, vmax=255)
plt.subplot(133), plt.axis('off'), plt.title("thresh-Laplacian")
plt.imshow(imgLaplace3, cmap='gray', vmin=0, vmax=255)
plt.tight_layout()
plt.show()
注:图二是直接用Laplacian进行卷积,图三是先进行阈值化处理再进行卷积,这样提出的边缘会更明显。
OpenCV提供了函数cv.Sobel
实现Sobel梯度算子
cv.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]]) → dst
参数说明:
为了处理微分运算导致的数据异常(超出 [0,255]),OpenCV 提供了cv.convertScaleAbs
进行饱和运算:dst=saturate(src∗α+beta)。
cv.convertScaleAbs(src[, alpha[, beta]]) → dst
参数说明:
"""
Sobel算子
"""
import cv2
import matplotlib.pyplot as plt
import numpy as np
img = cv2.imread("../img/lena.jpg", flags=0)
# 使用 cv2.Sobel 实现 Sobel 算子
SobelX = cv2.Sobel(img, cv2.CV_16S, 1, 0) # 计算 x 轴方向
SobelY = cv2.Sobel(img, cv2.CV_16S, 0, 1) # 计算 y 轴方向
absX = cv2.convertScaleAbs(SobelX) # 转回 uint8
absY = cv2.convertScaleAbs(SobelY) # 转回 uint8
SobelXY = cv2.addWeighted(absX, 0.5, absY, 0.5, 0) # 用绝对值近似平方根
plt.figure(figsize=(10, 6))
plt.subplot(141), plt.axis('off'), plt.title("Original")
plt.imshow(img, cmap='gray', vmin=0, vmax=255)
plt.subplot(142), plt.axis('off'), plt.title("SobelX")
plt.imshow(SobelX, cmap='gray', vmin=0, vmax=255)
plt.subplot(143), plt.axis('off'), plt.title("SobelY")
plt.imshow(SobelY, cmap='gray', vmin=0, vmax=255)
plt.subplot(144), plt.axis('off'), plt.title("SobelXY")
plt.imshow(SobelXY, cmap='gray')
plt.tight_layout()
plt.show()
OpenCV提供了函数cv.Scharr
实现Scharr算子。
cv.Scharr(src, ddepth, dx, dy[, dst[, scale[, delta[, borderType]]]]) → dst
参数说明:
示例程序
"""
Scharr算子
"""
import cv2
import matplotlib.pyplot as plt
import numpy as np
img = cv2.imread("../img/lena.jpg", flags=0)
# 使用 cv2.Scharr 实现 Scharr 算子
ScharrX = cv2.Scharr(img, cv2.CV_16S, 1, 0) # 计算 x 轴方向
ScharrY = cv2.Scharr(img, cv2.CV_16S, 0, 1) # 计算 y 轴方向
absX = cv2.convertScaleAbs(ScharrX) # 转回 uint8
absY = cv2.convertScaleAbs(ScharrY) # 转回 uint8
ScharrXY = cv2.addWeighted(absX, 0.5, absY, 0.5, 0) # 用绝对值近似平方根
plt.figure(figsize=(10, 6))
plt.subplot(141), plt.axis('off'), plt.title("Original")
plt.imshow(img, cmap='gray', vmin=0, vmax=255)
plt.subplot(142), plt.axis('off'), plt.title("ScharrX")
plt.imshow(ScharrX, cmap='gray', vmin=0, vmax=255)
plt.subplot(143), plt.axis('off'), plt.title("ScharrY")
plt.imshow(ScharrY, cmap='gray', vmin=0, vmax=255)
plt.subplot(144), plt.axis('off'), plt.title("ScharrXY")
plt.imshow(ScharrXY, cmap='gray')
plt.tight_layout()
plt.show()