第二章 局部图像描述子

news2024/11/26 7:50:01

文章目录

  • 第二章 局部图像描述子
    • 2.1Harris角点检测器
    • 2.2SIFT(尺度不变特征变换)
      • 2.2.1兴趣点
      • 2.2.2描述子
      • 2.2.3检测兴趣点

第二章 局部图像描述子

本章旨在寻找图像间的对应点和对应区域。本章将介绍用于图像匹配的两种局部描述子算法。本书的很多内容中都会用到这些局部特征,它们在很多应用中都有重要作用,比如创建全景图、增强现实技术以及计算图像的三维重建。

2.1Harris角点检测器

Harris 角点检测算法(也称 Harris & Stephens 角点检测器)是一个极为简单的角点检测算法。该算法的主要思想是,如果像素周围显示存在多于一个方向的边,我们认为该点为兴趣点。该点就称为角点。我们把图像域中点 x 上的对称半正定矩阵 M I = M I ( x ) M_I=M_I(x) MI=MI(x)定义为: M I = ∇ I ∇ I T = [ I x I y ] [ I x I y ] = [ I x 2 I x I y I x I y I y 2 ] M_I=\nabla I\nabla I^T=\begin{bmatrix}I_x\\I_y\end{bmatrix}[I_xI_y]=\begin{bmatrix}I_x^2&I_xI_y\\I_xI_y&I_y^2\end{bmatrix} MI=IIT=[IxIy][IxIy]=[Ix2IxIyIxIyIy2]

选择权重矩阵 W(通常为高斯滤波器gaussian_filter),我们可以得到卷积: M ‾ i = W ∗ M i \overline{\boldsymbol{M}}_i=\boldsymbol{W}*\boldsymbol{M}_i Mi=WMi

使用商数作为指示函数 det ⁡ ( M ‾ i ) = M x x M y y − M x y 2 \det(\overline{M}_i)=M_{xx}M_{yy}-M_{xy}^2 det(Mi)=MxxMyyMxy2 t r a c e ( M ‾ i ) = M x x + M y y \mathrm{trace}(\overline{M}_i)=M_{xx}+M_{yy} trace(Mi)=Mxx+Myy r e s p o n c e = det ⁡ ( M ‾ i ) trace ⁡ ( M ‾ i ) 2 \mathrm{responce=}\frac{\det(\overline{M}_i)}{\operatorname{trace}\left(\overline{M}_i\right)^2} responce=trace(Mi)2det(Mi)

from scipy.ndimage import gaussian_filter
import numpy as np
from numpy import *
from PIL import Image
from matplotlib import pyplot as plt

img = Image.open('am.png')
plt.figure()
plt.axis('off')
plt.imshow(img)
plt.show()

在这里插入图片描述

原图为上图所示,是一个卡通人物

def compute_harris_response(im, sigma=3):
    """ 在一幅灰度图像中,对每个像素计算 Harris 角点检测器响应函数 """
    # 计算导数
    im=np.array(im.convert('L'))
    Ix = gaussian_filter(im, (sigma, sigma), (0, 1))
    Iy = gaussian_filter(im, (sigma, sigma), (1, 0))
    # 计算 Harris 矩阵的分量
    Mxx = gaussian_filter(Ix*Ix, sigma)
    Mxy = gaussian_filter(Ix*Iy, sigma)
    Myy = gaussian_filter(Iy*Iy, sigma)
    # 计算特征值和迹
    det_M = Mxx*Myy - Mxy**2
    trace_M = Mxx + Myy
    return np.divide(det_M, trace_M, out=np.zeros_like(det_M, dtype=np.float64), where=(trace_M != 0))
def plot_harris_points(image, filtered_coords):
    """ 绘制图像中检测到的角点 """
    plt.figure()
    plt.imshow(image)
    # 将坐标以*标出
    plt.plot([p[1] for p in filtered_coords],[p[0] for p in filtered_coords], '*')
    plt.axis('off')
    plt.show()
# print(img)
harrisim = compute_harris_response(img)
# harrisim_t=255*(harrisim>0.1)
# plt.figure(figsize=(8, 8))
# plt.imshow(harrisim_t)
n,m=len(harrisim),len(harrisim[0])
coords=[]
for i in range(n):
    for j in range(m):
        if harrisim[i][j]:
            coords.append([i,j])
