最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

GitHub

互联网 admin 31浏览 0评论

GitHub

Image-Stitching

学习源码来自Github-pavanpn/Image-Stitching


主要函数:

1. cv2.cvtColor()  颜色空间转换函数
img_yuv=cv2.cvtColor(img,k) # img是需要转换对图片,k是转换成何种格式
# cv2.COLOR_BGR2RGB 将BGR格式转换成RGB格式
# cv2.COLOR_BGR2GRAY 将BGR格式转换成灰度图片

2. cv2.equalizeHist()   直方图均衡化函数
cv2.equalizeHist(img) # 将要均衡化的原图像[要求是灰度图像]作为参数传入,则返回值即为均衡化后的图像
3. bf=cv2.BFMatcher()、matches=bf.knnMatch()   K-最邻近匹配
# 暴力匹配BFMatcher,遍历描述符,确定描述符是否匹配,然后计算匹配距离并排序
# BFMatcher函数参数:
# normType:NORM_L1, NORM_L2, NORM_HAMMING, NORM_HAMMING2。
# NORM_L1和NORM_L2是SIFT和SURF描述符的优先选择
# NORM_HAMMING和NORM_HAMMING2是用于ORB算法
bf = cv2.BFMatcher(normType=cv2.NORM_HAMMING, crossCheck=True)
matches = bf.knnMatch(d1, d2, k=1) #获得knn检测器,d1,d2为描述子
# knn匹配可以返回k个最佳的匹配项,bf返回所有的匹配项
4. cv2.findHomography()   单应矩阵发现函数
M,mask=cv2.findHomography(img1_pts,img2_pts,cv2.RANSAC,5.0) 
# img1_pts 目标图像的特征点集合
# 第三个参数 配准方法的选择
# 第四个参数 每次抽取样本的个数,仅RANSAC和RHO有
5. cv2.perspectiveTransform()   透视变换函数
cv2.perspectiveTransform(src, m[, dst]) → dst
# src:输入的2通道或者3通道的图片
# m:变换矩阵
6. np.concatenate()
result_dims=np.concatenate((img1_dims,img2_dims),axis=0) 
# 前两个参数为要拼接对数组
# axis参数为指定按照哪个维度进行拼接,axis=0则代表着按照第一维度进行拼接


上述两个数组不能按行拼接(axis不能为0),因为第二维度尺寸不同。

7. cv2.warpPerspective()
cv2.warpPespective(imageA, H, (imageA.shape[1] + imageB.shape[1], imageA.shape[0]))  # 获得根据单应性矩阵变化后的图像
# image表示输入图像,H表示单应性的矩阵,(imageA.shape[1] + imageB.shape[1], imageA.shape[0])表示矩阵变化后的维度
8. sift.detectAndComputer()
sift.detectAndComputer(gray, None) # 计算出图像的关键点和sift特征向量,gray表示输入的图片
9. np.reshape()
numpy.reshape(a, newshape, order='C')
# a 需要reshape的array,可以看成是对数组的扩展,但是不影响原始数组
# 关于newshape参数
np.reshape(m,n) # 返回一个m行n列的数组
np.reshape(-1) # 返回一个一维数组
np.reshape(-1,n) # 返回一个n列的数组,行数自动给定
np.reshape(k,n,m) # 创建一个三维 (k个n*m)的数组
np.reshape(p,k,n,m) # 四维 p个(k,n,m)# order: 可选为(C, F, A)
C: 按照行来填充
F: 按照列的顺序来填充
A: 按任意方向,默认,这里相当于行
arr=np.array([1,2,3,4,5,6,7,8,9,10,11,12])
m=arr.reshape(3,4)
print(m)>>
[[ 1  2  3  4][ 5  6  7  8][ 9 10 11 12]]m=arr.reshape(3,2,2)>>
[[[ 1  2][ 3  4]][[ 5  6][ 7  8]][[ 9 10][11 12]]]m=arr.reshape(2,3,1,2)>>
[[[[ 1  2]][[ 3  4]][[ 5  6]]][[[ 7  8]][[ 9 10]][[11 12]]]]

当newshape参数大于2个的时候,pylint就开始报参数过多的错 ?

官方文档


步骤:

  1. 读入图像,
  2. 用SIFT/SURF/FAST/ORB提取每张图的特征点 和 每个特征点对应的描述子
  3. 通过匹配特征点描述子,找到两张图中匹配的特征点对(这里可能存在错误匹配)
  4. 使用RANSAC算法剔除错误匹配
  5. 求解方程组,计算Homograph单应性变换矩阵
  6. 通过Homograph单应性变换矩阵对其中一张图片进行仿射变换
  7. 拼接图片

1.彩色图像的直方图均衡化

直方图均衡化就是对图像进行非线性拉伸,重新分配图像像素值,使一定灰度范围内的像素数量大致相同。

中心思想:原始图像的灰度直方图从比较集中的某个灰度区间变成在全部灰度范围内均匀分布
def equalize_histogram_color(img):img_yuv=cv2.cvtColor(img,cv2.COLOR_BGR2YUV)img_yuv[:,:,0] = cv2.equalizeHist(img_yuv[:,:,0])img = cv2.cvtColor(img_yuv,cv2.COLOR_YUV2BGR)return img

为什么要做直方图均衡化?

一副高质量的图像的像素值分布应该很广泛,所以应该把它的直方图做一个横向拉伸,这就是直方图均衡化要做的事情。通常情况下这种操作会改善图像的对比度

2.特征点匹配和计算单应矩阵

def get_sift_homography(img1, img2):#特征提取# 初始化SIFTsift=cv2.xfeatures2d.SIFT_create() # 修改点 版本原因#提取关键点和描述子k1,d1=sift.detectAndCompute(img1,None) # k1存储提取的特征点,d1存储对应的描述子k2,d2=sift.detectAndCompute(img2,None)#图片匹配# 描述子计算:k-最邻近匹配bf=cv2.BFMatcher()matches=bf.knnMatch(d1,d2, k=2)# 获得理想匹配verify_ratio=0.8 # Source: stackoverflowverified_matches=[]for m1,m2 in matches:# 只加入理想匹配if m1.distance<0.8*m2.distance:verified_matches.append(m1)# 最少匹配数min_matches=8if len(verified_matches)>min_matches:# 存储匹配点img1_pts=[]img2_pts=[]# 把匹配点加进去for match in verified_matches:img1_pts.append(k1[match.queryIdx].pt)img2_pts.append(k2[match.trainIdx].pt)img1_pts=np.float32(img1_pts).reshape(-1,1,2)img2_pts=np.float32(img2_pts).reshape(-1,1,2)# 计算单应矩阵M,掩模 mark,使用了RANSAC算法剔初错误匹配M,mask=cv2.findHomography(img1_pts,img2_pts,cv2.RANSAC,5.0) return Melse: # 如果不够最小匹配数print('Error: Not enough matches')exit()

3.拼接图片

# 使用关键点来拼接图片
def get_stitched_image(img1,img2,M):# 获得输入图片的宽、高w1,h1=img1.shape[:2]w2,h2=img2.shape[:2]# 获得图像维度img1_dims=np.float32([[0,0],[0,w1],[h1,w1],[h1,0]]).reshape(-1,1,2)img2_dims_temp=np.float32([[0,0],[0,w2],[h2,w2],[h2,0]]).reshape(-1,1,2)# 获取第二幅图像的相对透视图img2_dims=cv2.perspectiveTransform(img2_dims_temp,M) # 执行矢量的透视矩阵变换# 得到结果图片的维度result_dims=np.concatenate((img1_dims,img2_dims),axis=0)# 拼接图像# 计算匹配点的维度[x_min,y_min]=np.int32(result_dims.min(axis=0).ravel()-0.5)[x_max,y_max]=np.int32(result_dims.max(axis=0).ravel()+0.5)# 仿射变换后创建输出数组transform_dist=[-x_min,-y_min]transform_array=np.array([[1, 0, transform_dist[0]], [0, 1, transform_dist[1]], [0,0,1]]) # 扭曲图像以用于拼接result_img=cv2.warpPerspective(img2,transform_array.dot(M), (x_max-x_min,y_max-y_min))result_img[transform_dist[1]:w1+transform_dist[1], transform_dist[0]:h1+transform_dist[0]]=img1# Return the resultreturn result_img

