opencv_图像查找和图像拼接

图像查找

通过特征匹配和单应性矩阵我们可以实现图像查找.

基本的原理是通过特征匹配得到匹配结果, 作为输入, 得到单应性矩阵, 再经过透视变换就能够找到最终的图像

单应性矩阵

单应性(Homography)变换 :可以简单的理解为它用来描述物体在世界坐标系和像素坐标系之间的位置映射关系。对应的变换矩阵称为单应性矩阵。
在这里插入图片描述

在这里插入图片描述

  • 单应性矩阵的应用

  • 把图片摆正

    在这里插入图片描述

  • 图片替换
    在这里插入图片描述

  • findHomography(srcPoints, dstPoints[, method[, ransacReprojThreshold[, mask[, maxIters[, confidence]]]]])

    • srcPoints: 源平面中点的坐标矩阵,可以是CV_32FC2类型,也可以是vector <Point2f>类型

    • dstPoints: 目标平面中点的坐标矩阵,可以是CV_32FC2类型,也可以是vector <Point2f>类型

    • method: 计算单应矩阵所使用的方法。不同的方法对应不同的参数,具体如下:

      • 0 - 利用所有点的常规方法
      • RANSAC - RANSAC-基于RANSAC的鲁棒算法
      • LMEDS - 最小中值鲁棒算法
      • PROSAC-基于PROSAC的鲁棒算法
    • ransacReprojThreshold: 将点对视为内点的最大允许重投影错误阈值(仅用于RANSAC和RHO方法)。若srcPoints和dstPoints是以像素为单位的,则该参数通常设置在1到10的范围内。

    • mask: 可选输出掩码矩阵,通常由鲁棒算法(RANSAC或LMEDS)设置。 请注意,输入掩码矩阵是不需要设置的。

    • maxIters: RANSAC算法的最大迭代次数,默认值为2000。

    • confidence: 可信度值,取值范围为0到1.

import cv2
import numpy as np

# 打开图片
img1 = cv2.imread('opencv_search.png')
img2 = cv2.imread('opencv_orig.png')

# 灰度化
g1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
g2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

#创建特征检测器
sift = cv2.SIFT_create()

# 计算特征点和描述子
kp1, des1 = sift.detectAndCompute(g1, None)
kp2, des2 = sift.detectAndCompute(g2, None)

# 创建特征匹配器
index_params = dict(algorithm=1, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)

# 对描述子进行特征匹配
matches = flann.knnMatch(des1, des2, k=2)

# 过滤match对象
goods = []
for (m, n) in matches:
    # 阈值一般设0.7到0.8之间.
    if m.distance < 0.75 * n.distance:
        goods.append(m)
        

# 通过goods把对应的特征点找到
# 因为计算单应性矩阵要求最少4个点
if len(goods) >= 4:
    # 找到对应的四个点
    src_points = np.float32([kp1[m.queryIdx].pt for m in goods]).reshape(-1, 1, 2)
    dst_points = np.float32([kp2[m.trainIdx].pt for m in goods]).reshape(-1, 1, 2)
    
    # 根据匹配上的关键点去计算单应性矩阵.
    H, _ = cv2.findHomography(src_points, dst_points, cv2.RANSAC, 5)
    
    # 通过单应性矩阵, 计算小图(img1)小图在大图中的对应位置.
    h, w = img1.shape[:2] # 小图的高和宽
    
    # 小图中的四个角点
    pts = np.float32([[0, 0], [0, h-1], [w-1, h-1], [w-1, 0]]).reshape(-1, 1, 2)
    
    # warpPerspective是对图片进行透视变换的.
    # 将小图中的四个角点,投射到大图中,找到大图中对应的四个点
    dst = cv2.perspectiveTransform(pts, H)
    print(dst)
    
    # 在大图中, 把dst区域框出来
    cv2.polylines(img2, [np.int32(dst)], True, (0, 0, 255), 2)
else:
    print('not enough point number to compute homography matrix')
    exit()

# 画出匹配的特征点
ret = cv2.drawMatchesKnn(img1, kp1, img2, kp2, [goods], None)
cv2.imshow('ret', ret)

cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.waitKey(1)
[[[ 97.57899  86.01002]]

 [[ 92.22688 435.28094]]

 [[471.19507 435.65234]]

 [[465.97748  85.17265]]]


-1

图像拼接

方法一

变换右图,使之适应左图

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

# 打开两个文件
img1 = cv2.imread('./map1.png')
img2 = cv2.imread('./map2.png')

# 灰度化
g1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
g2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)


# 创建SIFT特征检测器
sift = cv2.SIFT_create()

# 计算描述子与特征点
kp1, des1 = sift.detectAndCompute(g1, None)
kp2, des2 = sift.detectAndCompute(g2, None)

# 创建匹配器
index_params = dict(algorithm=1, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)

# 对描述子进行匹配计算
matchs = flann.knnMatch(des1, des2, k=2)

# 过滤match对象,选出合适的匹配点
good = []
for i, (m, n) in enumerate(matchs):
    if m.distance < 0.75 * n.distance:
        good.append(m)

if len(good) >= 10:
    # 找出两图对应的匹配点
    srcPts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
    dstPts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)

    # 查找单应性矩阵
    M, mask = cv2.findHomography(srcPts, dstPts, cv2.RANSAC, 5.0)

    # 利用M矩阵的逆 -- 将img2图变换,使之与img1匹配
    # 返回变换之后的图像,宽高得自己设定
    warpImg = cv2.warpPerspective(img2, np.linalg.inv(M), (img1.shape[1]+img2.shape[1], img2.shape[0]+6))  # 后面广播的时候高度会缺失6个像素
    
    warpImg[0:img1.shape[0], 0:img1.shape[1]] = img1  # 将左边img1的部分重新赋值

# 处理中间黑线问题.
# 经过仔细观察, 中间的黑线是左图自带的. 黑线在第743列的位置, 我们把这一列删掉
warpImg = np.hstack((warpImg[:, :742], warpImg[:, 744:]))

# 然后再对局部做一个高斯模糊.
temp = cv2.GaussianBlur(warpImg[:, 740:747], (5, 5), sigmaX=0)

# 替换
warpImg[:, 740:747] = temp

cv2.imshow('result', warpImg)

cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.waitKey(1)

-1

方法二

变换左图,使之适应右图

图像拼接的思路.

  1. 读图片
  2. 灰度化处理
  3. 计算各自的特征点和描述子
  4. 匹配特征.
  5. 根据匹配到的特征, 计算单应性矩阵.
  6. 对图片进行透视变换.
  7. 创建一个大图.
  8. 放入两张图.
import cv2 
import numpy as np

# 读图片
img1 = cv2.imread('left_01.png')
img2 = cv2.imread('right_01.png')

# 把两张图的尺寸设置成同样大小
img1 = cv2.resize(img1, (640, 480))
img2 = cv2.resize(img2, (640, 480))

# 灰度化处理
g1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
g2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

# 创建sift对象
sift = cv2.SIFT_create()

kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)


# 创建特征匹配器
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1, des2, k=2)

# 过滤match对象,使之更准确地匹配
goods = []
for m, n in matches:
    if m.distance < 0.75 * n.distance:
        goods.append(m)
        
if len(goods) >= 4:
    # 根据DMatch对象拿到各自的特征点
    src_points = np.float32([kp1[m.queryIdx].pt for m in goods]).reshape(-1, 1, 2)
    dst_points = np.float32([kp2[m.trainIdx].pt for m in goods]).reshape(-1, 1, 2)
    
    # 计算单应性矩阵
    # 第一个对变成第二个图的视角, 计算出来的单应性矩阵.
    H, _ = cv2.findHomography(src_points, dst_points, cv2.RANSAC, 5)
else:
    print('not enough point number to compute homography matrix')
    exit()
    

# 获取原始图的高和宽
h1, w1 = img1.shape[:2]
h2, w2 = img2.shape[:2]

# 获取两个图的角点
img1_pts = np.float32([[0, 0], [0, h1 - 1], [w1 - 1, h1 - 1], [w1 -1, 0]]).reshape(-1, 1, 2)
img2_pts = np.float32([[0, 0], [0, h2 - 1], [w2 - 1, h2 - 1], [w2 -1, 0]]).reshape(-1, 1, 2)

# 根据前面计算出来的H, 计算img1的四个角变换之后的坐标
img1_transform = cv2.perspectiveTransform(img1_pts, H)

# 计算合成图的大小
## 先获取角点坐标的最大值和最小值
result_pts = np.concatenate((img2_pts, img1_transform), axis=0)
[x_min, y_min] = np.int32(result_pts.min(axis=0).ravel() - 1)
[x_max, y_max] = np.int32(result_pts.max(axis=0).ravel() + 1)

# 手动构造平移矩阵:使img1的变换图像 移到显示区域
# 如果不平移, img1很大一部分都在显示窗口外面, 我们看不到.
move_matrix = np.array([[1, 0, -x_min],[0, 1, -y_min], [0, 0, 1]])