plot_harris_points(img, coords)

在这里插入图片描述

从上图可以看到原图的卡通人物的基本轮廓。但是这里的点太多了,我们需要的是重要的交点,所以需要做以下筛选。

def get_harris_points(harrisim, min_dist=10, threshold=0.1):
    """ 从一幅 Harris 响应图像中返回角点。min_dist 为分割角点和图像边界的最少像素数目 """
    # 寻找高于阈值的候选角点
    corner_threshold = harrisim.max() * threshold
    harrisim_t = (harrisim > corner_threshold) * 1

    # 得到候选点的坐标
    coords = np.array(harrisim_t.nonzero()).T
    # 以及它们的 Harris 响应值
    candidate_values = [harrisim[c[0], c[1]] for c in coords]
    # 对候选点按照 Harris 响应值进行排序
    index = argsort(candidate_values)
    # 将可行点的位置保存到数组中
    allowed_locations = np.zeros(harrisim.shape)
    allowed_locations[min_dist:-min_dist, min_dist:-min_dist] = 1
    # 按照 min_distance 原则,选择最佳 Harris 点
    filtered_coords = []
    for i in index:
        if allowed_locations[coords[i, 0], coords[i, 1]] == 1:
            filtered_coords.append(coords[i])
            allowed_locations[(coords[i, 0]-min_dist):(coords[i, 0]+min_dist),
                              (coords[i, 1]-min_dist):(coords[i, 1]+min_dist)] = 0
    return filtered_coords



filtered_coords = get_harris_points(harrisim, 3, 0.05)
# plt.figure(figsize=(8, 8))
# plt.imshow(im)
# plt.plot([p[1] for p in filtered_coords],[p[0] for p in filtered_coords], '*')
# plt.show()
plot_harris_points(img, filtered_coords)

在这里插入图片描述

上图和上上图对比,角点数量大大减少,但是效果不减。
方法是:选取像素值高于阈值的所有图像点;再加上额外的限制,即角点之间的间隔必须大于设定的最小距离。这种方法会产生很好的角点检测结果。为了实现该算法,我们获取所有的候选像素点,以角点响应值递减的顺序排序,然后将距离已标记为角点位置过近的区域从候选像素点中删除。
其中,我们可以通过设置阈值threshold角点之间的间隔min_dist来控制角点的数量

接下来,我们将归一化的互相关矩阵应用于 Harris 角点周围图像块,来寻找匹配对应点,

def yasuo(name1,n,name2):
    img=cv2.imread(name1)
    times=img.shape[0]/n
    m=int(img.shape[1]/times)
    print([n,m])
    img_t = np.zeros([n,m,3])
    for i in range(n):
        for j in range(m):
            for k in range(3):
                img_t[i][j][k]=img[int(i*times)][int(j*times)][k]
    img_t=img_t.astype(np.uint8)
    cv2.imwrite(name2,img_t)
    # plt_show(img,img_t)
    print(img.shape)
    print(img_t.shape)
    return img_t

import cv2
for i in range(1,3):
    name='r'+str(i)+'.jpg'
    name2='dormitory'+str(i)+'.jpg'
    img=cv2.imread(name)
    img=img[-2600:,-2300:,:]
    cv2.imwrite(name2,img)
    yasuo(name2,500,name2)
[500, 442]
(2600, 2300, 3)
(500, 442, 3)
[500, 442]
(2600, 2300, 3)
(500, 442, 3)
plt.figure(figsize=(9,5))
for i in range(1,3):
    name2='dormitory'+str(i)+'.jpg'
    img=cv2.imread(name2)
    plt.subplot(120+i)
    plt.imshow(img)
    plt.axis('off')
plt.show()

在这里插入图片描述

例如上图是两张宿舍部分图,我们接下来对其进行匹配。

# -*- coding: utf-8 -*-
from pylab import *
from PIL import Image

import harris


im1 = array(Image.open("dormitory1.jpg").convert("L"))
im2 = array(Image.open("dormitory2.jpg").convert("L"))


