计算机视觉实验

文章详细介绍了如何使用Python代码实现Harris角点检测和SIFT特征提取,并对比了两者在图像处理中的差异。Harris角点检测算法简单但不具尺度不变性,而SIFT算法则提供了尺度不变性和更好的旋转、亮度鲁棒性,适合于图像匹配和识别任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.实现Harris角点检测与SIFT特征提取,对比两者的区别

图片处理代码实现:

from PIL import Image
from numpy import *
from scipy.ndimage import filters
from pylab import *


def compute_harris_response(im,sigma=3): 
 """ 在一幅灰度图像中,对每个像素计算 Harris 角点检测器响应函数 """
 # 计算导数
 imx = zeros(im.shape)
 filters.gaussian_filter(im, (sigma,sigma), (0,1), imx)
 imy = zeros(im.shape)
 filters.gaussian_filter(im, (sigma,sigma), (1,0), imy)
 # 计算 Harris 矩阵的分量
 Wxx = filters.gaussian_filter(imx*imx,sigma)
 Wxy = filters.gaussian_filter(imx*imy,sigma)
 Wyy = filters.gaussian_filter(imy*imy,sigma)
 # 计算特征值和迹
 Wdet = Wxx*Wyy - Wxy**2
 Wtr = Wxx + Wyy
 return Wdet / Wtr



def get_harris_points(harrisim,min_dist=10,threshold=0.2):
 # 寻找高于阈值的候选角点
 corner_threshold = harrisim.max() * threshold
 harrisim_t = (harrisim > corner_threshold) * 1
 
 # 得到候选点的坐标
 coords = array(harrisim_t.nonzero()).T
 # 以及它们的 Harris 响应值
 candidate_values = [harrisim[c[0],c[1]] for c in coords]
 # 对候选点按照 Harris 响应值进行排序
 index = argsort(candidate_values)
 # 将可行点的位置保存到数组中
 allowed_locations = 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



def plot_harris_points(image,filtered_coords): 
    figure()
    gray()
    imshow(image)
    plot([p[1] for p in filtered_coords],[p[0] for p in filtered_coords],'*')
    axis('off')
    show()

其中 正在get_harris_points  中可以修改阈值

以下是测试的代码: 

im = array(Image.open('D:/WXC/ima/outlook.jpg').convert('L'))
harrisim = compute_harris_response(im)
filtered_coords = get_harris_points(harrisim,10)
plot_harris_points(im, filtered_coords)

实验结果:阈值分别为(0.02,0.06,0.1,0.2)

 SIFT提取特征值

主函数:

from PIL import Image
from pylab import *
from PCV.localdescriptors import sift

imname = 'outlook.jpg'
im1 = array(Image.open(imname).convert('L'))
sift.process_image(imname,'outlook.sift')
l1,d1 = sift.read_features_from_file('outlook.sift')
figure()
gray()
sift.plot_features(im1,l1,circle=True)
show()

 然后相关的sift是独立一个包

安装过程:

下载VLFEAT和PCV库,在PCV库中localdescriptors中有sift文件,用记事本打开修改一下

重点是cmmd这地方,把前面的地址改成你下载VLFEAT文件下的sift.exe 

(记得先把sift.exe和dll文件复制一份到你的Python项目下)

还有一个就是修改print加个括号,因为之前它版本是2,现在都是3.8左右。

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("D:/360安全浏览器下载/vlfeat-0.9.20-bin/vlfeat-0.9.20/bin/win64/sift.exe "+imagename+" --output="+resultname+
                " "+params)
    os.system(cmmd)
    print ('processed', imagename, 'to', resultname)

还有一种是cv: 

sift.py中相关代码不做解释,课本都有。

区别 

 用 Harris 算法进行检测,有三点不足:(1)不具有尺度不变性;(2)提取的角点是像素级的;(3)算法检测时间较长,实时应用效果较差。

        Harris 算子是一种有效的点特征提取算子,其优点总结起来有: ①计算简单:Harris 算子中只用到灰度的一阶差分以及滤波,操作简单。②提取的点特征均匀而且合理:Harris算子对图像中的每个点都计算其兴趣值,然后在邻域中选择最优点。实验表明,在纹理信息丰富的区域,Harris 算子可以提取出大量有用的特征点,而在纹理信息少的区域,提取的特征点则较少。③稳定:Harris算子的计算公式中只涉及到一阶导数,因此对图像旋转、灰度变化、噪声影响和视点变换不敏感,它也是比较稳定的一种点特征提取算子。

        Harris 算子的局限性有:①它对尺度很敏感,不具有尺度不变性。②提取的角点是像素级的。

 尺度不变特征变换(Scale-invariantfeature transform),主要特点在于其多尺度信息描述,能够有效描述缩放,并且对 图像旋转、亮度、仿射变换、视角变化具有很好的适应性。

SIFT算法还具有如下一些特点:

1. 信息量丰富,即使少数的几个物体也可以产生大量的SIFT特征向量;

2. 特征区分度大,适用于在海量特征数据库中进行快速、准确的匹配;

3. 速度快,加速的SIFT算法可以达到实时。
 

 利用SIFT算法实现两幅相近图像的特征匹配

代码:

im1f = 'palace1.png'
im2f = 'palace2.png'
im1 = array(Image.open(im1f))
im2 = array(Image.open(im2f))

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()

效果:

 实现匹配地理标记图像

书上代码是长这样的:

import urllib.parse
import urllib.request
import simplejson as json
from urllib import parse
# 查询图像
url ='http://www.panoramio.com/map/get_panoramas.php?order=popularity&\set=public&from=0&to=20&minx=-77.037564&miny=38.896662&\maxx=-77.035564&maxy=38.898662&size=medium'
c = urllib.request.urlopen(url)
# 从 JSON 中获得每个图像的 url
j = json.loads(c.read())
imurls = []
for im in j['photos']:
 imurls.append(im['photo_file_url'])

for url in imurls:
 image = urllib.request.URLopener()
 image.retrieve(url, os.path.basename(urllib.parse.urlparse(url).path))
 print ('downloading:', url)

 但是根本下载不下来,因为是外网所以一直响应失败,因此需要自行寻找图片存储然后运行。

from pylab import *
from PIL import Image
from PCV.localdescriptors import sift
from PCV.tools import imtools
import pydot


download_path = r"D:/WXC/WEBK/img"
path = r"D:/WXC/WEBK/imgsave"

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 triangle
        print('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 diagonal
        matchscores[j, i] = matchscores[i, j]


threshold = 2  # min number of matches needed to create link

g = pydot.Dot(graph_type='graph')  # don't want the default directed graph

for i in range(nbr_images):
    for j in range(i + 1, nbr_images):
        if matchscores[i, j] > threshold:
            # first image in pair
            im = Image.open(imlist[i])
            im.thumbnail((100, 100))
            filename = path + str(i) + '.jpg'
            im.save(filename)  # need temporary files of the right size
            g.add_node(pydot.Node(str(i), fontcolor='transparent', shape='rectangle', image=filename))

            # second image in pair
            im = Image.open(imlist[j])
            im.thumbnail((100, 100))
            filename = path + str(j) + '.jpg'
            im.save(filename)  # need temporary files of the right size
            g.add_node(pydot.Node(str(j), fontcolor='transparent', shape='rectangle', image=filename))
            g.add_edge(pydot.Edge(str(i), str(j)))
g.write_png('Disneyland.jpg')

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值