# 对img1进行平移后透视变换,并设置结果画面的大小
result_img = cv2.warpPerspective(img1, move_matrix.dot(H), (x_max -x_min, y_max - y_min))

# 把img2放进来
result_img[-y_min: -y_min + h2,-x_min: -x_min + w2] = img2

cv2.imshow('result_img', result_img)
cv2.waitKey(0) 
cv2.destroyAllWindows()
cv2.waitKey(1)
[[[   0.         0.     ]]

 [[   0.       479.     ]]

 [[ 639.       479.     ]]

 [[ 639.         0.     ]]

 [[-910.4307  -314.8995 ]]

 [[-885.33563  692.0095 ]]

 [[ 269.34866  428.4168 ]]

 [[ 289.10074   20.58108]]]



-1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
OpenCV(开源计算机视觉库)是一个开源计算机视觉和机器学习软件库。OpenCV的构建旨在为计算机视觉应用程序提供通用的基础结构,并加速在商业产品中使用机器感知。作为BSD许可的产品,OpenCV使企业可以轻松地使用和修改代码。 该库具有2500多种优化算法,其中包括一整套经典和最新的计算机视觉和机器学习算法。这些算法可用于检测和识别人脸,识别对象,对视频中的人为行为进行分类,跟踪摄像机的运动,跟踪运动的对象,提取对象的3D模型,从立体摄像机生成3D点云,将图像拼接在一起以产生高分辨率整个场景的图像,从图像数据库中查找相似的图像,从使用闪光灯拍摄的图像中消除红眼,跟随眼睛的运动,识别风景并建立标记以将其与增强现实叠加在一起等。OpenCV拥有超过4.7万人的用户社区,下载量估计超过1800万。该库在公司,研究小组和政府机构中得到广泛使用。 除了使用该库的Google,Yahoo,Microsoft,Intel,IBM,Sony,Honda,Toyota之类的知名公司外,还有许多应用创业公司,Applied Minds,VideoSurf和Zeitera等都在广泛使用OpenCVOpenCV的部署用途包括将街景图像拼接在一起,检测以色列监视视频中的入侵,监视中国的矿山设备,帮助机器人在Willow Garage导航和拾取物体,检测欧洲游泳池溺水事故,在西班牙和纽约,在土耳其检查跑道上的碎屑,检查世界各地工厂产品上的标签,然后在日本进行快速面部识别。 它具有C ++,Python,Java和MATLAB接口,并支持Windows,Linux,Android和Mac OS。OpenCV主要倾向于实时视觉应用,并在可用时利用MMX和SSE指令。 目前,正在积极开发功能齐全的CUDA和OpenCL接口。有500多种算法,而构成或支持这些算法的功能大约是其10倍。OpenCV用C ++原生编写,并具有可与STL容器无缝配合的模板化接口。
Part I 基础篇 OpenCV 开发基础. 1 第 1 章初识 OpenCV.. 3 1.1 OpenCV 初识 4 1.1.1 OpenCV 简介.. 4 1.1.2 OpenCV 组件及架构.. 5 1.1.3 OpenCV 资源.. 9 1.2 VS2012 安装OpenCV2.4.x .. 9 1.3 VS2013 安装OpenCV3.0 14 1.4 Sublime 下配置OpenCV. 16 1.5 小结 19 第2 章图像及视频基本操作. 20 2.1 图像初级操作 21 2.1.1 Mat 类 21 2.1.2 Mat 基本操作 23 2.1.3 Mat 类型转换 24 2.1.4 图像读取显示保存 24 2.1.5 图像存储. 26 2.2 图像几何变换 28 2.2.1 坐标映射. 28 2.2.2 平移 29 2.2.3 缩放 33 2.2.4 旋转 36 2.2.5 仿射变换. 40 2.3 视频操作.. 43 2.3.1 VideoCapture 类.. 43 2.3.2 视频写操作 45 2.3.3 视频质量评价.. 48 2.4 图像基础应用操作. 50 2.4.1 界面事件. 50 2.4.2 区域提取. 54 2.4.3 图像元素遍历——反色.. 58 2.4.4 单窗口显示多幅图像 63 2.4.5 图像颜色空间转换 66 2.4.6 图像批量读取——规则.. 69 2.4.7 图像批量读取——无规则. 70 2.5 小结 71 Part II 进阶篇图像处理技术.. 73 第 3 章进阶篇——图像灰度变换技术. 75 3.1 阈值化处理. 76 3.1.1 OTSU 阈值化 76 3.1.2 固定阈值化 79 3.1.3 自适应阈值化.. 81 3.1.4 双阈值化. 83 3.1.5 半阈值化. 84 3.2 直方图处理. 85 3.2.1 灰度直方图 85 3.2.2 H-S 直方图. 88 3.2.3 BGR 直方图.. 89 3.2.4 自定义直方图.. 91 3.2.5 灰度直方图均衡. 93 3.2.6 彩色直方图均衡. 94 3.2.7 直方图变换——查找 95 3.2.8 直方图变换——累计 97 3.2.9 直方图匹配 99 3.2.10 直方图对比.. 101 3.2.11 直方图的反向投影 105 3.3 距离变换 108 3.3.1 距离. 108 3.3.2 邻接性 109 3.3.3 区域..110 3.3.4 距离变换——扫描..110 3.3.5 距离变换——distanceTransform..113 3.4 Gamma 校正.115 3.5 其他常见的灰度变换技术117 3.5.1 线性变换117 3.5.2 对数变换119 3.5.3 对比度拉伸. 121 3.5.4 灰度级分层. 124 3.5.5 灰度比特平面 125 3.6 实例应用 128 3.6.1 最大熵阈值分割.. 128 3.6.2 投影峰谷查找 131 3.7 小结. 134 第4 章进阶篇——图像平滑技术.. 135 4.1 图像采样 136 4.1.1 最近邻插值. 136 4.1.2 双线性插值. 138 4.1.3 插值操作性能对比. 140 4.1.4 图像金字塔. 143 4.2 傅里叶变换.. 146 4.2.1 图像掩码操作 146 4.2.2 离散傅里叶. 149 4.2.3 图像卷积.. 151 4.3 图像噪声 153 4.3.1 椒盐噪声.. 153 4.3.2 高斯噪声.. 155 4.4 空间平滑 157 4.4.1 盒滤波 157 4.4.2 均值滤波.. 159 4.4.3 中值滤波.. 159 4.4.4 高斯滤波.. 161 4.4.5 双边滤波.. 163 4.5 实例应用 166 4.5.1 导向滤波.. 166 4.5.2 图像污点修复 169 4.5.3 旋转文本图像矫正. 172 4.6 小结. 178 第5 章进阶篇——边缘检测技术.. 179 5.1 边缘检测基础. 180 5.1.1 边缘检测概念 180 5.1.2 梯度算子.. 180 5.1.3 一阶微分算子 180 5.1.4 二阶微分算子 181 5.1.5 图像差分运算 182 5.1.6 非极大值抑制 184 5.2 基本边缘检测算子——Sobel 184 5.2.1 非极大值抑制Sobel 检测.. 185 5.2.2 图像直接卷积实现Sobel 186 5.2.3 图像卷积下非极大值抑制Sobel. 187 5.2.4 Sobel 库函数实现 190 5.3 基本边缘检测算子——Laplace 192 5.4 基本边缘检测算子——Roberts 194 5.5 基本边缘检测算子——Prewitt. 195 5.6 改进边缘检测算子——Canny .. 198 5.6.1 Canny 算子.. 198 5.6.2 Canny 原理及实现.. 198 5.6.3 Canny 库函数实现.. 203 5.7 改进边缘检测算子——Marr-Hildreth .. 204 5.8 几何检测 207 5.8.1 霍夫变换.. 207 5.8.2 线检测技术. 208 5.8.3 LSD 快速直线检测. 210 5.8.4 圆检测技术. 214 5.9 形状检测 215 5.9.1 轮廓检测.. 215 5.9.2 凸包检测.. 217 5.9.3 轮廓边界框. 221 5.9.4 轮廓矩 226 5.9.5 点多边形测试 229 5.10 角点检测. 232 5.10.1 moravec 角点 232 5.10.2 harris 角点. 235 5.10.3 Shi-Tomasi 角点. 238 5.11 实例应用. 240 5.11.1 颜色圆检测.. 240 5.11.2 车牌区域检测.. 243 5.12 小结 249 第6 章进阶篇——形态学技术. 250 6.1 腐蚀膨胀操作. 251 6.2 开闭运算操作. 253 6.3 形态学梯度.. 255 6.4 形态学Top-Hat.. 256 6.5 实例应用 257 6.5.1 形态学滤波角点提取. 257 6.5.2 车牌目标提取 260 6.6 小结. 263 Part III 高级篇图像应用技术. 265 第 7 章高级篇——图像分割技术.. 267 7.1 分水岭分割.. 268 7.1.1 分水岭的特征 268 7.1.2 实现分水岭分割.. 269 7.1.3 分水岭分割合并.. 270 7.2 FloodFill 分割. 273 7.3 均值漂移MeanShift 276 7.4 图割Grabcut 279 7.5 实例实例 282 7.5.1 奇异区域检测 282 7.5.2 肤色检测.. 285 7.6 小结. 288 第8 章高级篇——特征分析.. 289 8.1 尺度空间 290 8.1.1 尺度与旋转不变性. 290 8.1.2 特征点尺度变换.. 290 8.2 特征描述子.. 291 8.2.1 SIFT 特征. 292 8.2.2 SURF 特征.. 296 8.2.3 ORB 特征. 300 8.3 方向梯度直方图HOG 302 8.3.1 HOG 原理. 302 8.3.2 HOG 特征提取步骤 303 8.3.3 HOGDescriptor 特征描述类.. 304 8.3.4 HOG 特征描述实现 305 8.4 局部二值模式LBP.. 309 8.4.1 经典LBP.. 309 8.4.2 圆形LBP311 8.5 Haar 特征描述 314 8.5.1 Haar 原理. 314 8.5.2 Haar 特征提取 315 8.6 应用实例 317 8.6.1 最近邻特征点目标提取 317 8.6.2 最大极值稳定区域匹配MSER 320 8.6.3 字符特征提取 324 8.6.4 车牌字符SVM 训练.. 327 8.7 小结. 331 第 9 章高级篇——复杂视频处理技术.. 332 9.1 视频稳像技术. 333 9.2 图像拼接 338 9.2.1 拼接原理及过程.. 338 9.2.2 图像拼接实现 339 9.3 高动态范围图像HDR 342 9.3.1 HDR 合成技术.. 342 9.3.2 HDR 合成原理.. 342 9.3.3 OpenCV 实现. 343 9.4 背景建模 344 9.4.1 背景差分.. 345 9.4.2 混合高斯背景建模. 345 9.4.3 混合高斯背景建模实现 346 9.4.4 混合模型MOG2 成员参数设定. 348 9.4.5 KNN 模型背景建模实现. 349 9.4.6 GMG 模型背景建模实现 351 9.5 级联分类器——人脸检测.. 353 9.5.1 级联分类器. 353 9.5.2 CascadeClassifier 类 353 9.6 应用实例 355 9.6.1 运动目标提取 355 9.6.2 TLD 单目标跟踪.. 358 9.6.3 人眼检测与跟踪.. 361 9.7 小结. 365 附录A 366 1——代码清单.. 366 2——CMake 编译OpenCV3.1 源码. 372 3——OpenCV3.1 Extra 扩展库 375 参考文献.... 379
OpenCV是一个开源的计算机视觉库,它提供了许多图像处理和计算机视觉的功能。图像拼接是一种常见的计算机视觉任务,它涉及到将多张图像拼接在一起,形成一个更大的全景图像。在Python中,可以使用OpenCV库来实现图像拼接。 PyCharm是一种流行的Python集成开发环境(IDE),它提供了许多功能,包括代码编辑、调试、测试和版本控制等。使用PyCharm可以更方便地编写和运行Python代码,同时还可以利用其内置的调试工具来查找和修复代码中的错误。 要在PyCharm中使用OpenCV进行图像拼接,可以按照以下步骤进行操作: 1. 安装OpenCV库:在PyCharm中,可以通过PyPI(Python包索引)来安装OpenCV库。可以在PyCharm的终端中输入“pip install opencv-python”来安装OpenCV库。 2. 读取图像:使用OpenCV库中的imread函数来读取要拼接的图像。可以将这些图像保存在同一个文件夹中,或者使用不同的文件夹来分别存储它们。 3. 调整图像大小:为了使图像能够正确地拼接在一起,需要对图像进行大小调整。可以使用resize函数来调整图像的大小。 4. 合并图像:使用OpenCV库中的imwrite函数将调整大小后的图像合并在一起。可以使用cv2.imshow函数来显示合并后的图像,以便检查拼接的效果。 5. 保存图像:使用imwrite函数将合并后的图像保存到文件中。 以上是基本的图像拼接流程,具体实现时可能还需要考虑一些其他因素,例如相机标定、图像配准等。这些操作可以使用OpenCV库中的其他函数来实现。 总之,使用PyCharm和OpenCV库可以实现图像拼接,并且可以方便地进行调试和测试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

¥骁勇善战¥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值