参考链接:Python+OpenCV实现图像的全景拼接


几个修改点

1. >83 print后需要带括号输出 版本原因
2. >45 module ‘cv2’ has no attribute ‘SIFT’ 版本原因

3.4.2版本中,openCV将SIFT等算法整合到xfeatures2d集合里面了

sift=cv2.SIFT()变成sift=cv2.xfeatures2d.SIFT_create()

3. >97 98 关于读入图像cv2.imread()函数的使用
# 一直越界报错 (可能是我环境下的命令行参数没有配置好)
img1 = cv2.imread(sys.argv[1]) 
img2 = cv2.imread(sys.argv[2])

需要修改成路径形式

注意:

1.路径形式不支持 单右斜线形式,可以支持 双右斜线、双左斜线、单左斜线形式、混合形式

#include<opencv2\opencv.hpp>
using namespace cv;
int main(int argc,char* argv[])
{Mat img;//-- 1 --双右斜线法//string imgpath = "C:\\Users\\bingbuyu\\Pictures\\photo\\miao1.jpg";//-- 2 --双左斜线法//string imgpath = "C://Users//bingbuyu//Pictures//photo//miao1.jpg";//-- 3 --单左斜线法//string imgpath = "C:/Users/bingbuyu/Pictures/photo/miao1.jpg";//-- 4 --以上三种混合法//string imgpath = "C:/Users//bingbuyu\\Pictures//photo//miao1.jpg";//-- 5 --相对路径法//string imgpath = "miao.jpg";//-- 6 --命令行参数法string imgpath = argv[1];img = imread(imgpath, 1);imshow("img", img);waitKey(0);return 0;
}

参考链接:使用imread()函数读取图片的六种正确姿势

2.命令行参数法
Python中 sys.argv[]的用法简明解释

4. >115 写入时,同样是由sys.argv[]引起的越界错误,写入时需要带后缀名写入


不能为imwrite()找到特定扩展名的writer,因为result_image_name必须是.png.jpg.bmg,改成带后缀的即可。


虽然能跑出来,但是有个报错没整明白是因为多于了2个newshape参数,变三维、四维数组的时候就会报这个,但还是可以用


方法调用的位置参数过多?reshape()


完整代码:

import sys
import cv2
import numpy as np
# Use the keypoints to stitch the images
def get_stitched_image(img1,img2,M):# Get width and height of input images	w1,h1=img1.shape[:2]w2,h2=img2.shape[:2]# Get the canvas dimesionsimg1_dims=np.float32([[0,0],[0,w1],[h1,w1],[h1,0]]).reshape(-1,1,2)img2_dims_temp=np.float32([[0,0],[0,w2],[h2,w2],[h2,0]]).reshape(-1,1,2)# Get relative perspective of second imageimg2_dims=cv2.perspectiveTransform(img2_dims_temp,M)# Resulting dimensionsresult_dims=np.concatenate((img1_dims,img2_dims),axis=0)# Getting images together# Calculate dimensions of match points[x_min,y_min]=np.int32(result_dims.min(axis=0).ravel()-0.5)[x_max,y_max]=np.int32(result_dims.max(axis=0).ravel()+0.5)# Create output array after affine transformation transform_dist=[-x_min,-y_min]transform_array=np.array([[1, 0, transform_dist[0]], [0, 1, transform_dist[1]], [0,0,1]]) # Warp images to get the resulting imageresult_img=cv2.warpPerspective(img2,transform_array.dot(M), (x_max-x_min,y_max-y_min))result_img[transform_dist[1]:w1+transform_dist[1], transform_dist[0]:h1+transform_dist[0]]=img1# Return the resultreturn result_img# Find SIFT and return Homography Matrix
def get_sift_homography(img1, img2):# Initialize SIFT sift=cv2.xfeatures2d.SIFT_create() #修改点 版本原因# Extract keypoints and descriptorsk1,d1=sift.detectAndCompute(img1,None)k2,d2=sift.detectAndCompute(img2,None)# Bruteforce matcher on the descriptorsbf=cv2.BFMatcher()matches=bf.knnMatch(d1,d2, k=2)# Make sure that the matches are goodverify_ratio=0.8 # Source: stackoverflowverified_matches=[]for m1,m2 in matches:# Add to array only if it's a good matchif m1.distance<0.8*m2.distance:verified_matches.append(m1)# Mimnum number of matchesmin_matches=8if len(verified_matches)>min_matches:# Array to store matching pointsimg1_pts=[]img2_pts=[]# Add matching points to arrayfor match in verified_matches:img1_pts.append(k1[match.queryIdx].pt)img2_pts.append(k2[match.trainIdx].pt)img1_pts=np.float32(img1_pts).reshape(-1,1,2)img2_pts=np.float32(img2_pts).reshape(-1,1,2)# Compute homography matrixM,mask=cv2.findHomography(img1_pts,img2_pts,cv2.RANSAC,5.0)return Melse:print('Error: Not enough matches')exit()# Equalize Histogram of Color Images
def equalize_histogram_color(img):img_yuv=cv2.cvtColor(img,cv2.COLOR_BGR2YUV)img_yuv[:,:,0] = cv2.equalizeHist(img_yuv[:,:,0])img = cv2.cvtColor(img_yuv,cv2.COLOR_YUV2BGR)return img# Main function definition
def main():# Get input set of imagesimg1=cv2.imread("/Applications/code/test/01_suburbA.jpg") #修改点img2=cv2.imread("/Applications/code/test/01_suburbB.jpg")# Equalize histogramimg1=equalize_histogram_color(img1)img2=equalize_histogram_color(img2)# Show input imagesinput_images=np.hstack((img1,img2))cv2.imshow('Input Images',input_images)# Use SIFT to find keypoints and return homography matrixM=get_sift_homography(img1, img2)# Stitch the images together using homography matrixresult_image=get_stitched_image(img2,img1,M)# Write the result to the same directoryresult_image_name='result.jpg'           #需要带后缀写入cv2.imwrite(result_image_name,result_image)# Show the resulting imagecv2.imshow('Result',result_image)cv2.waitKey()# Call main function
if __name__=='__main__':main()

GitHub

Image-Stitching

学习源码来自Github-pavanpn/Image-Stitching


主要函数:

1. cv2.cvtColor()  颜色空间转换函数
img_yuv=cv2.cvtColor(img,k) # img是需要转换对图片,k是转换成何种格式
# cv2.COLOR_BGR2RGB 将BGR格式转换成RGB格式
# cv2.COLOR_BGR2GRAY 将BGR格式转换成灰度图片

2. cv2.equalizeHist()   直方图均衡化函数
cv2.equalizeHist(img) # 将要均衡化的原图像[要求是灰度图像]作为参数传入,则返回值即为均衡化后的图像
3. bf=cv2.BFMatcher()、matches=bf.knnMatch()   K-最邻近匹配
# 暴力匹配BFMatcher,遍历描述符,确定描述符是否匹配,然后计算匹配距离并排序
# BFMatcher函数参数:
# normType:NORM_L1, NORM_L2, NORM_HAMMING, NORM_HAMMING2。
# NORM_L1和NORM_L2是SIFT和SURF描述符的优先选择
# NORM_HAMMING和NORM_HAMMING2是用于ORB算法
bf = cv2.BFMatcher(normType=cv2.NORM_HAMMING, crossCheck=True)
matches = bf.knnMatch(d1, d2, k=1) #获得knn检测器,d1,d2为描述子
# knn匹配可以返回k个最佳的匹配项,bf返回所有的匹配项
4. cv2.findHomography()   单应矩阵发现函数
M,mask=cv2.findHomography(img1_pts,img2_pts,cv2.RANSAC,5.0) 
# img1_pts 目标图像的特征点集合
# 第三个参数 配准方法的选择
# 第四个参数 每次抽取样本的个数,仅RANSAC和RHO有
5. cv2.perspectiveTransform()   透视变换函数
cv2.perspectiveTransform(src, m[, dst]) → dst
# src:输入的2通道或者3通道的图片
# m:变换矩阵
6. np.concatenate()
result_dims=np.concatenate((img1_dims,img2_dims),axis=0) 
# 前两个参数为要拼接对数组
# axis参数为指定按照哪个维度进行拼接,axis=0则代表着按照第一维度进行拼接


上述两个数组不能按行拼接(axis不能为0),因为第二维度尺寸不同。

7. cv2.warpPerspective()
cv2.warpPespective(imageA, H, (imageA.shape[1] + imageB.shape[1], imageA.shape[0]))  # 获得根据单应性矩阵变化后的图像
# image表示输入图像,H表示单应性的矩阵,(imageA.shape[1] + imageB.shape[1], imageA.shape[0])表示矩阵变化后的维度
8. sift.detectAndComputer()
sift.detectAndComputer(gray, None) # 计算出图像的关键点和sift特征向量,gray表示输入的图片
9. np.reshape()
numpy.reshape(a, newshape, order='C')
# a 需要reshape的array,可以看成是对数组的扩展,但是不影响原始数组
# 关于newshape参数
np.reshape(m,n) # 返回一个m行n列的数组
np.reshape(-1) # 返回一个一维数组
np.reshape(-1,n) # 返回一个n列的数组,行数自动给定
np.reshape(k,n,m) # 创建一个三维 (k个n*m)的数组
np.reshape(p,k,n,m) # 四维 p个(k,n,m)# order: 可选为(C, F, A)
C: 按照行来填充
F: 按照列的顺序来填充
A: 按任意方向,默认,这里相当于行
arr=np.array([1,2,3,4,5,6,7,8,9,10,11,12])
m=arr.reshape(3,4)
print(m)>>
[[ 1  2  3  4][ 5  6  7  8][ 9 10 11 12]]m=arr.reshape(3,2,2)>>
[[[ 1  2][ 3  4]][[ 5  6][ 7  8]][[ 9 10][11 12]]]m=arr.reshape(2,3,1,2)>>
[[[[ 1  2]][[ 3  4]][[ 5  6]]][[[ 7  8]][[ 9 10]][[11 12]]]]

当newshape参数大于2个的时候,pylint就开始报参数过多的错 ?

官方文档


步骤:

  1. 读入图像,
  2. 用SIFT/SURF/FAST/ORB提取每张图的特征点 和 每个特征点对应的描述子
  3. 通过匹配特征点描述子,找到两张图中匹配的特征点对(这里可能存在错误匹配)
  4. 使用RANSAC算法剔除错误匹配
  5. 求解方程组,计算Homograph单应性变换矩阵
  6. 通过Homograph单应性变换矩阵对其中一张图片进行仿射变换
  7. 拼接图片

1.彩色图像的直方图均衡化

直方图均衡化就是对图像进行非线性拉伸,重新分配图像像素值,使一定灰度范围内的像素数量大致相同。

中心思想:原始图像的灰度直方图从比较集中的某个灰度区间变成在全部灰度范围内均匀分布
def equalize_histogram_color(img):img_yuv=cv2.cvtColor(img,cv2.COLOR_BGR2YUV)img_yuv[:,:,0] = cv2.equalizeHist(img_yuv[:,:,0])img = cv2.cvtColor(img_yuv,cv2.COLOR_YUV2BGR)return img

为什么要做直方图均衡化?

一副高质量的图像的像素值分布应该很广泛,所以应该把它的直方图做一个横向拉伸,这就是直方图均衡化要做的事情。通常情况下这种操作会改善图像的对比度

2.特征点匹配和计算单应矩阵

def get_sift_homography(img1, img2):#特征提取# 初始化SIFTsift=cv2.xfeatures2d.SIFT_create() # 修改点 版本原因#提取关键点和描述子k1,d1=sift.detectAndCompute(img1,None) # k1存储提取的特征点,d1存储对应的描述子k2,d2=sift.detectAndCompute(img2,None)#图片匹配# 描述子计算:k-最邻近匹配bf=cv2.BFMatcher()matches=bf.knnMatch(d1,d2, k=2)# 获得理想匹配verify_ratio=0.8 # Source: stackoverflowverified_matches=[]for m1,m2 in matches:# 只加入理想匹配if m1.distance<0.8*m2.distance:verified_matches.append(m1)# 最少匹配数min_matches=8if len(verified_matches)>min_matches:# 存储匹配点img1_pts=[]img2_pts=[]# 把匹配点加进去for match in verified_matches:img1_pts.append(k1[match.queryIdx].pt)img2_pts.append(k2[match.trainIdx].pt)img1_pts=np.float32(img1_pts).reshape(-1,1,2)img2_pts=np.float32(img2_pts).reshape(-1,1,2)# 计算单应矩阵M,掩模 mark,使用了RANSAC算法剔初错误匹配M,mask=cv2.findHomography(img1_pts,img2_pts,cv2.RANSAC,5.0) return Melse: # 如果不够最小匹配数print('Error: Not enough matches')exit()

3.拼接图片

# 使用关键点来拼接图片
def get_stitched_image(img1,img2,M):# 获得输入图片的宽、高w1,h1=img1.shape[:2]w2,h2=img2.shape[:2]# 获得图像维度img1_dims=np.float32([[0,0],[0,w1],[h1,w1],[h1,0]]).reshape(-1,1,2)img2_dims_temp=np.float32([[0,0],[0,w2],[h2,w2],[h2,0]]).reshape(-1,1,2)# 获取第二幅图像的相对透视图img2_dims=cv2.perspectiveTransform(img2_dims_temp,M) # 执行矢量的透视矩阵变换# 得到结果图片的维度result_dims=np.concatenate((img1_dims,img2_dims),axis=0)# 拼接图像# 计算匹配点的维度[x_min,y_min]=np.int32(result_dims.min(axis=0).ravel()-0.5)[x_max,y_max]=np.int32(result_dims.max(axis=0).ravel()+0.5)# 仿射变换后创建输出数组transform_dist=[-x_min,-y_min]transform_array=np.array([[1, 0, transform_dist[0]], [0, 1, transform_dist[1]], [0,0,1]]) # 扭曲图像以用于拼接result_img=cv2.warpPerspective(img2,transform_array.dot(M), (x_max-x_min,y_max-y_min))result_img[transform_dist[1]:w1+transform_dist[1], transform_dist[0]:h1+transform_dist[0]]=img1# Return the resultreturn result_img

参考链接:Python+OpenCV实现图像的全景拼接


几个修改点

1. >83 print后需要带括号输出 版本原因
2. >45 module ‘cv2’ has no attribute ‘SIFT’ 版本原因

3.4.2版本中,openCV将SIFT等算法整合到xfeatures2d集合里面了

sift=cv2.SIFT()变成sift=cv2.xfeatures2d.SIFT_create()

3. >97 98 关于读入图像cv2.imread()函数的使用
# 一直越界报错 (可能是我环境下的命令行参数没有配置好)
img1 = cv2.imread(sys.argv[1]) 
img2 = cv2.imread(sys.argv[2])

需要修改成路径形式

注意:

1.路径形式不支持 单右斜线形式,可以支持 双右斜线、双左斜线、单左斜线形式、混合形式

#include<opencv2\opencv.hpp>
using namespace cv;
int main(int argc,char* argv[])
{Mat img;//-- 1 --双右斜线法//string imgpath = "C:\\Users\\bingbuyu\\Pictures\\photo\\miao1.jpg";//-- 2 --双左斜线法//string imgpath = "C://Users//bingbuyu//Pictures//photo//miao1.jpg";//-- 3 --单左斜线法//string imgpath = "C:/Users/bingbuyu/Pictures/photo/miao1.jpg";//-- 4 --以上三种混合法//string imgpath = "C:/Users//bingbuyu\\Pictures//photo//miao1.jpg";//-- 5 --相对路径法//string imgpath = "miao.jpg";//-- 6 --命令行参数法string imgpath = argv[1];img = imread(imgpath, 1);imshow("img", img);waitKey(0);return 0;
}

参考链接:使用imread()函数读取图片的六种正确姿势

2.命令行参数法
Python中 sys.argv[]的用法简明解释

4. >115 写入时,同样是由sys.argv[]引起的越界错误,写入时需要带后缀名写入


不能为imwrite()找到特定扩展名的writer,因为result_image_name必须是.png.jpg.bmg,改成带后缀的即可。


