当前位置: 首页 > news >正文

计算机视觉-局部图像描述子

[原发布时间: 2022-03-24 21:59:29]

目录

    • 1. 相关概念
      • 1.1 角点及其类型
      • 1.2 角点的性质
      • 1.3 Harris角点检测
    • 2. 理论基础
      • 2.1 Harris角点检测数学模型
      • 2.2 角点响应函数
    • 3. 代码实现
      • 3.1 使用Harris检测器检测角点
      • 3.2 为每个角点添加描述子
      • 3.3 SIFT算法
      • 3.4 描述子匹配
      • 3.5 匹配地理标记图像

1. 相关概念

1.1 角点及其类型

角点:角点通常被定义为两条边的交点,严格说角点的局部邻域应该具有两个不同区域的不同方向的边界。角点检测(Corner Detection)是计算机视觉系统中获取图像特征的一种方法,广泛应用于运动检测、图像匹配、视频跟踪、三维重建和目标识别等,也可称为特征点检测。

角点的类型:
在这里插入图片描述

1.2 角点的性质

在这里插入图片描述
如上是同一物体在不同角度、明暗程度下的图片,但通过角点可以将两张图片进行特征匹配,因此需要求角点需具备以下基本性质:

  • 几何不变性:位移、旋转、尺度……
  • 光度不变性:光照、 曝光……

1.3 Harris角点检测

基本思想:使用一个固定窗口在图像上进行任意方向上的滑动,比较滑动前与滑动后窗口中的像素灰度变化程度。如果存在任意方向上的滑动,都有着较大灰度变化,那么我们可以认为该窗口中存在角点。

过程:
当一个窗口在图像上移动时,如图(a)(a)(a),窗口在各个方向上都没有变化,则认为窗口区域为平滑区域。如图(b)(b)(b),窗口在某个方向上没有变化,另一个方向上有明显变化,那么,这块区域可能存在边缘。如图(c)(c)(c),窗口在各个方向上灰度发生了较大的变化,那么,这块区域可能存在角点。Harris角点检测正是利用了这个直观的物理现象,通过窗口在各个方向上的变化程度来决定角点。
在这里插入图片描述

2. 理论基础

2.1 Harris角点检测数学模型

图像窗口平移[u,v]后产生的灰度变化E(u,v)可表示为

E(u,v)=∑x,yw(x,y)[I(x+u,y+v)−I(x,y)]2E(u,v)=\displaystyle\sum_{x,y}w(x,y)[I(x+u,y+v)-I(x,y)]^2E(u,v)=x,yw(x,y)[I(x+u,y+v)I(x,y)]2

其中,w(x,y)w(x,y)w(x,y)为窗口函数,常见的窗口函数如下:
在这里插入图片描述

I(x+u,y+v)I(x+u,y+v)I(x+u,y+v)为平移后的图像灰度,I(x,y)I(x,y)I(x,y)为图像在(x,y)点的灰度。为了寻找带角点的窗口,需要搜索像素灰度变化较大的窗口。于是,我们期望最大化E(u,v)E(u,v)E(u,v)
假设u和v很小,则有:

I(x+u,y+v)−I(x,y)≈Ixu+IyvI(x+u,y+v)-I(x,y)\approx I_xu+I_yvI(x+u,y+v)I(x,y)Ixu+Iyv

于是对于局部微小的移动量[u,v],可以近似得到下面的表达式
在这里插入图片描述
其中M是2x2矩阵,可由图像的导数求得
在这里插入图片描述
协方差矩阵可以表示多维随机变量之间的相关性。协方差矩阵的对角线元素表示的是各个维度的方差,而非对角线上的元素表示的是各个维度之间的相关性。可以把矩阵M看作一个二维随机分布的协方差矩阵,通过将其对角化,求矩阵的两个特征值,然后根据这两个特征值来判断是不是角点。

假设λ1,λ2为矩阵M的特征值,当λ1≫λ2或λ1≪λ2时,该区域为边缘点;当λ1和λ2都很小且接近时,该区域为平坦区域内的点;当λ1和λ2都很大且接近时,说明图像窗口在各个方向上移动都产生了明显灰度变化,此时该区域为角点。

2.2 角点响应函数

由于特征值的计算量较大,因此,实际中采用角点响应函数来检测角点。角点响应函数定义为
R=Det(M)−k[trace(M)]2=λ1λ2−k(λ1+λ2)2(k=0.04∽0.06)R=Det(M)-k[trace(M)]^2=\lambda_1\lambda_2-k(\lambda_1+\lambda_2)^2 \\ (k=0.04\backsim 0.06)R=Det(M)k[trace(M)]2=λ1λ2k(λ1+λ2)2(k=0.040.06)

其中R的值只与M的特征值有关,R的值与区域类型的关系如下:
在这里插入图片描述

3. 代码实现

3.1 使用Harris检测器检测角点

源码:

from pylab import *
from PIL import Image
from PCV.localdescriptors import harris
# 添加中文字体支持
from matplotlib.font_manager import FontProperties
font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)# 读入图像
im = array(Image.open('C:/Users/lenovo/Pictures/Saved Pictures/view1.jpg').convert('L'))
# 检测harris角点
harrisim = harris.compute_harris_response(im)
# Harris响应函数
harrisim1 = 255 - harrisim
figure()
gray()#画出Harris响应图
subplot(141)
imshow(harrisim1)
title(u'(1)', fontproperties=font)
print(harrisim1.shape)
axis('off')threshold = [0.01, 0.05, 0.1]
for i, thres in enumerate(threshold):filtered_coords = harris.get_harris_points(harrisim, 6, thres)subplot(1, 4, i+2)imshow(im)title(u'('+str(i+2)+')', fontproperties=font)print(im.shape)plot([p[1] for p in filtered_coords], [p[0] for p in filtered_coords], '*')axis('off')
show()

运行结果:
在这里插入图片描述

其中,图(1)为画出Harris响应图,图(2-4)分别是使用阈值为0.01、0.05和0.1检测出的角点。

3.2 为每个角点添加描述子

源码:

from pylab import *
from PIL import Imagefrom PCV.localdescriptors import harris
from PCV.tools.imtools import imresizeim1 = array(Image.open("C:/Users/lenovo/Pictures/Saved Pictures/view1.jpg").convert("L"))
im2 = array(Image.open("C:/Users/lenovo/Pictures/Saved Pictures/view2.jpg").convert("L"))# resize加快匹配速度
im1 = imresize(im1, (im1.shape[1]/2, im1.shape[0]/2))
im2 = imresize(im2, (im2.shape[1]/2, im2.shape[0]/2))wid = 5
harrisim = harris.compute_harris_response(im1, 5)
filtered_coords1 = harris.get_harris_points(harrisim, wid+1)
d1 = harris.get_descriptors(im1, filtered_coords1, wid)harrisim = harris.compute_harris_response(im2, 5)
filtered_coords2 = harris.get_harris_points(harrisim, wid+1)
d2 = harris.get_descriptors(im2, filtered_coords2, wid)print('starting matching')
matches = harris.match_twosided(d1, d2)figure()
gray() 
harris.plot_matches(im1, im2, filtered_coords1, filtered_coords2, matches)
show()

运行结果:
在这里插入图片描述

3.3 SIFT算法

由于Harris角点检测器是旋转不变的,这意味着即使图像旋转了,检测器也可以找到相同的角,这是因为转角在旋转的图像中也仍然是转角。但是在缩放的情况下拐角可能不是拐角。例如,使用检测器检查下面的简单图像,在同一窗口中放大小窗口图像中的拐角时,该角可认为是平坦的,即Harris拐角不是尺度不变的。因此,在2004年,不列颠哥伦比亚大学的D.Lowe在他的论文《尺度不变关键点中的独特图像特征》中提出了一种新算法,即尺度不变特征变换(SIFT)算法,该算法提取关键点并计算其描述算符,并且SIFT算法能够适应旋转、尺度缩放、亮度的变化,也能在一定程度上不受视角变化、仿射变换、噪声的干扰。


下面使用SIFT算法对图像提取SIFT特征,并与提取的Harri角点进行比较。
源码:

from PIL import Image
from pylab import *
from PCV.localdescriptors import sift
from PCV.localdescriptors import harris# 添加中文字体支持
from matplotlib.font_manager import FontProperties
font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)imname = 'C:/Users/lenovo/Pictures/Saved Pictures/view1.jpg'
im = array(Image.open(imname).convert('L'))
sift.process_image(imname, 'empire.sift')
l1, d1 = sift.read_features_from_file('empire.sift')figure()
gray()
subplot(131)
sift.plot_features(im, l1, circle=False)
title(u'SIFT特征',fontproperties=font)
subplot(132)
sift.plot_features(im, l1, circle=True)
title(u'用圆圈表示SIFT特征尺度',fontproperties=font)# 检测harris角点
harrisim = harris.compute_harris_response(im)
subplot(133)
filtered_coords = harris.get_harris_points(harrisim, 6, 0.1)
imshow(im)
plot([p[1] for p in filtered_coords], [p[0] for p in filtered_coords], '*')
axis('off')
title(u'Harris角点',fontproperties=font)
show()

运行结果:
在这里插入图片描述

(注:运行代码时报“empire.sift not found”错误时的解决方法)

3.4 描述子匹配