wid = 13
harrisim = harris.compute_harris_response(im1, wid)
filtered_coords1 = harris.get_harris_points(harrisim, wid+1)
d1 = harris.get_descriptors(im1, filtered_coords1, wid)

harrisim = harris.compute_harris_response(im2, wid)
filtered_coords2 = harris.get_harris_points(harrisim, wid+1)
d2 = harris.get_descriptors(im2, filtered_coords2, wid)


matches = harris.match_twosided(d1, d2)

plt.figure()
harris.plot_matches(im1, im2, filtered_coords1, filtered_coords2, matches)
plt.show()
plt.savefig('test.jpg')

在这里插入图片描述

该算法的结果存在一些不正确匹配。这是因为图像像素块的互相关矩阵具有较弱的描述性。实际运用中,我们通常使用更稳健的方法来处理这些对应匹配。这些描述符还有一个问题,它们不具有尺度不变性和旋转不变性,而算法中像素块的大小也会影响对应匹配的结果。

2.2SIFT(尺度不变特征变换)

SIFT(Scale-Invariant Feature Transform,尺度不变特征变换)是过去最成功的图像局部描述子之一。SIFT 特征包括兴趣点检测器和描述子。SIFT 描述子具有非常强的稳健性,这在很大程度上也是 SIFT 特征能够成功和流行的主要原因。SIFT 特征对于尺度、旋转和亮度都具有不变性,因此,它可以用于三维视角和噪声的可靠匹配。

2.2.1兴趣点

SIFT 特征使用高斯差分函数来定位兴趣点: D ( x , σ ) = [ G κ σ ( x ) − G σ ( x ) ] ∗ I ( x ) = [ G κ σ − G σ ] ∗ I = I κ σ − I σ D(\mathbf{x},\sigma)=[G_{\kappa\sigma}(\mathbf{x})-G_{\sigma}(\mathbf{x})]*I(\mathbf{x})=[G_{\kappa\sigma}-G_{\sigma}]*I=I_{\kappa\sigma}-I_{\sigma} D(x,σ)=[Gκσ(x)Gσ(x)]I(x)=[GκσGσ]I=IκσIσ

Gσ 是上一章中介绍的二维高斯核,Iσ 是使用 Gσ 模糊的灰度图像,κ 是决定相差尺度的常数。兴趣点是在图像位置和尺度变化下 D(x,σ) 的最大值和最小值点

2.2.2描述子

上面讨论的兴趣点(关键点)位置描述子给出了兴趣点的位置和尺度信息。为了实现旋转不变性,基于每个点周围图像梯度的方向和大小,SIFT 描述子又引入了参考方向。SIFT 描述子使用主方向描述参考方向。主方向使用方向直方图(以大小为权重)来度量

SIFT 描述子的标准设置使用 4×4 的子区域,每个子区域使用 8 个小区间的方向直方图,会产生共128 个小区间的直方图(4×4×8=128)

在这里插入图片描述

2.2.3检测兴趣点

我们使用开源工具包 VLFeat 提供的二进制文件来计算图像的 SIFT 特征。VLFeat 工具包可以从 http://www.vlfeat.org/ 下载,二进制文件可以在所有主要的平台上运行。VLFeat 库是用 C 语言来写的,但是我们可以使用该库提供的命令行接口。

由于该二进制文件需要的图像格式为灰度 .pgm,所以如果图像为其他格式,我们需要首先将其转换成 .pgm 格式文件

from PIL import Image
import os
import numpy
from pylab import *


def process_image(imagename, resultname, params="--edge-thresh 10 --peak-thresh 5"):
    """ Process an image and save the results in a file. """

    if imagename[-3:] != 'pgm':
        # create a pgm file
        im = Image.open(imagename).convert('L')
        im.save('tmp.pgm')
        imagename = 'tmp.pgm'

    cmmd = str(r"D:\software\vlfeat\vlfeat-0.9.20\bin\win32\sift.exe " +
               imagename+" --output="+resultname + " "+params)
    os.system(cmmd)
    print(cmmd)
    print('processed', imagename, 'to', resultname)

读取特征属性值,然后将其以矩阵的形式返回

import chardet

