OpenCV39:特征匹配+单应性矩阵查找对象_单应矩阵 特征匹配_uncle_ll的博客-程序员秘密

技术标签: python  # OpenCV  特征匹配  目标检测  opencv  

目标

在本章中,将学习

  • 将从Calib3D模块中混淆特征匹配和找到(单应性矩阵)homography,以查找复杂图像中的已知对象。

基础

在之前的内容中,使用了一个query image,在其中找到了一些特征点,拍摄了另一张train image,也在该图像中找到了特征,找到了其中最好的匹配。简而言之,在另一张杂乱的图像中找到了物体某些部分的位置。该信息足以准确地在train image上找到对象

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

之前的内容中可以看到,匹配的时候可能存在一些可能的错误,这可能会影响结果。为了解决这个问题,算法使用RANSACLEAST_MEDIAN(可以由标志决定)。如此良好的匹配,提供正确估计称为inliers,并且剩余的称为异常值cv2.findhomography()返回一个掩码,指定Inlier和异常值

实现

首先,像往常一样,在图像中查找SIFT特征,并应用比率测试来找到最佳匹配。

现在设置了一个至少10的匹配(由min_match_count定义)的条件是在那里找到对象。否则简单地显示一条消息,表明不够匹配。

**如果找到有足够的匹配,将在两个图像中提取匹配项点的位置。**通过以找到相似的转变。一旦获得此3x3转换矩阵,将使用它将QueryImage的角转换为TrainImage中的对应点,然后画出来。

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

MIN_MATCH_COUNT = 10

img1 = cv2.imread('box2.png', 0)  # query image
img2 = cv2.imread('box_in_scene.png', 0)  # train image

# Initial SIFT detector
sift = cv2.xfeatures2d.SIFT_create()

# find the keypoints and descriptiors with 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 = cv2.FlannBasedMatcher(index_params, search_params)

matches = flann.knnMatch(des1, des2, k=2)

