您的位置:首页 > 其它

图像算法之三:特征提取算子之SIFT

2016-09-27 14:49 417 查看
SIFT(Scale-invariant feature transform)是一种检测局部特征的算法,该算法通过求一幅图中的特征点(interest points,or corner points)及其有关scale 和 orientation 的描述子得到特征并进行图像特征点匹配,获得了良好效果,详细解析如下:

1、算法描述

SIFT特征不只具有尺度不变性,即使改变旋转角度,图像亮度或拍摄视角,仍然能够得到好的检测效果。整个算法分为以下几个部分:

(1)构造尺度空间:DoG尺度空间

(2)检测DoG尺度空间极值点

(3)去除不好的特征点

(4)给特征点赋值一个128维的方向参数。每个关键点都包含三个信息:位置、尺度和方向。

(5)关键点描述子的生成:

首先将坐标轴旋转为关键点的方向,以确保旋转不变性。以关键点为中心取8×8的窗口。

(6)最后进行特征匹配。当两幅图像的SIFT特征向量(128维)生成后,采用关键点特征向量的欧式聚类来作为相似性判定度量。

取图像1中的某个关键点,并找出其与图像2中欧式距离最近的前两个关键点,在这两个关键点中,如果最近的距离除以次近的距离少于某个比例阈值,则接受这一对匹配点。降低这个比例阈值,SIFT匹配点数目会减少,但更加稳定。

2、算法实现:

(一) SIFT的Matlab代码实现:

% [image, descriptors, locs] = sift(imageFile)
%
% This function reads an image and returns its SIFT keypoints.
%   Input parameters:
%     imageFile: the file name for the image.
%
%   Returned:
%     image: the image array in double format
%     descriptors: a K-by-128 matrix, where each row gives an invariant
%         descriptor for one of the K keypoints.  The descriptor is a vector
%         of 128 values normalized to unit length.
%     locs: K-by-4 matrix, in which each row has the 4 values for a
%         keypoint location (row, column, scale, orientation).  The
%         orientation is in the range [-PI, PI] radians.
%
% Credits: Thanks for initial version of this program to D. Alvaro and
%          J.J. Guerrero, Universidad de Zaragoza (modified by D. Lowe)

function [image, descriptors, locs] = sift(imageFile)

% Load image
image = imread(imageFile);

% If you have the Image Processing Toolbox, you can uncomment the following
%   lines to allow input of color images, which will be converted to grayscale.
% if isrgb(image)
%    image = rgb2gray(image);
% end

[rows, cols] = size(image);

% Convert into PGM imagefile, readable by "keypoints" executable
f = fopen('tmp.pgm', 'w');
if f == -1
error('Could not create file tmp.pgm.');
end
fprintf(f, 'P5\n%d\n%d\n255\n', cols, rows);
fwrite(f, image', 'uint8');
fclose(f);

% Call keypoints executable
if isunix
command = '!./sift ';
else
command = '!siftWin32 ';
end
command = [command ' <tmp.pgm >tmp.key'];
eval(command);

% Open tmp.key and check its header
g = fopen('tmp.key', 'r');
if g == -1
error('Could not open file tmp.key.');
end
[header, count] = fscanf(g, '%d %d', [1 2]);
if count ~= 2
error('Invalid keypoint file beginning.');
end
num = header(1);
len = header(2);
if len ~= 128
error('Keypoint descriptor length invalid (should be 128).');
end

% Creates the two output matrices (use known size for efficiency)
locs = double(zeros(num, 4));
descriptors = double(zeros(num, 128));

% Parse tmp.key
for i = 1:num
[vector, count] = fscanf(g, '%f %f %f %f', [1 4]); %row col scale ori
if count ~= 4
error('Invalid keypoint file format');
end
locs(i, :) = vector(1, :);

[descrip, count] = fscanf(g, '%d', [1 len]);
if (count ~= 128)
error('Invalid keypoint file value.');
end
% Normalize each input vector to unit length
descrip = descrip / sqrt(sum(descrip.^2));
descriptors(i, :) = descrip(1, :);
end
fclose(g);


使用方法:

1.寻找图像中的sift特征:

[image,descrips,locs] = sift('scene.pgm');
showkeys(image,locs);




scene.pgm



book.pgm

2、对两幅图中的sift特征进行匹配



match(‘scene.pgm’,’book.pgm’);

由于scene和book两幅图中有相同的一本书,但是方向和尺度都不同,从匹配结果可以看出去sift特征匹配检测效果非常好滴!

关于SIFT的其他讲解:

http://blog.csdn.net/abcjennifer/article/details/7639681

http://blog.csdn.net/abcjennifer/article/details/7372880

http://blog.csdn.net/abcjennifer/article/details/7365882

(二)SIFT的Python实现:

import cv2
import numpy as np
import pdb
pdb.set_trace()#turn on the pdb prompt

#read image
img = cv2.imread('E:\OpenCV\Picture\sky.jpg',cv2.IMREAD_COLOR)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow('origin',img);

#SIFT
detector = cv2.SIFT() #调用SIFT特征描述子
keypoints = detector.detect(gray,None)#检测兴趣点
img = cv2.drawKeypoints(gray,keypoints)#画出兴趣点
#img = cv2.drawKeypoints(gray,keypoints,flags = cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imshow('test',img);
cv2.waitKey(0)
cv2.destroyAllWindows()


测试:

实验结果:



(三)SIFT的OpenCV实现

#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/legacy/legacy.hpp>
#include <opencv2/nonfree/nonfree.hpp>
#include <vector>
using namespace std;
using namespace cv;
int main(void)
{
cout << "当前使用的OpenCV版本:" << CV_VERSION << endl;
Mat image = imread("scene.pgm");
Mat image2 = imread("book.pgm");
if (image.empty())
{
fprintf(stderr, "Cannot load image %s \n", "scene.pgm");
return -1;
}
if (image2.empty())
{
fprintf(stderr, "Cannot load image %s \n", "book.pgm");
return -1;
}
//显示图像
imshow("image before", image);
waitKey(10);
imshow("image2 before", image2);
waitKey(10);
//sift特征点检测
SiftFeatureDetector siftdtc;
vector<KeyPoint> kp1, kp2;
siftdtc.detect(image, kp1);
Mat outimg1;
drawKeypoints(image, kp1, outimg1);
imshow("image1 keypoints", outimg1);
siftdtc.detect(image2, kp2);
Mat outimg2;
drawKeypoints(image2, kp2, outimg2);
imshow("image2 keypoints", outimg2);
//生成描述子
SiftDescriptorExtractor ext;
Mat descp1, descp2;
BruteForceMatcher<L2<float>> matcher;
vector<DMatch> matches;
Mat img_matches;
ext.compute(image, kp1, descp1);
ext.compute(image2, kp2, descp2);
imshow("desc", descp1);
waitKey(10);
//cout << endl << descp1 << endl;
matcher.match(descp1, descp2, matches);

drawMatches(image, kp1, image2, kp2, matches, img_matches);
imshow("matches", img_matches);
waitKey(10);
//namedWindow("My Image");
//imshow("My Image",image);
//waitKey(0);
//Mat result,image2,image3;
//result = image;
//image2 = result;
//result.copyTo(image3);
//flip(image, result, 1);//正数水平翻转,0表示垂直翻转,负数表示既有水平也有垂直翻转
//namedWindow("Output window");
//imshow("Output window", result);
//namedWindow("1");
//imshow("1", image2);
//namedWindow("2");
//imshow("2", image3);
waitKey(0);
return 0;
}






内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: