计算机视觉与模式识别实验2-2 SIFT特征提取与匹配

news2024/11/20 10:29:01

文章目录

    • 🧡🧡实验流程🧡🧡
      • SIFT算法原理总结:
      • 实现SIFT特征检测和匹配
      • 通过RANSAC 实现图片拼接
      • 更换其他图片再次测试效果(依次进行SIFT特征提取、RANSAC 拼接)
    • 🧡🧡全部代码🧡🧡

🧡🧡实验流程🧡🧡

SIFT算法原理总结:

1.创建尺度空间:
高斯模糊去除噪声,强调了图像的重要特征
在这里插入图片描述
根据原图创建不同比例的新图像
在这里插入图片描述

2.采用高斯差异DOG增强特征
在这里插入图片描述
如下,对于某一比例的5张不同模糊程度的图像,进行差分
在这里插入图片描述

3.关键点定位(尺度不变性)
找出局部最大值和最小值(这里“局部”的含义:它不仅包括该图像的周围像素(像素所在的像素),还包括八度中上一张和下一张图像的九个像素)
这意味着将每个像素值与其他26个像素值进行比较,以确定是否为局部最大值/最小值。例如,在下图中,从第一个八度获得了三个图像。将标记为x的像素与相邻像素(绿色)进行比较,如果它是相邻像素中最高或最低的像素,则将其选择为关键点:
在这里插入图片描述
关键点的筛选
消除对比度低或非常靠近边缘的关键点:
采用二阶泰勒展开消除对比度低或非常靠近边缘的关键点、采用二阶Hessian矩阵来识别具有高边缘度但对少量噪点无鲁棒性的关键点

4.关键点方向分配(旋转不变性)
对于每个关键点和其周围的像素,都执行如下操作:
根据梯度计算幅度和方向,如下Gx=9,Gy=14则
在这里插入图片描述
在这里插入图片描述
随后创建大小和方向的柱状图
在这里插入图片描述

5.生成描述符
已经通过3、4生成了具有尺度不变性和旋转不变性的关键点,对于每个关键点,使用相邻像素,它们的方向和大小为该关键点生成一个唯一的指纹,称为“描述符”。

6.关键点匹配
使用描述子之间的距离或相似度度量来匹配不同图像中的关键点,通常采用最近邻或 k近邻方法来进行匹配。
(在opencv中,BFMatcher.match() 和BFMatcher.knnMatch(),第一个返回最佳匹配,第二个返回前k个最佳的匹配,k值由用户指定。)




实现SIFT特征检测和匹配

原始图像如下:
在这里插入图片描述

截出两个图像(分别截取前宽度的4/5和后4/5部分)
在这里插入图片描述

画出关键点
在这里插入图片描述

SIFT匹配(总共529个匹配,按连线长度升序,画出全部线)
在这里插入图片描述

为方便观察,画出按连线长度前100匹配的连线
在这里插入图片描述

将右侧图片旋转90度,重复上述步骤
在这里插入图片描述
在这里插入图片描述

将右侧图片旋转15度,并缩放到原图0.8倍,重复上述步骤
在这里插入图片描述
在这里插入图片描述




通过RANSAC 实现图片拼接

右侧图片正放
在这里插入图片描述
拼接结果:
在这里插入图片描述


右侧图片旋转90度
在这里插入图片描述
拼接结果:
在这里插入图片描述


右侧图片旋转15度并缩放到0.8倍
在这里插入图片描述
拼接结果:
在这里插入图片描述




更换其他图片再次测试效果(依次进行SIFT特征提取、RANSAC 拼接)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

🧡🧡全部代码🧡🧡

import numpy as np
import cv2
from matplotlib import pyplot as plt
def cv_show(title,img):
    cv2.imshow(title, img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
"""
    SIFT 图像特征连接+ RANSAC拼接
"""

def check_and_draw_KeyPoint(img1,img2):
    img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
    img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
    # Sift
    sift = cv2.SIFT_create()
    kp1, des1 = sift.detectAndCompute(img1,None)
    kp2, des2 = sift.detectAndCompute(img2,None)
    # len(kp1), len(kp2)

    # Draw KeyPoint
    imgShow1 = cv2.drawKeypoints(img1,kp1,None,color=(255,0,255)) #画出特征点,并显示为红色圆圈
    imgShow2 = cv2.drawKeypoints(img2,kp2,None,color=(255,0,255)) #画出特征点,并显示为红色圆圈
    cv_show("KeyPoint", np.hstack((imgShow1, imgShow2)))
    return img1,img2,kp1,kp2,des1,des2

def match_KeyPoint(img1,img2,kp1,kp2,des1,des2,show_line_num=100):
    # Feature Matching
    bf = cv2.BFMatcher(cv2.NORM_L1, crossCheck=True)
    matches = bf.match(des1,des2)
    matches =sorted(matches, key=lambda x:x.distance)
    # print(len(matches))
    imgShow = cv2.drawMatches(img1, kp1, img2, kp2, matches[0:show_line_num], None, flags=2)
    cv_show("Match",imgShow)

def concat_Image(img1,img2,kp1,kp2,des1,des2):
    # 匹配特征,并返回透视变换矩阵
    matcher = cv2.BFMatcher()
    rawMatches = matcher.knnMatch(des2, des1, 2)
    matches = []
    for m in rawMatches:
        if len(m) == 2 and m[0].distance < m[1].distance * 0.75:
            matches.append((m[0].trainIdx, m[0].queryIdx))
    kp1 = np.float32([kp.pt for kp in kp1])
    kp2 = np.float32([kp.pt for kp in kp2])
    if len(matches) > 4:
        ptsA = np.float32([kp2[i] for (_, i) in matches])
        ptsB = np.float32([kp1[i] for (i, _) in matches])
        (H, status) = cv2.findHomography(ptsA, ptsB, cv2.RANSAC, 4.0)

    result = cv2.warpPerspective(img2, H, (img2.shape[1] + img1.shape[1], img2.shape[0]))
    result[0:img1.shape[0], 0:img1.shape[1]] = img1
    cv_show("Concat Image",result)


if __name__=="__main__":
    # Read Original Image
    image = cv2.imread('img/test2_Sift.jpg')
    height, width, _ = image.shape
    image = cv2.resize(image,(int(width*4/6),int(height*4/6))) # 图片有点宽,缩放一下
    height, width, _ = image.shape

    # 截取前4/5部分和后4/5部分
    img1 = image[:, 0 : int(width * 4 / 5)]
    img2 = image[:, int(width / 5) : width]

    img1 = cv2.imread("img/test2_river1.png")
    img2 = cv2.imread("img/test2_river2.png")
    # 可注释)图像转变2:img2旋转90度
#     img2 = cv2.rotate(img2, cv2.ROTATE_90_CLOCKWISE) # 旋转90度
#     img2 = cv2.resize(img2,(img2.shape[1], img1.shape[0]))

    # 可注释)图像转变3:img2旋转15度,并且缩放到0.9倍,同时img1设置跟img2同样高度,并且宽度按比例变换
#     center=(width/2,height/2)
#     angle=15
#     scale=0.8
#     M=cv2.getRotationMatrix2D(center,angle,scale)
#     img2=cv2.warpAffine(img2,M,(int(width),int(1.1*height)))
#     img1=cv2.resize(img1,(int(img1.shape[1]*img2.shape[0]/img1.shape[0]), img2.shape[0]))
    
    cv_show("spilt", np.hstack((img1, img2))) #拼接显示原图

    # 调用自定义函数
    img1,img2,kp1,kp2,des1,des2=check_and_draw_KeyPoint(img1,img2) # 检测并画出关键点
    match_KeyPoint(img1,img2,kp1,kp2,des1,des2, show_line_num=100) # 连接关键点
    concat_Image(img1,img2,kp1,kp2,des1,des2) # 拼接图像

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1798778.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Texture2D 实现Unity 截屏功能

实现 截屏 Texture2D texture new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false); texture.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0); texture.Apply(); 存储 byte[] array ImageConversion.EncodeToPNG(texture); if (!…

MATLAB format

在MATLAB中&#xff0c;format 是一个函数&#xff0c;用于控制命令窗口中数值的显示格式。这个函数可以设置数值的精度、显示的位数等。以下是一些常用的 format 命令&#xff1a; format long&#xff1a;以默认的长格式显示数值&#xff0c;通常显示15位有效数字。format s…

揭秘!如何从精益生产转向智能制造

企业在“工业4.0、智能制造、互联网”等概念满天飞的环境下迷失了方向&#xff0c;不知该如何下手&#xff0c;盲目跟风。 君不见&#xff0c;很多企业在“工业4.0、智能制造、互联网”等概念满天飞的环境下迷失了方向&#xff0c;不知该如何下手&#xff0c;盲目跟风&#xf…

完美落地的自动化测试框架(pytest):智能生成?业务依赖?动态替换?报告构建?你来,这儿有!

前言 随着软件测试行业的快速发展&#xff0c;去测试化、全员测开化的趋势&#xff0c;技术测试已成为确保软件质量不可或缺的一环。 但对于许多没有代码基础或缺乏系统性自动化知识的测试人员来说&#xff0c;如何入手并实现高质量的自动化测试成为了一个挑战。 为此&#xff…

怎么将3d的模型同比例缩放?---模大狮模型网

在展览3d模型设计过程中&#xff0c;经常需要对3d模型进行缩放以满足不同的需求。然而&#xff0c;有时候缩放操作可能会导致模型失去比例&#xff0c;造成不必要的麻烦。模大狮将介绍如何将展览3D模型按比例缩放&#xff0c;帮助展览设计师们更好地掌握这一关键的模型设计技巧…

Ubuntu 安装好虚拟环境后,找不到workon 命令

1、安装虚拟环境 pip3 install virtualenv pip3 install virtualenvwrapper 2、安装完成后 workon 命令。 找不到workon 命令 执行&#xff0c;source virtualenvwrapper.sh 执行后&#xff0c;在使用workon命令&#xff0c;即可完成。

HQL面试题练习 —— 求连续段的最后一个数及每个连续段的个数

目录 1 题目2 建表语句3 题解 题目来源&#xff1a;拼多多。 1 题目 有一张表t_id记录了id&#xff0c;id不重复&#xff0c;但是会存在间断&#xff0c;求出连续段的最后一个数及每个连续段的个数。 ----- | id | ----- | 1 | | 2 | | 3 | | 5 | | 6 | | 8 | | …

Unity基础实践小项目

项目流程&#xff1a; 需求分析 开始界面 选择角色面板 排行榜面板 设置面板 游戏面板 确定退出面板 死亡面板 UML类图 准备工作 1.导入资源 2.创建需要的文件夹 3.创建好面板基类 开始场景 开始界面 1.拼面板 2.写脚本 注意事项&#xff1a;注意先设置NGUI的分辨率大小&…

FactoryTalk View Site Edition的VBA基本应用

第一节 在VBA中标签的读取和写入 本例要达到的目标是通过FactoryTalk View Site Edition&#xff08;以下简称SE&#xff09;的VBA来访问PLC中的下位标签&#xff0c;并实现标签的读写。 1.准备工作 打开SE&#xff0c;选择应用程序类型&#xff08;本例是Site Edition Netwo…

【qt】MDI多文档界面开发

MDI多文档界面开发 一.应用场景二.界面设计三.界面类设计四.实现功能1.新建文档2.打开文件3.关闭所有4.编辑功能5.MDI页模式6.瀑布展开模式7.平铺模式 五.总结 一.应用场景 类似于vs的界面功能,工具栏的功能可以对每个文档使用! 二.界面设计 老规矩,边做项目边学! 目标图: 需…

[职场] 美术指导的重要作用 #学习方法#笔记

美术指导的重要作用 美术指导是广告、电影、电视剧等创意作品中的一个重要角色&#xff0c;负责整体视觉风格和美术设计的指导和管理。 美术指导的目标是通过视觉表达来传达故事的情感、氛围和主题&#xff0c;以及塑造角色和场景的形象。 美术指导在创作过程中扮演着重要的角…

MacBook Pro上高cpu上不断重启运行的efilogin-helper

高 cpu 运行这个不知道干什么的进程&#xff0c;让风扇疯狂输出&#xff0c;让人甚是烦躁&#xff0c;苹果社区里的回答比较抽象&#xff0c;要么换设备&#xff0c;要么重装。 尝试过找到这个文件&#xff0c;删了部分内容&#xff0c;无果。。。 stack overflow 有个回答&a…

三维可视化技术在厂区人员、车辆定位中的设计与应用效益

随着厂区规模的不断扩大&#xff0c;车辆和人员的流动管理成为了每个厂区管理者面临的难题。如何在错综复杂的厂区环境中&#xff0c;实现车辆的高效调度和人员的精准定位&#xff0c;成为了亟待解决的问题。维小帮厂区地图导航系统&#xff0c;结合三维可视化技术和智能算法&a…

【NoSQL数据库】Redis——哨兵模式

Redis——哨兵模式 Redis哨兵 Redis——哨兵模式1.什么是哨兵机制&#xff08;Redis Sentinel&#xff09;1.1 哨兵的作用 2.哨兵的运行机制3.故障处理redis常见问题汇总1、redis缓存击穿是什么&#xff1f;如何解决&#xff1f;2、redis缓存穿透是什么&#xff1f;如何解决&am…

css网格背景样式

空白内容效果图 在百度页面测试效果 ER图效果 注意&#xff1a;要给div一个宽高 <template><div class"grid-bg"></div> </template><style scoped> .grid-bg {width: 100%;height: 100%;background: url(data:image/svgxml;base…

短视频评论截取提取软件技术思路

关于开发短视频评论所需要用到得技术第一篇 前言&#xff1a;根据业务需要&#xff0c;我们需要通过短视频找到准客户&#xff0c;这个软件应该是叫短视频评论提取软件&#xff0c;或者是短视频评论采集。无所谓叫什么都可以 进入正题。 第一篇只讲解所应该用到得基础工作 一…

关于JavaScript技术的基础内容汇总

目录 JavaScript 基础知识1. JavaScript 基本语法2. 变量和常量3. 数据类型4. 运算符5. 控制结构6. 函数7. 对象8. 数组9. 事件处理10. DOM 操作 JavaScript 基础知识 学习 JavaScript&#xff08;简称 JS&#xff09;是前端开发的重要组成部分&#xff0c;它是一种动态的、弱…

100V 15A TO-252 N沟道MOS管 HC070N10L 惠海

MOS管的工作原理是基于在P型半导体与N型半导体之间形成的PN结&#xff0c;通过改变栅极电压来调整沟道内载流子的数量&#xff0c;从而改变沟道电阻和源极与漏极之间的电流大小。由于MOS管具有输入电阻高、噪声小、功耗低等优点&#xff0c;它们在大规模和超大规模集成电路中得…

【ARM Cache 及 MMU 系列文章 6.3 -- ARMv8/v9 Cache Tag数据读取及分析】

请阅读【ARM Cache 及 MMU/MPU 系列文章专栏导读】 及【嵌入式开发学习必备专栏】 文章目录 Cache Tag 数据读取测试代码Cache Tag 数据读取 在处理器中,缓存是一种快速存储资源,用于减少访问主内存时的延迟。缓存通过存储主内存中经常访问的数据来实现这一点。为了有效地管…

java高并发实战<2>

##>>> 我们解决我们重复下单的问题 我们可以使用mysql 的唯一索引 &#xff0c;在我们的数据库层面保证不能重复下单 我可以控制是唯一的 同一个用户 针对于同一个商品只可以买一个 重复下单 优化 我们 >1.使用数据库唯一索引 一旦是 2个请求 因为mysql 有行级…