# store all the good matches as per lows ratio test
good = []
for m, n in matches:
    if m.distance < 0.7 * n.distance:
        good.append(m)
        
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 = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
    matchesMask = mask.ravel().tolist()
    
    h, w = img1.shape
    pts = np.float32([[0, 0], [0, h-1], [w-1, h-1], [w-1, 0]]).reshape(-1, 1, 2)
    dst = cv2.perspectiveTransform(pts, M)
    
    img2 = cv2.polylines(img2, [np.int32(dst)], True, 255, 3, cv2.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 = cv2.drawMatches(img1, kp1, img2, kp2, good, None, **draw_params)
plt.imshow(img3, 'gray')
plt.show()

结果如下。在杂乱图像中用白色颜色标记匹配的物体
在这里插入图片描述

附加资源

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/uncle_ll/article/details/121703211

智能推荐

使用vue的pull-to插件进行分页操作_vue-pull-to umd模式_round123_rr的博客-程序员秘密

1.官网地址:https://github.com/stackjie/vue-pull-to/blob/master/README.zh-CN.md2.安装:npm install vue-pull-to --save3.使用&amp;lt;template scope&amp;gt; &amp;lt;div class=&quot;user-page&quot;&amp;gt; &amp;lt;div clas...

oracle 创建临时表空间/表空间,用户及授权_weixin_30367945的博客-程序员秘密

1:创建临时表空间create temporary tablespace user_temp tempfile 'Q:\oracle\product\10.2.0\oradata\Test\xyrj_temp.dbf' size 50m autoextend on next 50m maxsize 20480m extent management local; ...

SAP取历史库存(可查询期初期末库存和指定日期之库存)_sap 按期间查询库存_ChampaignWolf的博客-程序员秘密

含仓位之Table:MARD / MARDH        MARD里记载的是当前库存的数量,是实时变化的,但是期间并不一定是当月。比如:当前是2015年11月,料号A在2015年10月初至今都没有库存异动,那么现在看到MARD里料号A的期间数还是2015年09月,而非2015年11月。       当料号A发生异动时,系统将实时更新MARD数据。在更新之前,会检查此异动的过账期间和MARD...

size _t 类型介绍_freertos size_t类型_ADHERENTS的博客-程序员秘密

size _t为了增强程序的可移植性,便有了size_t,不同系统上,定义size_t可能不一样。经测试发现,在32位系统中size_t是4字节的,在64位系统中,size_t是8字节的,这样利用该类型可以增加程序移植性。...

Android性能优化系列一:启动优化_且听风吟9527的博客-程序员秘密

文章目录黑白屏优化冷/热/暖启动代码未优化造成的问题App启动时间检测方式方式一:adb命令方式二:手动打点启动优化工具选择traceview介绍Systrace介绍优雅获取方法耗时异步优化分析异步优化方案优化-启动器启动器的具体使用更优秀的延迟初始化方案更优方案黑白屏优化黑白屏原因​ 在App的启动流程中,我们已知:当系统加载并启动App时,需要消耗相应的时间,即使不到1s,用户也会感觉...

随便推点

java 如何清除临时文件_如何删除Java中的临时文件?_Java架构月亮的博客-程序员秘密

java.io包的名为File的类表示系统中的文件或目录(路径名)。此类提供了各种方法来对文件/目录执行各种操作。临时文件在某些情况下,例如单元测试或某些应用程序逻辑,您可能需要创建临时文件。Java中的File类提供了一个名为createTempFile()的方法。此方法接受两个String变量,它们代表临时文件的前缀(起始名称)和后缀(扩展名),以及一个File对象,该变量代表您需要在其中创建...

python之使用functools.partial_function.partial_keyson R的博客-程序员秘密

文章目录`partial`定义`partialmethod`定义partial定义functools.partial 这个高阶函数用于部分应用一个函数。部分应用是指,基于一个函数创建一个新的可调用对象,把原函数的某些参数固定。使用这个函数可以把接受一个或多个参数的函数改编成需要回调的 API,这样参数更少。这是一段引自Fluent Python的代码示例:&gt;&gt;&gt; from operator import mul&gt;&gt;&gt; from functools import

js-xlsx + handsontable + echarts实现excel上传编辑然后显示成图表_noahnee的博客-程序员秘密

js-xlsx + handsontable + echarts 实现在前端导入excel数据并生成echart报表前言最近都在做类似 ERP 的项目,所以呢,又碰到一个比较变态的需求(至少对我来说是),在前端导入 excel 文件,然后在浏览器里面预览和编辑, 最后再选择一些数据,用echarts生成报表.依赖js-xlsx 读取excel数据到jshandsontable 类似Ex...

【Spring Boot】整合 MyBatis-Plus 实现 CRUD 操作_骑着蜗牛ひ追导弹'的博客-程序员秘密

文章目录MyBatis-Plus 实现 CRUD 操作一、什么是MyBatis-Plus1.概述2.特点3.插件功能展示二、整合MyBatis-Plus1.创建数据库环境2.导入mybatis-plus依赖3.创建数据库表实体类Users4.创建UsersMapper接口5.测试补充三、CRUD3.1 查询所有 list()1.UserMapper2.UserService3.UserServiceImpl4.前端控制器实现查询所有展示3.2 分页 page()1.分页框架构建2.修改后端控制器3.修改.

stm32f429 利用stm32cube配置FMC接口_mail-mail的博客-程序员秘密

目录一、为什么使用SDRAM二、SDRAM芯片W9825G6KH三、stm32f4的fmc接口四、stm32cubemx配置fmc五、实验现象:六、源码:七、注意事项:八、参考记录:硬件平台:正点原子阿波罗stm32f429一、为什么使用SDRAMSTM32控制器芯片内部有一定大小的SRAM及FLASH作为内存和程序存储空间,但当程序较大,内存和程序空间...

NSFileHandle简单的读写文件_KumaHuang的博客-程序员秘密

NSString *savepath = [self saveFilePath:@"savepath"]; NSString *outpath = [self saveFilePath:@"outpath"]; NSString *text = @"This is test text in file."; NSData *buffer; if (![fm fileE

推荐文章

热门文章

相关标签