目标

在本章节中,我们将把calib3d模块中的特征匹配和findHomography混合在一起,以在复杂图像中找到已知对象。

基础

那么我们在上一环节上做了什么?我们使用了queryImage,找到了其中的一些特征点,我们使用了另一个trainImage,也找到了该图像中的特征,并且找到了其中的最佳匹配。简而言之,我们在另一个混乱的图像中找到了对象某些部分的位置。此信息足以在trainImage上准确找到对象。

为此,我们可以使用calib3d模块中的函数,即cv.findHomography()。如果我们从两个图像中传递点集,它将找到该对象的透视变换。然后,我们可以使用cv.perspectiveTransform()查找对象。找到转换至少需要四个正确的点。

我们已经看到,匹配时可能会出现一些可能影响结果的错误。为了解决这个问题,算法使用RANSACLEAST_MEDIAN(可以由标志决定)。因此,提供正确估计的良好匹配称为“内部点”,其余的称为“外部点”。cv.findHomography()返回指定内部和外部点的掩码。

让我们开始吧!!!

代码

首先,像往常一样,让我们​​在图像中找到SIFT功能并应用比例测试以找到最佳匹配。

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
MIN_MATCH_COUNT = 10
img1 = cv.imread('box.png',0) # 索引图像
img2 = cv.imread('box_in_scene.png',0) # 训练图像
# 初始化SIFT检测器
sift = cv.xfeatures2d.SIFT_create()
# 用SIFT找到关键点和描述符
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks = 50)
flann = cv.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1,des2,k=2)
# #根据Lowe的比率测试存储所有符合条件的匹配项。
good = []
for m,n in matches:
if m.distance < 0.7*n.distance:
good.append(m)

现在我们设置一个条件,即至少有10个匹配项(由MIN_MATCH_COUNT定义)可以找到对象。否则,只需显示一条消息,说明没有足够的匹配项。

如果找到足够的匹配项,我们将在两个图像中提取匹配的关键点的位置。他们被传递以寻找预期的转变。一旦获得了这个3x3转换矩阵,就可以使用它将索引图像的角转换为训练图像中的相应点。然后我们画出来。

if len(good)>MIN_MATCH_COUNT:
src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)
dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2)
M, mask = cv.findHomography(src_pts, dst_pts, cv.RANSAC,5.0)
matchesMask = mask.ravel().tolist()
h,w,d = img1.shape
pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2)
dst = cv.perspectiveTransform(pts,M)
img2 = cv.polylines(img2,[np.int32(dst)],True,255,3, cv.LINE_AA)
else:
print( "Not enough matches are found - {}/{}".format(len(good), MIN_MATCH_COUNT) )
matchesMask = None

最后,我们绘制内部线(如果成功找到对象)或匹配关键点(如果失败)。

draw_params = dict(matchColor = (0,255,0), # 用绿色绘制匹配
singlePointColor = None,
matchesMask = matchesMask, # 只绘制内部点
flags = 2)
img3 = cv.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params)
plt.imshow(img3, 'gray'),plt.show()

请参阅下面的结果。对象在混乱的图像中标记为白色:

欢迎关注磐创博客资源汇总站:

http://docs.panchuang.net/

欢迎关注PyTorch官方中文教程站:

http://pytorch.panchuang.net/

OpenCV中文官方文档:

http://woshicver.com/

OpenCV-Python 特征匹配 + 单应性查找对象 | 四十五的更多相关文章

  1. python opencv3 FLANN单应性匹配

    git:https://github.com/linyi0604/Computer-Vision 匹配准确率非常高. 单应性指的是图像在投影发生了 畸变后仍然能够有较高的检测和匹配准确率 # codi ...

  2. OpenCV仿射变换+投射变换+单应性矩阵

    本来想用单应性求解小规模运动的物体的位移,但是后来发现即使是很微小的位移也会带来超级大的误差甚至错误求解,看起来这个方法各种行不通,还是要匹配知道深度了以后才能从三维仿射变换来入手了,纠结~ esti ...

  3. OpenCV 之 平面单应性

    上篇 OpenCV 之 图象几何变换 介绍了等距.相似和仿射变换,本篇侧重投影变换的平面单应性.OpenCV相关函数.应用实例等. 1  投影变换 1.1  平面单应性 投影变换 (Projectiv ...

  4. [OpenCV]基于特征匹配的实时平面目标检测算法

    一直想基于传统图像匹配方式做一个融合Demo,也算是对上个阶段学习的一个总结. 由此,便采购了一个摄像头,在此基础上做了实时检测平面目标的特征匹配算法. 代码如下: # coding: utf-8 ' ...

  5. OpenCV 之 特征匹配

    OpenCV 中有两种特征匹配方法:暴力匹配 (Brute force matching) 和 最近邻匹配 (Nearest Neighbors matching) 它们都继承自 Descriptor ...

  6. 机器学习进阶-案例实战-图像全景拼接-图像全景拼接(RANSCA) 1.sift.detectAndComputer(获得sift图像关键点) 2.cv2.findHomography(计算单应性矩阵H) 3.cv2.warpPerspective(获得单应性变化后的图像) 4.cv2.line(对关键点位置进行连线画图)

    1. sift.detectAndComputer(gray, None)  # 计算出图像的关键点和sift特征向量 参数说明:gray表示输入的图片 2.cv2.findHomography(kp ...

  7. 相机标定 和 单应性矩阵H

    求解相机参数的过程就称之为相机标定. 1.相机模型中的四个平面坐标系: 1.1图像像素坐标系(u,v) 以像素为单位,是以图像的左上方为原点的图像坐标系: 1.2图像物理坐标系(也叫像平面坐标系)(x ...

  8. 【Computer Vision】图像单应性变换/投影/仿射/透视

    一.基础概念 1. projective transformation  = homography = collineation. 2. 齐次坐标:使用N+1维坐标来表示N维坐标,例如在2D笛卡尔坐标 ...

  9. 单应性(homography)变换的推导

    矩阵的一个重要作用是将空间中的点变换到另一个空间中.这个作用在国内的<线性代数>教学中基本没有介绍.要能形像地理解这一作用,比较直观的方法就是图像变换,图像变换的方法很多,单应性变换是其中 ...

随机推荐

  1. C++走向远洋——52(十三周阅读程序)

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...

  2. PAT-进制转换

    3.5-进制转换 对于一个P进制的数,如果要转换为Q进制的数,需要分为两步: ①将P进制数x转换为十进制数y 对于一个十进制数y=d1d2···dn,可以将其写为: y = d1 * 10n-1 + ...

  3. springDataJPA笔记

    springDataJPA笔记 第一 orm思想 主要目的:操作实体类就相当于操作数据库表 建立两个映射关系: 实体类和表的映射关系 实体类中属性和表中字段的映射关系 不再重点关注:sql语句 实现了 ...

  4. 小白学 Python 数据分析(10):Pandas (九)数据运算

    人生苦短,我用 Python 前文传送门: 小白学 Python 数据分析(1):数据分析基础 小白学 Python 数据分析(2):Pandas (一)概述 小白学 Python 数据分析(3):P ...

  5. c++获取屏幕大小

    API: 要取得屏幕大小,可以用下面几个函数: # include <windows.h>int cx = GetSystemMetrics( SM_CXFULLSCREEN ); int ...

  6. 6,HDFS HA

    目录 HDFS HA 一.HA(High Availability)的使用原因 二.HA的同步 三.HA的自动容灾 HDFS HA 一.HA(High Availability)的使用原因 1.1 在 ...

  7. 【布局】圣杯布局&双飞翼布局

    背景 随着前端技术的发展推进,web端的布局方式已基本成熟,那么在网站布局方式中,三列布局最为常用,布局方式也有很多,渐渐的开发者们开始从效率的角度优化自己的代码"如果三排布局能将中间的模块 ...

  8. 使用web写UI, 使用js对接C++项目, 提高开发效率

    ppt资源下载地址https://www.slidestalk.com/s/webui_nodejs_cmdlrx

  9. Java基础--Java基本数据类型

    一.基本数据类型(primitive type) (1)数值型 1.数值型包括整数类型(byte,short,int,long) a.byte :1字节=8bit位   (-128~127) 包装类: ...

  10. vue项目打包后打开空白解决办法

    1.记得改一下config下面的index.js中bulid模块导出的路径.因为index.html里边的内容都是通过script标签引入的,而你的路径不对,打开肯定是空白的.先看一下默认的路径. a ...