虽然能跑出来,但是有个报错没整明白是因为多于了2个newshape参数,变三维、四维数组的时候就会报这个,但还是可以用


方法调用的位置参数过多?reshape()


完整代码:

import sys
import cv2
import numpy as np
# Use the keypoints to stitch the images
def get_stitched_image(img1,img2,M):# Get width and height of input images	w1,h1=img1.shape[:2]w2,h2=img2.shape[:2]# Get the canvas dimesionsimg1_dims=np.float32([[0,0],[0,w1],[h1,w1],[h1,0]]).reshape(-1,1,2)img2_dims_temp=np.float32([[0,0],[0,w2],[h2,w2],[h2,0]]).reshape(-1,1,2)# Get relative perspective of second imageimg2_dims=cv2.perspectiveTransform(img2_dims_temp,M)# Resulting dimensionsresult_dims=np.concatenate((img1_dims,img2_dims),axis=0)# Getting images together# Calculate dimensions of match points[x_min,y_min]=np.int32(result_dims.min(axis=0).ravel()-0.5)[x_max,y_max]=np.int32(result_dims.max(axis=0).ravel()+0.5)# Create output array after affine transformation transform_dist=[-x_min,-y_min]transform_array=np.array([[1, 0, transform_dist[0]], [0, 1, transform_dist[1]], [0,0,1]]) # Warp images to get the resulting imageresult_img=cv2.warpPerspective(img2,transform_array.dot(M), (x_max-x_min,y_max-y_min))result_img[transform_dist[1]:w1+transform_dist[1], transform_dist[0]:h1+transform_dist[0]]=img1# Return the resultreturn result_img# Find SIFT and return Homography Matrix
def get_sift_homography(img1, img2):# Initialize SIFT sift=cv2.xfeatures2d.SIFT_create() #修改点 版本原因# Extract keypoints and descriptorsk1,d1=sift.detectAndCompute(img1,None)k2,d2=sift.detectAndCompute(img2,None)# Bruteforce matcher on the descriptorsbf=cv2.BFMatcher()matches=bf.knnMatch(d1,d2, k=2)# Make sure that the matches are goodverify_ratio=0.8 # Source: stackoverflowverified_matches=[]for m1,m2 in matches:# Add to array only if it's a good matchif m1.distance<0.8*m2.distance:verified_matches.append(m1)# Mimnum number of matchesmin_matches=8if len(verified_matches)>min_matches:# Array to store matching pointsimg1_pts=[]img2_pts=[]# Add matching points to arrayfor match in verified_matches:img1_pts.append(k1[match.queryIdx].pt)img2_pts.append(k2[match.trainIdx].pt)img1_pts=np.float32(img1_pts).reshape(-1,1,2)img2_pts=np.float32(img2_pts).reshape(-1,1,2)# Compute homography matrixM,mask=cv2.findHomography(img1_pts,img2_pts,cv2.RANSAC,5.0)return Melse:print('Error: Not enough matches')exit()# Equalize Histogram of Color Images
def equalize_histogram_color(img):img_yuv=cv2.cvtColor(img,cv2.COLOR_BGR2YUV)img_yuv[:,:,0] = cv2.equalizeHist(img_yuv[:,:,0])img = cv2.cvtColor(img_yuv,cv2.COLOR_YUV2BGR)return img# Main function definition
def main():# Get input set of imagesimg1=cv2.imread("/Applications/code/test/01_suburbA.jpg") #修改点img2=cv2.imread("/Applications/code/test/01_suburbB.jpg")# Equalize histogramimg1=equalize_histogram_color(img1)img2=equalize_histogram_color(img2)# Show input imagesinput_images=np.hstack((img1,img2))cv2.imshow('Input Images',input_images)# Use SIFT to find keypoints and return homography matrixM=get_sift_homography(img1, img2)# Stitch the images together using homography matrixresult_image=get_stitched_image(img2,img1,M)# Write the result to the same directoryresult_image_name='result.jpg'           #需要带后缀写入cv2.imwrite(result_image_name,result_image)# Show the resulting imagecv2.imshow('Result',result_image)cv2.waitKey()# Call main function
if __name__=='__main__':main()
发布评论

评论列表 (0)

  1. 暂无评论