基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接

大四毕业后的这个暑假正式开始学习openCV

参考教程:唐宇迪老师: https://www.bilibili.com/video/BV1tb4y1C7j7

1.傅里叶变换

傅里叶变换的作用

高频:变化剧烈的灰度分量,例如边界

低频:变化缓慢的灰度分量,例如一片大海

滤波:

低通滤波器:只保留低频,会使图像模糊

高通滤波器:只保留高频,会使得图像细节增强

opencv中主要是cv2.dft()cv2.idft(),输入图像需要先转换成np.float32格式。

得到的结果中频率为0的部分会在左上角,通常需要转换到中心位置,可以通过shift实现。

cv2.dft()返回的结果是双通道的(实部,虚部),通常还需要转换成图像格式才能展示(0,255)。

一些函数说明:

  1. cv2.dft(img, cv2.DFT_COMPLEX_OUTPUT) 进行傅里叶变化

参数说明: img表示输入的图片, cv2.DFT_COMPLEX_OUTPUT表示进行傅里叶变化的方法

  1. np.fft.fftshift(img) 将图像中的低频部分移动到图像的中心

参数说明:img表示输入的图片

  1. cv2.magnitude(x, y) 将sqrt(x^2 + y^2) 计算矩阵维度的平方根

参数说明:需要进行x和y平方的数

4.np.fft.ifftshift(img) # 进图像的低频和高频部分移动到图像原来的位置

参数说明:img表示输入的图片

5.cv2.idft(img) # 进行傅里叶的逆变化

参数说明:img表示经过傅里叶变化后的图片

demo1:

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

'''
第一步:载入图片

第二步:使用np.float32进行格式转换

第三步:使用cv2.dft进行傅里叶变化

第四步:使用np.fft.shiftfft将低频转移到中间位置

第五步:使用cv2.magnitude将实部和虚部投影到空间域

第六步:进行作图操作
'''

img = cv2.imread('D:\\openCV files\\data\\2\\lena.jpg',0)#0表示灰度图

img_float32 = np.float32(img)#必须转换

dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)#将左上角的低频移动至中心
#得到灰度图能表示的形式
magnitude_spectrum = 20*np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))#0,1表示实部虚部两个通道,:,:,表示图像像素坐标,20*log,是将结果映射到0-255的公式

plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'),plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(magnitude_spectrum, cmap = 'gray')
plt.title('Magnitude Spectrum'),plt.xticks([]),plt.yticks([])
plt.show()

ou1:
基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第1张图片
低通滤波

demo2:

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

# 第一步读入图片
img = cv2.imread('D:\\openCV files\\data\\2\\lena.jpg',0)#0表示灰度图

# 第二步:进行数据类型转换
img_float32 = np.float32(img)#必须转换
# 第三步:使用cv2.dft进行傅里叶变化
dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT)
# 第四步:使用np.fft.fftshift将低频转移到图像中心
dft_shift = np.fft.fftshift(dft)#将左上角的低频移动至中心

# 第五步:定义掩模:生成的掩模中间为1周围为0
rows, cols = img.shape
crow, ccol = int(rows/2), int(cols/2)   #中心位置,方便确定掩膜

#低通滤波
mask = np.zeros((rows, cols, 2), np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1

# 第六步:将掩模与傅里叶变化后图像相乘,保留中间部分
fshift = dft_shift*mask
# 第七步:使用np.fft.ifftshift(将低频移动到原来的位置
f_ishift = np.fft.ifftshift(fshift)
# 第八步:使用cv2.idft进行傅里叶的反变化
img_back = cv2.idft(f_ishift)
# 第九步:使用cv2.magnitude转化为空间域内
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])
# 第十步:进行绘图操作
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'),plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(img_back, cmap = 'gray')
plt.title('Result'),plt.xticks([]),plt.yticks([])
plt.show()

out2:
基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第2张图片
高通滤波

demo3:

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

# 第一步读入图片
img = cv2.imread('D:\\openCV files\\data\\2\\lena.jpg',0)#0表示灰度图

# 第二步:进行数据类型转换
img_float32 = np.float32(img)#必须转换
# 第三步:使用cv2.dft进行傅里叶变化
dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT)
# 第四步:使用np.fft.fftshift将低频转移到图像中心
dft_shift = np.fft.fftshift(dft)#将左上角的低频移动至中心

# 第五步:定义掩模:生成的掩模中间为1周围为0
rows, cols = img.shape
crow, ccol = int(rows/2), int(cols/2)   #中心位置,方便确定掩膜

#高通滤波
mask = np.ones((rows, cols, 2), np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 0

# 第六步:将掩模与傅里叶变化后图像相乘,保留四周部分
fshift = dft_shift*mask
# 第七步:使用np.fft.ifftshift(将低频移动到原来的位置
f_ishift = np.fft.ifftshift(fshift)
# 第八步:使用cv2.idft进行傅里叶的反变化
img_back = cv2.idft(f_ishift)
# 第九步:使用cv2.magnitude转化为空间域内
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])
# 第十步:进行绘图操作
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'),plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(img_back, cmap = 'gray')
plt.title('Result'),plt.xticks([]),plt.yticks([])
plt.show()

out3:
基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第3张图片
2.harris角点检测

基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第4张图片
基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第5张图片

基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第6张图片
基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第7张图片
在这里插入图片描述

基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第8张图片
基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第9张图片

cv2.cornerHarris()

img:数据类型为float32的输入图像

blockSize:角点检测中指定区域的大小

ksize:Sobel求导中使用的窗口大小

k:取值参数为[0.04,0.06]

demo4:

import cv2
import numpy as np

img = cv2.imread('D:\\openCV_files\\data\\5\\chessboard.jpg')
print('img.shape:',img.shape)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#gray = np.float32(gray)
dst = cv2.cornerHarris(gray, 2, 3, 0.04) #block:2,ksize:3,k:0.04
print('dst.shape:', dst.shape)

img[dst>0.01*dst.max()] = [0,0,255]  #把检测到的角点处用红色标记
cv2.imshow('dst',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

out4:

img.shape: (512, 512, 3)
dst.shape: (512, 512)

基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第10张图片
3.Scale Invariant Feature Transform(SIFT)

图像尺度空间

在一定的范围内,无论物体是大还是小,人眼都可以分辨出来,然而计算机要有相同的能力却很难,所以要让机器能够对物体在不同尺度下有一个统一的认知,就需要考虑图像在不同的尺度下都存在的特点。

基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第11张图片

基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第12张图片

基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第13张图片
基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第14张图片
基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第15张图片
基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第16张图片
基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第17张图片
基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第18张图片
基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第19张图片
基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第20张图片
基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第21张图片
基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第22张图片
demo5:

import cv2
import numpy as np

img = cv2.imread('D:\\openCV_files\\data\\5\\test_1.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

print(cv2.__version__)  #查看opencv版本信息

#得到特征点
sift = cv2.SIFT_create()  #opencv4.4.0以上版本重新支持了sift,调用方式由sift = cv2.xfeatures2d.SIFT_create()改为sift = cv2.SIFT_create()
kp = sift.detect(gray, None)  #关键点信息

img = cv2.drawKeypoints(gray, kp, img)  #绘制关键点

cv2.imshow('drawKeypoints', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

#计算特征
kp, des = sift.compute(gray, kp)  #返回关键点
print(np.array(kp).shape)

print(des.shape)  #每个关键点被转换成128维的向量

print(des[0])  #取出来一个看看

out5:

4.5.3
(6809,)
(6809, 128)
[  0.   0.   0.   0.   0.   0.   0.   0.  21.   8.   0.   0.   0.   0.
   0.   0. 157.  31.   3.   1.   0.   0.   2.  63.  75.   7.  20.  35.
  32.  74.  23.  66.   0.   0.   1.   3.   4.   1.   0.   0.  76.  15.
  13.  27.   8.   1.   0.   2. 157. 112.  50.  31.   2.   0.   0.   9.
  49.  42. 157. 157.  12.   4.   1.   5.   1.  13.   7.  12.  41.   5.
   0.   0. 104.   8.   5.  19.  53.   5.   1.  21. 157.  55.  35.  90.
  22.   0.   0.  17.   3.   6.  69. 157.  52.   0.   0.   0.   7.  33.
  10.  10.  11.   0.   1.   6.  44.   9.   3.   7.  19.   5.  14.  26.
  38.  28.  32.  92.  16.   2.   3.   4.   0.   0.   7.  92.  23.   0.
   0.   0.]


4.特征匹配

demo6:

import cv2

img1 = cv2.imread('D:\\openCV_files\\data\\5\\box.png', 0)
img2 = cv2.imread('D:\\openCV_files\\data\\5\\box_in_scene.png', 0)

def cv_show(name,img):
    cv2.imshow(name,img)
    cv2.waitKey()
    cv2.destroyAllWindows()

cv_show('img1', img1)
cv_show('img2', img2)

#Brute-Force蛮力匹配
sift = cv2.SIFT_create()
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)

#crossCheck表示两个特征点要相互匹配,例如A中的第i个特征点与B中的第j个特征点最近的,并且B中的第j个特征点到A中的第i个特征点也是
#NORM_L2:归一化数组的(欧几里德距离),如果其他特征计算方法需要考虑不同的匹配计算方式
bf = cv2.BFMatcher(crossCheck=True) #BFMatcher蛮力匹配

#1对1的匹配
matches = bf.match(des1, des2)
matches = sorted(matches, key=lambda x:x.distance)#排序
img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=2)  #把两幅图的关键点连在一起,取了前十个点
cv_show('img3',img3)

#k对最佳匹配
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1, des2, k=2)  #一个点可对应最近的两个点

good = []
for m,n in matches:
    if m.distance < 0.75 * n.distance:
        good.append([m])

img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, good, None, flags = 2)
cv_show('img3',img3)

out6:
基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第23张图片
基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第24张图片


5.图像拼接方法——RANSAC算法

基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第25张图片
基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第26张图片

基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第27张图片
基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第28张图片
基于python的openCV自学笔记(三)——傅里叶变换与滤波、harris角点检测、SIFT、特征匹配和图像拼接_第29张图片
图像拼接代码:https://blog.csdn.net/weixin_45719141/article/details/119079973

你可能感兴趣的:(openCV,python,opencv)