欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2023-12-27 08:42:03
...

导入所需的库

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章)

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

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

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

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章)

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

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章)

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章)

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

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

higher_reso2 = cv2.pyrUp(lower_reso)

showImages(img, higher_reso2)

输出:

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

上述输出过程:首先对原图进行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章)

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

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

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

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

 

 

上一篇:

下一篇: