Opencv实战——图像拼接

人工智能168

文章目录

前言

图像拼接(Image Stitching)是一种利用实景图像组成全景空间的技术,它将多幅图像拼接成一幅大尺度图像或360度全景图,接可以看做是场景重建的一种特殊情况,其中图像仅通过平面单应性进行关联。图像拼接在运动检测和跟踪,增强现实,分辨率增强,视频压缩和图像稳定等机器视觉领域有很大的应用。
图像拼接的输出是两个输入图像的并集。通常用到四个步骤:
特征提取(Feature Extraction):检测输入图像中的特征点。

图像配准(Image Registration):建立了图像之间的几何对应关系,使它们可以在一个共同的参照系中进行变换、比较和分析。

图像变形(Warping):图像变形是指将其中一幅图像的图像重投影,并将图像放置在更大的画布上。

图像融合(Blending):图像融合是通过改变边界附近的图像灰度级,去除这些缝隙,创建混合图像,从而在图像之间实现平滑过渡。混合模式(Blend modes)用于将两层融合到一起。

实现方法

1、用SIFT提取图像中的特征点,并对每个关键点周围的区域计算特征向量。可以使用比SIFT快的SURF方法,但是我的opencv版本为最新版,不知道是专利的原因还是什么原因用SURF = cv2.xfeatures2D.SURF_create ()实例化的时候会报错,网上说可以退opencv版本,但是我这里没有尝试,就用了sift = cv2.SIFT_create()。
2、在分别提取好了两张图片的关键点和特征向量以后,可以利用它们进行两张图片的匹配。在拼接图片中,可以使用Knn进行匹配,但是使用FLANN快速匹配库更快,图片拼接,需要用到FLANN的单应性匹配。
3、单应性匹配完之后可以获得透视变换H矩阵,用这个的逆矩阵来对第二幅图片进行透视变换,将其转到和第一张图一样的视角,为下一步拼接做准备。
4、透视变化完后就可以直接拼接图片了,将图片通过numpy直接加到透视变化完成的图像的左边,覆盖掉重合的部分,得到拼接图片,但是这样拼接得图片中间会有一条很明显的缝隙,可以通过加权平均法,界线的两侧各取一定的比例来融合缝隙,速度快,但不自然。或者羽化法,或者拉普拉斯金字塔融合,效果最好。在这里用的是加权平均法,可以把第一张图叠在左边,但是对第一张图和它的重叠区做一些加权处理,重叠部分,离左边图近的,左边图的权重就高一些,离右边近的,右边旋转图的权重就高一些,然后两者相加,使得过渡是平滑地,这样看上去效果好一些,速度就比较慢。

实现代码

先给出原图
Opencv实战——图像拼接
Opencv实战——图像拼接

; 直接拼接


import cv2
import numpy as np
import sys
from PIL import Image

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

ima = cv2.imread("you.jpg")
imb = cv2.imread("zuo.jpg")
A = ima.copy()
B = imb.copy()
imageA = cv2.resize(A,(0,0),fx=0.2,fy=0.2)
imageB = cv2.resize(B,(0,0),fx=0.2,fy=0.2)

def detectAndDescribe(image):

    sift = cv2.SIFT_create()

    (kps, features) = sift.detectAndCompute(image, None)

    kps = np.float32([kp.pt for kp in kps])

    return (kps, features)

kpsA, featuresA = detectAndDescribe(imageA)
kpsB, featuresB = detectAndDescribe(imageB)

bf = cv2.BFMatcher()

matches = bf.knnMatch(featuresA, featuresB, 2)
good = []
for m in matches:

    if len(m) == 2 and m[0].distance < m[1].distance * 0.75:

        good.append((m[0].trainIdx, m[0].queryIdx))

if len(good) > 4:

    ptsA = np.float32([kpsA[i] for (_, i) in good])
    ptsB = np.float32([kpsB[i] for (i, _) in good])

    H, status = cv2.findHomography(ptsA, ptsB, cv2.RANSAC,4.0)