from PIL import Image
from pylab import *
from PCV.localdescriptors import siftim1f = 'C:/Users/lenovo/Pictures/Saved Pictures/view3.jpg'
im2f = 'C:/Users/lenovo/Pictures/Saved Pictures/view4.jpg'im1 = array(Image.open(im1f).convert('L'))
im2 = array(Image.open(im2f).convert('L'))sift.process_image(im1f, 'out_sift_1.txt')
l1, d1 = sift.read_features_from_file('out_sift_1.txt')
figure()
gray()
subplot(121)
sift.plot_features(im1, l1, circle=False)sift.process_image(im2f, 'out_sift_2.txt')
l2, d2 = sift.read_features_from_file('out_sift_2.txt')
subplot(122)
sift.plot_features(im2, l2, circle=False)matches = sift.match_twosided(d1, d2)
print ('{} matches'.format(len(matches.nonzero()[0])))figure()
gray()
sift.plot_matches(im1, im2, l1, l2, matches, show_below=True)
show()

运行结果:
在这里插入图片描述
在这里插入图片描述

3.5 匹配地理标记图像

源码:

from pylab import *
from PIL import Image
from PCV.localdescriptors import sift
from PCV.tools import imtools
import pydotdownload_path = "D:/image/"  # set this to the path where you downloaded the panoramio images
path = "D:/image/"  # path to save thumbnails (pydot needs the full system path)imlist = imtools.get_imlist(download_path)
nbr_images = len(imlist)featlist = [imname[:-3] + 'sift' for imname in imlist]
for i, imname in enumerate(imlist):sift.process_image(imname, featlist[i])matchscores = zeros((nbr_images, nbr_images))for i in range(nbr_images):for j in range(i, nbr_images):  # only compute upper triangleprint('comparing ', imlist[i], imlist[j])l1, d1 = sift.read_features_from_file(featlist[i])l2, d2 = sift.read_features_from_file(featlist[j])matches = sift.match_twosided(d1, d2)nbr_matches = sum(matches > 0)print('number of matches = ', nbr_matches)matchscores[i, j] = nbr_matches
print("The match scores is: \n", matchscores)
for i in range(nbr_images):for j in range(i + 1, nbr_images):  # no need to copy diagonalmatchscores[j, i] = matchscores[i, j]#可视化
threshold = 2  # min number of matches needed to create linkg = pydot.Dot(graph_type='graph')  # don't want the default directed graphfor i in range(nbr_images):for j in range(i + 1, nbr_images):if matchscores[i, j] > threshold:# first image in pairim = Image.open(imlist[i])im.thumbnail((100, 100))filename = path + str(i) + '.png'im.save(filename)  # need temporary files of the right sizeg.add_node(pydot.Node(str(i), fontcolor='transparent', shape='rectangle', image=filename))# second image in pairim = Image.open(imlist[j])im.thumbnail((100, 100))filename = path + str(j) + '.png'im.save(filename)  # need temporary files of the right sizeg.add_node(pydot.Node(str(j), fontcolor='transparent', shape='rectangle', image=filename))g.add_edge(pydot.Edge(str(i), str(j)))
g.write_png('jmu.png')

由于运行该代码需要消耗足够大的算力,耗时一整天仍未出结果后暂时放弃运行,因此暂无图像集匹配连线后的结果( •̀ ω •́ )✧。

http://www.dtcms.com/a/305113.html

相关文章:

  • 代理IP轮换机制:突破反爬虫的关键策略
  • AI驱动的知识管理新时代:释放组织潜力的关键武器
  • win10 环境删除文件提示文件被使用无法删除怎么办?
  • MPLS 专线网络
  • 字符集学习
  • 实现多路标注截图
  • GESP2025年6月认证C++七级( 第三部分编程题(1)线图)
  • Spring Boot中的this::语法糖详解
  • Spring与数学的完美碰撞
  • 偏二甲肼气体浓度报警控制系统
  • 自适应双门限的能量检测算法
  • Python算法实战:从排序到B+树全解析
  • TDengine:用AI改变数据消费范式
  • linux命令ps的实际应用
  • 学习Python中Selenium模块的基本用法(3:下载浏览器驱动续)
  • 微服务快速入门
  • BehaviorTree.Ros2 编译教程
  • JavaWeb 入门:JavaScript 基础与实战详解(Java 开发者视角)
  • 飞算科技:以原创之力,开启Java开发新纪元与行业数智变革
  • 技术QA | GNSS模拟器如何赋能自动驾驶?聚焦HIL、多实例与精准轨迹仿真的技术优势
  • Ignite(Apache Ignite)中计算与数据共置的核心概念和编程实践
  • 小程序视频播放,与父视图一致等样式设置
  • Electron将视频文件单独打包成asar并调用
  • 如何在Linux系统下进行C语言程序的编写和debug测试
  • 解锁全球数据:Bright Data MCP 智能解决代理访问难题
  • 三极管、MOS 管、CMOS 管的特点、属性及综合对比
  • DAY27 函数专题2:装饰器
  • 【算法训练营Day18】二叉树part8
  • BOSMA博冠推出8K广播级讯道摄像机DC0300 EFP
  • 项目开发需求管理