计算机视觉之OpenCV中的图像处理2(18章-20章)

导入所需的库

import cv2
import numpy as np
import matplotlib.pyplot as plt

for i in [cv2, np]:
    print(i.__name__,": ",i.__version__,sep="")

输出:

cv2.cv2: 4.2.0
numpy: 1.17.4
# 定义图像显示函数
def showImages(original, processed):
    plt.figure(figsize=(10,5))
    plt.subplot(1,2,1)
    plt.imshow(original[:,:,[2,1,0]])  # 由于OpenCV读入的图像是BGR,故在显示时转换成RGB格式
    plt.axis("off")
    plt.title("Original"+": "+str(original.shape))
    
    plt.subplot(1,2,2)
    plt.imshow(processed[:,:,[2,1,0]])
    plt.axis("off")
    plt.axis("off")
    plt.title("Processed"+": "+str(processed.shape))
    
    plt.tight_layout()
    plt.show()

18. 图像梯度

梯度简单来说就是求导,OpenCV中提供三种不同的梯度滤波器:Sobel,Scharr和Laplacian。其中前两个求一阶导或二阶导,Scharr是对Sobel的优化,Laplacian求二阶导。

学习函数:cv2.Sobel(), cv2.Schar(), cv2.Laplacian()等

18.1 Sobel算子和Scharr算子

img = cv2.imread("4.jpg")

laplacian = cv2.Laplacian(img, cv2.CV_64F)
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=5)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5)

showImages(img, laplacian)
showImages(img, sobelx)
showImages(img, sobely)

输出:

计算机视觉之OpenCV中的图像处理2(18章-20章)_第1张图片

计算机视觉之OpenCV中的图像处理2(18章-20章)_第2张图片

计算机视觉之OpenCV中的图像处理2(18章-20章)_第3张图片

输出图片的深度不同造成的不同效果:

sobelx8u = cv2.Sobel(img, cv2.CV_8U,1,0,ksize=5)
sobelx64f = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=5)
abs_sobel64f = np.absolute(sobelx64f)
sobel_8u = np.uint8(abs_sobel64f)

showImages(img, sobelx8u)
showImages(img, sobel_8u)

输出:

计算机视觉之OpenCV中的图像处理2(18章-20章)_第4张图片

计算机视觉之OpenCV中的图像处理2(18章-20章)_第5张图片

19. 边缘检测

学习函数:cv2.Canny()

19.1 原理

Canny边缘检测是一种非常流行的边缘检测算法,该算法由很多步构成。

  1. 噪声去除:由于边缘检测很容易受到噪声影响,因此第一步使用5*5的高斯滤波器去除噪声。
  2. 计算图像梯度: 对平滑后的图像使用Sobel算子计算水平方向和竖直方向的一阶导数,根据得到的两幅梯度图找到边界的梯度和方向。梯度的方向总是与边界垂直,梯度的方向归为四类:垂直、水平和两个对角线。
  3. 非极大值抑制:获得梯度的方向和大小后,对整幅图像做扫描,去除那些非边界上的点。
  4. 确定那些边界才是真正的边界。

19.2 OpenCV中的Canny边界检测

cv2.Canny()函数:

  • 参数1:输入图像
  • 参数2和参数3:minVal和maxVal
  • 参数4:Sobel卷积核大小,默认为3
  • 参数5:L2gradient,默认为False
img = cv2.imread("messi5.jpg")
edges = cv2.Canny(img, 100, 600)

showImages(img ,edges)

输出:

计算机视觉之OpenCV中的图像处理2(18章-20章)_第6张图片

20. 图像金字塔

学习函数:cv2.pyrUp(), cv2.pyrDown()

20.1 原理

图像金字塔:同一图像的不同分辨率的子图集合。如果把分辨率最大的放在底部,最小的放在顶部,看起来就像一座金子塔。图像金字塔分为两类:高斯和拉普拉斯。

  1. 高斯金字塔:顶部是由底部图像中连续行和列去除得到的。即顶部图像中的每个像素值等于下一层图像中5个像素的高斯加权平均值。
  2. 拉普拉斯:看起来像边界图,其中很多像素是0,经常被用在图像压缩中。
lower_reso = cv2.pyrDown(img)
higher_reso = cv2.pyrUp(img)

showImages(img, lower_reso)
showImages(img, higher_reso)

输出:

计算机视觉之OpenCV中的图像处理2(18章-20章)_第7张图片

计算机视觉之OpenCV中的图像处理2(18章-20章)_第8张图片

注意:输出图像的分辨率增大一倍或减少一倍。

higher_reso2 = cv2.pyrUp(lower_reso)

showImages(img, higher_reso2)

输出:

计算机视觉之OpenCV中的图像处理2(18章-20章)_第9张图片

上述输出过程:首先对原图进行Down,分辨率降为一半,再进行Up,分辨率升为一倍。最终得到的图像与原图分辨率大小一样,但很明显图像已经变得很模糊了,这是因为在Down的过程中信息有丢失。

20.2 使用金字塔进行图像融合

步骤:

  1. 读入苹果和橘子两幅图像
  2. 构建苹果和橘子的高斯金字塔(6层)
  3. 根据高斯金字塔计算拉普拉斯金字塔
  4. 在拉普拉斯的每一层进行图像融合
  5. 根据融合后的图像金字塔重建原始图像
# 读入两幅图像
A, B = cv2.imread("apple.jpg"), cv2.imread("orange.jpg")

# 构建高斯金字塔
G = A.copy()
gpA = [G]
for i in range(6):
    G = cv2.pyrDown(G)
    gpA.append(G)

G = B.copy()
gpB = [G]
for i in range(6):
    G = cv2.pyrDown(G)
    gpB.append(G)
    
# 计算拉普拉斯金字塔
lpA = [gpA[5]]
for i in range(5,0,-1):
    GE = cv2.pyrUp(gpA[i])
    L = cv2.subtract(gpA[i-1],GE)
    lpA.append(L)
    
lpB = [gpB[5]]
for i in range(5,0,-1):
    GE = cv2.pyrUp(gpB[i])
    L = cv2.subtract(gpB[i-1],GE)
    lpB.append(L)

# 拉普拉斯每一层进行融合
LS = []
for la, lb in zip(lpA, lpB):
    rows, cols, dpt = la.shape
    ls = np.hstack((la[:,0:int(cols/2)],lb[:,int(cols/2):]))
    LS.append(ls)

# 重建图像
ls_ = LS[0]
for i in range(1,6):
    ls_ = cv2.pyrUp(ls_)
    ls_ = cv2.add(ls_, LS[i])
    
# 直接重建
real = np.hstack((A[:,:int(cols/2)],B[:,int(cols/2):]))

showImages(A, ls_)
showImages(ls_, B)
showImages(A, real)
showImages(real, B)

输出:

计算机视觉之OpenCV中的图像处理2(18章-20章)_第10张图片

计算机视觉之OpenCV中的图像处理2(18章-20章)_第11张图片

计算机视觉之OpenCV中的图像处理2(18章-20章)_第12张图片

计算机视觉之OpenCV中的图像处理2(18章-20章)_第13张图片

可以看到,图像融合的结果比直接拼接在一起的效果要好很多。

 

 

你可能感兴趣的:(OpenCV)