M = (matches, H, status)

if M is None:
    print("无匹配结果")
    sys.exit()

(matches, H, status) = M

result = cv2.warpPerspective(imageA, H, (imageA.shape[1] + imageB.shape[1], imageA.shape[0]))

result[0:imageB.shape[0], 0:imageB.shape[1]] = imageB
show('res',result)
print(result.shape)

效果:
Opencv实战——图像拼接
可以发现直接拼接虽然可以拼接但是在拼接的地方会有一条很明显的缝隙,不过直接拼接的速度比较快只用了2点多秒。

加权处理

我们通常使用alpha因子,通常称为alpha通道,它在中心像素处的值为1,在与边界像素线性递减后变为0。当输出拼接图像中至少有两幅重叠图像时,我们将使用如下的alpha值来计算其中一个像素处的颜色:假设两个图像,在输出图像中重叠;每个像素点在图像,其中(R,G,B)是像素的颜色值,我们将在缝合后的输出图像中计算(x, y)的像素值:
代码如下:

import cv2
import numpy as np
from matplotlib import pyplot as plt
import time
def show(name,img):
    cv2.imshow(name, img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
MIN = 10
FLANN_INDEX_KDTREE = 0
starttime = time.time()
img1 = cv2.imread('zuo.jpg')
img2 = cv2.imread('you.jpg')
imageA = cv2.resize(img1,(0,0),fx=0.2,fy=0.2)
imageB = cv2.resize(img2,(0,0),fx=0.2,fy=0.2)
surf=cv2.xfeatures2d.SIFT_create()

kp1,descrip1 = sift.detectAndCompute(imageA,None)
kp2,descrip2 = sift.detectAndCompute(imageB,None)

indexParams = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
searchParams = dict(checks=50)
flann=cv2.FlannBasedMatcher(indexParams,searchParams)
match=flann.knnMatch(descrip1,descrip2,k=2)
good=[]

for i,(m,n) in enumerate(match):
    if(m.distance<0.75*n.distance):
        good.append(m)

if len(good) > MIN:
    src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1,1,2)
    ano_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1,1,2)
    M,mask = cv2.findHomography(src_pts,ano_pts,cv2.RANSAC,5.0)
    warpImg = cv2.warpPerspective(imageB, np.linalg.inv(M), (imageA.shape[1]+imageB.shape[1], imageB.shape[0]))
    direct=warpImg.copy()
    direct[0:imageA.shape[0], 0:imageB.shape[1]] =imageA
    simple=time.time()

show('res',warpImg)
rows,cols=imageA.shape[:2]
print(rows)
print(cols)
for col in range(0,cols):

    if imageA[:, col].any() and warpImg[:, col].any():
        left = col
        print(left)
        break

for col in range(cols-1, 0, -1):

    if imageA[:, col].any() and warpImg[:, col].any():
        right = col
        print(right)
        break

res = np.zeros([rows, cols, 3], np.uint8)
for row in range(0, rows):
    for col in range(0, cols):
        if not imageA[row, col].any():
            res[row, col] = warpImg[row, col]
        elif not warpImg[row, col].any():
            res[row, col] = imageA[row, col]
        else:
            srcImgLen = float(abs(col - left))
            testImgLen = float(abs(col - right))
            alpha = srcImgLen / (srcImgLen + testImgLen)
            res[row, col] = np.clip(imageA[row, col] * (1 - alpha) + warpImg[row, col] * alpha, 0, 255)

warpImg[0:imageA.shape[0], 0:imageA.shape[1]]=res
show('res',warpImg)
final=time.time()
print(final-starttime)

效果:
Opencv实战——图像拼接
可以发现经过加权处理融合后的图片要比直接拼接效果要好,但是时间用了差不多16秒,而且还是有一条黑缝,目前还没有找到解决的办法,有好方法的友友们可以在评论区留意哟。

总结

除了加权处理的方法外,还可以尝试用羽化和拉普拉斯金字塔等方法来实现图像拼接,这里给出实现的原理,方便以后尝试。
羽化(原文连接):
加载原始图像并找到轮廓。

模糊原始图像并将其保存在不同的变量中。

创建一个空的蒙版并在其上绘制检测到的轮廓。

使用 np.where() 方法从要模糊值的蒙版(轮廓)中选择像素,然后替换它。

拉普拉斯金字塔(原文连接);

Original: https://blog.csdn.net/Thousand_drive/article/details/125084810
Author: 纸箱里的猫咪
Title: Opencv实战——图像拼接



相关阅读

Title: win10/win11系统下安装tensorflow-GPU版本

win10/win11系统下安装tensorflow-GPU版本

使用前注意

GPU版本

GPU版的tensorflow在调用的时候有加速效果,运行会比较快一些,当然,如果你的硬件没有GPU,只能使用CPU版本的tensorflow,就不需要安装CUDA和cuDNN,直接运行

pip install tensorflow

即可。

版本匹配!!!

tensorflowGPU版本对python、cuda和cuDNN的版本之间的匹配要求是非常高的,如果版本不匹配很有可能出现运行报错的情况。建议在使用和安装tensorflow之前查询官方文档,确定版本关系。
版本对应关系见网站:
链接: https://tensorflow.google.cn/install/source_windows.

cuda版本

使用控制面板 ,找到NVIDIA控制面板
Opencv实战——图像拼接
点击左下角《系统信息》,出现如下界面:
Opencv实战——图像拼接
切换至《组件》,呈现如下:
Opencv实战——图像拼接
可以看到,我的电脑CUDA的版本为11.2版本。

; 安装anaconda

Anaconda的安装和CUDA系列安装并无必须的匹配关系,可以自行搜索教程安装。

安装对应版本的CUDAtoolkit

NVIDIA控制面板显示我的CUDA为11.2版本,因此进入到anaconda prompt下(也可以在conda提供的虚拟环境下)采用如下命令安装

conda install cudatoolkit=11.2

意外的是,在我安装的时候(2022.1.29),国内的镜像源还没有出现11.2版本的cuda去安装,这里我便采用了官网去下载cuda安装包。
官网下载cuda: https://developer.nvidia.com/cuda-toolkit-archive.

进入后,找到你想下载的版本,下载好安装包之后,双击,之后根据提示完成安装即可,在这里一定要记下来CUDAtoolkit的安装路径!。

安装对应版本的cuDNN

根据之前的查询结果,cuda11.2版本最好对应cuDNN8.1版本,不幸的是,镜像源依旧没有该版本的cuDNN供下载,否则,你可以使用

conda install cuDNN=8.1

进行安装。

为了解决这一问题,可以去官网进行下载cuDNN包,
cuDNN官网:https://developer.nvidia.com/rdp/cudnn-archive.

这里比较麻烦的一点是:下载cuDNN必须注册NVIDIA账号!

从官网下载的cuDNN实际上只有一个压缩包,解压之后会发现:
Opencv实战——图像拼接

这时候,只需要将bin里面的所有文件复制到CUDAtoolkit的bin路径下,如下图:
Opencv实战——图像拼接
然后将cuDNN下的include里面的所有文件复制到CUDAtoolkit的include的路径下,如下图:
Opencv实战——图像拼接

将cuDNN下的lib里面的所有文件复制到CUDAtoolkit的lib路径下:
Opencv实战——图像拼接

到这里cuDNN就算安装完成了。

; 安装tensorflow

实际上安装tensorflow并不难,只要运行

pip install tensorflow-GPU

会自动安装。

最后,运行

pip list

查看你安装的tensorflow版本号是多少,是否和你的CUDA/cuDNN匹配。

总结

安装tensotflow-GPU最要紧的就是注意你要需要的版本是什么,你安装的版本是什么!
祝顺利!

Original: https://blog.csdn.net/xlxlqqq/article/details/122747988
Author: xlxlqqq
Title: win10/win11系统下安装tensorflow-GPU版本