def read_features_from_file(filename):
    with open(filename, 'rb') as f:
        rawdata = f.read()
        result = chardet.detect(rawdata)
        encoding = result['encoding']

    f = loadtxt(filename, encoding=encoding)
    return f[:, :4], f[:, 4:]  # 特征位置,描述子

将特征位置和描述子保存到文件中:

def write_features_to_file(filename, locs, desc):
    savetxt(filename, hstack((locs, desc)))

读取特征后,通过在图像上绘制出它们的位置,可以将其可视化:

def plot_features(im,locs,circle=False):

    def draw_circle(c,r): 
        t = arange(0,1.01,0.01)*2*pi
        x = r*cos(t) + c[0]
        y = r*sin(t) + c[1]
        plt.plot(x,y,'b',linewidth=2)
    
    plt.imshow(im)
    if circle:
        for p in locs:
            draw_circle(p[:2],p[2])
    else:
        plt.plot(locs[:,0],locs[:,1],'ob')
imgname = 'am.png'
im1 = array(Image.open(imgname).convert('L'))
process_image(imgname, 'am.sift')
l1, d1 = read_features_from_file('am.sift')

plt.figure()
plot_features(im1, l1, circle=True)
plt.show()-
D:\software\vlfeat\vlfeat-0.9.20\bin\win32\sift.exe tmp.pgm --output=am.sift --edge-thresh 10 --peak-thresh 5
processed tmp.pgm to am.sift

在这里插入图片描述

分析:SIFT算法的实质是在不同的尺度空间上查找关键点(特征点),并计算出关键点的方向。SIFT所查找到的关键点是一些十分突出,不会因光照、仿射变换和噪音等因素而变化的点(如角点、边缘点、暗区的亮点及亮区的暗点等)

在运行过程中,可能会出现一些问题,参考SIFT特征提取(PCV、VLFeat)的环境配置、常见Bug及修复方案。

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

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

相关文章

RocketMQ 安装与入门

文章目录 简介下载下载目录地址 安装部署环境要求下载二进制包解压即可启动 NameServer 启动BrokerProxy单组节点单副本模式启动 使用Java客户端发布订阅消息1. 创建主题 topic2. 创建Java工程使用Maven引入Java SDK包生产者代码 ProducerDemo消费者代码 ConsumerDemo RocketMQ…

SPSS教程:如何绘制带误差的折线图

