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

来源:互联网 发布:淘宝网运动鞋女款秋冬 编辑:程序博客网 时间:2024/05/16 19:11

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 imageimage = 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" executablef = fopen('tmp.pgm', 'w');if f == -1    error('Could not create file tmp.pgm.');endfprintf(f, 'P5\n%d\n%d\n255\n', cols, rows);fwrite(f, image', 'uint8');fclose(f);% Call keypoints executableif isunix    command = '!./sift ';else    command = '!siftWin32 ';endcommand = [command ' <tmp.pgm >tmp.key'];eval(command);% Open tmp.key and check its headerg = 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.');endnum = 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.keyfor 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, :);endfclose(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 cv2import numpy as npimport pdbpdb.set_trace()#turn on the pdb prompt#read imageimg = cv2.imread('E:\OpenCV\Picture\sky.jpg',cv2.IMREAD_COLOR)gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)cv2.imshow('origin',img);#SIFTdetector = 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;}

这里写图片描述

这里写图片描述

这里写图片描述

0 0
原创粉丝点击