Fork me on GitHub

图片拼接作业

sift算子

角点检测技术,比如Harris等,具有旋转不变性,即使图片发生了旋转,我们也能找到同样的角点。但是对图片进行缩放之后,角点就可能不再是角点了。

所以我们需要用尺度去描绘一副图片,不同大小的图片描绘的尺度,可以理解成单位是不一样的。为了达到这个目的需要使用尺度空间滤波器。SIFT算法使用高斯差分算子DOG来对LoG做一次近似。

图像金字塔,分成很多层,每一层又有很多组。之后我们可以做差值,经过一系列繁琐的步骤找到极值点。

按照教程写了一个代码调试一下:

1
2
3
4
5
6
7
8
9
img = cv2.imread('src1.jpg')
# 变成灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

sift = cv2.xfeatures2d.SIFT_create()
kp = sift.detect(gray, None)
img = cv2.drawKeypoints(gray,kp,outImage=gray)
cv2.imshow('img',img)
cv2.waitKey()

效果图如下:

注意我使用的opencv版本,要使用sift算子必须是sift = cv2.xfeatures2d.SIFT_create()

之后检测到特征点,直接调用cv2.drawKeypoints函数描绘特征点

cv2.drawKeypoints主要的五个参数

  • image:也就是原始图片
  • keypoints:从原图中获得的关键点,这也是画图时所用到的数据
  • outputimage:输出 //可以是原始图片
  • color:颜色设置,通过修改(b,g,r)的值,更改画笔的颜色,b=蓝色,g=绿色,r=红色。

  • flags:绘图功能的标识设置

特征点匹配如何做到图片拼接

这个问题我也很疑惑之后再写

图片拼接作业代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#coding: utf-8
import numpy as np
import cv2

'''
参考链接 https://blog.csdn.net/qq878594585/article/details/81901703
'''

leftgray = cv2.imread('src2.jpg')
rightgray = cv2.imread('src1.jpg')

hessian=400
surf = cv2.xfeatures2d.SURF_create(hessian)
#surf=cv2.SURF(hessian) #将Hessian Threshold设置为400,阈值越大能检测的特征就越少
kp1,des1=surf.detectAndCompute(leftgray,None) #查找关键点和描述符
kp2,des2=surf.detectAndCompute(rightgray,None)


FLANN_INDEX_KDTREE=0 #建立FLANN匹配器的参数
indexParams=dict(algorithm=FLANN_INDEX_KDTREE,trees=5) #配置索引,密度树的数量为5
searchParams=dict(checks=50) #指定递归次数
#FlannBasedMatcher:是目前最快的特征匹配算法(最近邻搜索)
flann=cv2.FlannBasedMatcher(indexParams,searchParams) #建立匹配器
matches=flann.knnMatch(des1,des2,k=2) #得出匹配的关键点

good=[]
#提取优秀的特征点
for m,n in matches:
if m.distance < 0.7*n.distance: #如果第一个邻近距离比第二个邻近距离的0.7倍小,则保留
good.append(m)
src_pts = np.array([ kp1[m.queryIdx].pt for m in good]) #查询图像的特征描述子索引
dst_pts = np.array([ kp2[m.trainIdx].pt for m in good]) #训练(模板)图像的特征描述子索引
H=cv2.findHomography(src_pts,dst_pts) #生成变换矩阵
h,w=leftgray.shape[:2]
h1,w1=rightgray.shape[:2]
shft=np.array([[1.0,0,w],[0,1.0,0],[0,0,1.0]])
M=np.dot(shft,H[0]) #获取左边图像到右边图像的投影映射关系
dst_corners=cv2.warpPerspective(leftgray,M,(w*2,h))#透视变换,新图像可容纳完整的两幅图
cv2.imshow('tiledImg1',dst_corners) #显示,第一幅图已在标准位置
dst_corners[0:h,w:w*2]=rightgray #将第二幅图放在右侧
cv2.imwrite('tiled.jpg',dst_corners)
cv2.imshow('tiledImg',dst_corners)
cv2.imshow('leftgray',leftgray)
cv2.imshow('rightgray',rightgray)
cv2.waitKey()
cv2.destroyAllWindows()

原来博主的代码出了一点小问题,估计是复制粘贴的时候出的错。修改了一下可以运行,效果如下:

参考

特征匹配