SPSS教程:如何绘制带误差的折线图 1、问题与数据 研究者想研究45-65岁健康男性中,静坐时长和血胆固醇水平的关系,故招募100名研究对象询问其每天静坐时长(time),并检测其血液中胆固醇水平(cho…

VSCode下载、安装及配置、调试的一些过程理解

第一步先下载了vscode,官方地址为:https://code.visualstudio.com/Download 第二步安装vscode,安装环境是win10,安装基本上就是一步步默认即可。 第三步汉化vscode,这一步就是去扩展插件里面下载一个中文插件即可&am…

安全测试-django防御安全策略

django安全性 django针对安全方面有一些处理,学习如何进行处理设置,也有利于学习安全测试知识。 CSRF 跨站点请求伪造(Cross-Site Request Forgery,CSRF)是一种网络攻击方式,攻击者欺骗用户在自己访问的网…

【实验二】基尔霍夫定律和叠加定理

【实验内容】 【实验报告】 表一线路图 表二线路图 线路1 线路2 同时作用 【得分】

两台电脑共享文件设置

步骤一:确保网络连接正常,可网线直连。 两台电脑IP设置,例: 步骤二:启用共享功能。 1.在【控制面板】中选择【网络和Internet】; 2.点击【网络和共享中心】,在左侧导航栏中,点击【…

政府网站之守护:如何确保信息真实与透明,避免政治风险?

在数字化时代,政府网站已经成为公众获取官方信息和政府政策的主要途径。确保这些信息的真实性、透明性和及时性是维护 政府公信力的关键。特别是在涉及落马官员、政治敏感信息等内容时,更需要加强审查与管理,避免带来不必要的政治风险。 那…

视频云存储/安防监控/AI视频智能分析网关V3:工服检测功能详解

在一些工地、后厨、化工、电力等特定的场景中,工服的穿戴是必不可少的。这不仅是安全制度的要求,更能降低工作风险、提高工作效率。TSINGSEE青犀AI 边缘计算网关硬件 —— 智能分析网关可以通过实时监测和识别工人的工装穿戴情况,确保他们符合…

DBeaver 23.1.5 发布

导读DBeaver 是一个免费开源的通用数据库工具,适用于开发人员和数据库管理员。DBeaver 23.1.5 现已发布,更新内容如下. Data editor 重新设计了词典查看器面板 UI 空间数据类型:曲线几何线性化已修复 数据保存时结果选项卡关闭的问题已解决…

springboot实战(三)之多环境部署配置文件生效方式

环境: jdk:1.8 springboot版本:2.7.15 配置: 1.新建yml文件 在resources包中创建application-dev.yml、application-testing.yml两个yml文件 2.配置 在application.yml进行配置生效文件 3.注意事项 新建yml的名称必须以&qu…

GBDT,XGBoost算法理解

pyspark实现GBDT 参考资料: datawhalechina/ensemble-learning (github.com)

Stable Diffusion 从入门到企业级应用0401

一、概述 本章是《Stable Diffusion 从入门到企业级实战》系列的第四部分能力进阶篇《Stable Diffusion ControlNet v1.1 图像精准控制》第01节, 利用Stable Diffusion ControlNet Inpaint模型精准控制图像生成。本部分内容,位于整个Stable Diffusion生…

java 多个list取交集

java 多个list集合根据某个字段取出交集 模拟多个list集合,如下图 如果只有一个集合那么交集就是当前集合,如果有多个集合,那么第一个集合当做目标集合,在通过目标集合去和剩下的集合比较,取出相同的值,运…

CAR-T商品化的第一步

1、CAR-T细胞的体外扩增能力 CAR-T细胞疗法需要先从患者体内获得T淋巴细胞,然后通过体外转基因技术 transduce CAR靶向结构域。这一过程需要在细胞培养体系中得到充分的扩增,以获得足够的治疗CAR-T细胞数量。因此,CAR-T细胞的体外扩增能力直…

邮箱授权码的获取(以qq邮箱为例)

第一步,登录你需要授权的邮箱(如登录qq邮箱主页面) 第二步,点击设置,选择账号 往下拉,找到POP3等服务中的服务状态,点击开启服务 在通过认证后得到授权码 在一些第三方登录中我们通过这个授权码…

想跳槽?先别急!这5个问题搞懂再离职也不迟!

创建坐席组的功能模块,如何进行测试用例设计? 解答: 功能测试,使用等价类划分法去分析创建坐席的每个输入项的有效及无效类,同步考虑边界值去设计对应的测试用例: 先进行冒烟测试,正常创建坐席…

如何让视频小于50m?最新视频压缩技巧分享

在我们的日常生活中,视频文件经常占据较大的存储空间,给我们存储和传输带来了困扰,那么如何将视频文件压缩至50m以下呢?下面就为大家分享三个实用的方法,轻松解决视频过大问题。 方法一:调整视频分辨率 视…

用小额贷款产品微粒贷借钱靠谱方便,应急周转值得一试

平时资金周转应急,除了找亲戚朋友之外,要说用着放心靠谱的渠道,小编是相当认可微粒贷的。微粒贷作为微众银行旗下的小额贷款,正规可靠,值得信赖。接下来做个详细介绍,平时有资金应急周转需要的小伙伴&#…

掌握Linkedin营销小技巧,再也不愁客户

众所周知,Linkedin是发展业务、拓展人脉的好地方,在过去的一年里,93%的B2B营销人员最常使用该平台来有机分发内容。Linkedin也因为能产生较好的营销效果而成为跨境业务开发的选择平台。 有些企业可以使用Linkedin向潜在用户进行营销和接触&a…

如何在`Pycharm`中配置基于WSL的`Python Interpreters`,以及配置基于WSL的`Terminal`

文章目录 一、创建pycharm用户并授予sudo权限0. 启动WSL下的CentOS1. 创建pycharm用户并授予sudo权限2. 设置pycharm用户为wsl启动Linux的默认用户3. 重启并重新登录wsl下的CentOS4. 验证pycharm用户的sudo权限 二、创建基于WSL的Python Interpreter1. 添加基于WSL的Python Int…