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()
梯度简单来说就是求导,OpenCV中提供三种不同的梯度滤波器:Sobel,Scharr和Laplacian。其中前两个求一阶导或二阶导,Scharr是对Sobel的优化,Laplacian求二阶导。
学习函数:cv2.Sobel(), cv2.Schar(), cv2.Laplacian()等
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)
输出:
输出图片的深度不同造成的不同效果:
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)
输出:
学习函数:cv2.Canny()
Canny边缘检测是一种非常流行的边缘检测算法,该算法由很多步构成。
cv2.Canny()函数:
img = cv2.imread("messi5.jpg")
edges = cv2.Canny(img, 100, 600)
showImages(img ,edges)
输出:
学习函数:cv2.pyrUp(), cv2.pyrDown()
图像金字塔:同一图像的不同分辨率的子图集合。如果把分辨率最大的放在底部,最小的放在顶部,看起来就像一座金子塔。图像金字塔分为两类:高斯和拉普拉斯。
lower_reso = cv2.pyrDown(img)
higher_reso = cv2.pyrUp(img)
showImages(img, lower_reso)
showImages(img, higher_reso)
输出:
注意:输出图像的分辨率增大一倍或减少一倍。
higher_reso2 = cv2.pyrUp(lower_reso)
showImages(img, higher_reso2)
输出:
上述输出过程:首先对原图进行Down,分辨率降为一半,再进行Up,分辨率升为一倍。最终得到的图像与原图分辨率大小一样,但很明显图像已经变得很模糊了,这是因为在Down的过程中信息有丢失。
步骤:
# 读入两幅图像
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)
输出:
可以看到,图像融合的结果比直接拼接在一起的效果要好很多。