siftjava实现的简单介绍

博主:adminadmin 2022-11-24 13:12:10 50

本篇文章给大家谈谈siftjava实现,以及对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

java opencv 怎样确定sift 匹配结果

这几天继续在看Lowe大神的SIFT神作,看的眼花手脚抽筋。也是醉了!!!!实在看不下去,来点干货。我们知道opencv下自带SIFT特征检测以及MATCH匹配的库,这些库完全可以让我们进行傻瓜似的操作。但实际用起来的时候还不是那么简单。下文将对一个典型的基于OPENCV的SIFT特征点提取以及匹配的例程进行分析,并由此分析详细的对OPENCV中SIFT算法的使用进行一个介绍。

OPENCV下SIFT特征点提取与匹配的大致流程如下:

读取图片-》特征点检测(位置,角度,层)-》特征点描述的提取(16*8维的特征向量)-》匹配-》显示

其中,特征点提取主要有两个步骤,见上行黄子部分。下面做具体分析。

1、使用opencv内置的库读取两幅图片

2、生成一个SiftFeatureDetector的对象,这个对象顾名思义就是SIFT特征的探测器,用它来探测衣服图片中SIFT点的特征,存到一个KeyPoint类型的vector中。这里有必要说keypoint的数据结构,涉及内容较多,具体分析查看opencv中keypoint数据结构分析,里面讲的自认为讲的还算详细(表打我……)。简而言之最重要的一点在于:

keypoint只是保存了opencv的sift库检测到的特征点的一些基本信息,但sift所提取出来的特征向量其实不是在这个里面,特征向量通过SiftDescriptorExtractor 提取,结果放在一个Mat的数据结构中。这个数据结构才真正保存了该特征点所对应的特征向量。具体见后文对SiftDescriptorExtractor 所生成的对象的详解。

就因为这点没有理解明白耽误了一上午的时间。哭死!

3、对图像所有KEYPOINT提取其特征向量:

得到keypoint只是达到了关键点的位置,方向等信息,并无该特征点的特征向量,要想提取得到特征向量就还要进行SiftDescriptorExtractor 的工作,建立了SiftDescriptorExtractor 对象后,通过该对象,对之前SIFT产生的特征点进行遍历,找到该特征点所对应的128维特征向量。具体方法参见opencv中SiftDescriptorExtractor所做的SIFT特征向量提取工作简单分析。通过这一步后,所有keypoint关键点的特征向量被保存到了一个MAT的数据结构中,作为特征。

4、对两幅图的特征向量进行匹配,得到匹配值。

两幅图片的特征向量被提取出来后,我们就可以使用BruteForceMatcher对象对两幅图片的descriptor进行匹配,得到匹配的结果到matches中,这其中具体的匹配方法暂没细看,过段时间补上。

至此,SIFT从特征点的探测到最后的匹配都已经完成,虽然匹配部分不甚了解,只扫对于如何使用OPENCV进行sift特征的提取有了一定的理解。接下来可以开始进行下一步的工作了。

附:使用OPENCV下SIFT库做图像匹配的例程

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

// opencv_empty_proj.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"

#include opencv.hpp

#include features2d/features2d.hpp

#includenonfree/nonfree.hpp

#includelegacy/legacy.hpp

#include

using namespace std;

using namespace cv;

int _tmain(int argc, _TCHAR* argv[])

{

const char* imagename = "img.jpg";

//从文件中读入图像

Mat img = imread(imagename);

Mat img2=imread("img2.jpg");

//如果读入图像失败

if(img.empty())

{

fprintf(stderr, "Can not load image %s\n", imagename);

return -1;

}

if(img2.empty())

{

fprintf(stderr, "Can not load image %s\n", imagename);

return -1;

}

//显示图像

imshow("image before", img);

imshow("image2 before",img2);

//sift特征检测

SiftFeatureDetector siftdtc;

vectorkp1,kp2;

siftdtc.detect(img,kp1);

Mat outimg1;

drawKeypoints(img,kp1,outimg1);

imshow("image1 keypoints",outimg1);

KeyPoint kp;

vector::iterator itvc;

for(itvc=kp1.begin();itvc!=kp1.end();itvc++)

{

cout"angle:"angle"\t"class_id"\t"octave"\t"pt"\t"responseendl;

}

siftdtc.detect(img2,kp2);

Mat outimg2;

drawKeypoints(img2,kp2,outimg2);

imshow("image2 keypoints",outimg2);

SiftDescriptorExtractor extractor;

Mat descriptor1,descriptor2;

BruteForceMatcherL2 matcher;

vector matches;

Mat img_matches;

extractor.compute(img,kp1,descriptor1);

extractor.compute(img2,kp2,descriptor2);

imshow("desc",descriptor1);

coutendldescriptor1endl;

matcher.match(descriptor1,descriptor2,matches);

drawMatches(img,kp1,img2,kp2,matches,img_matches);

imshow("matches",img_matches);

//此函数等待按键,按键盘任意键就返回

waitKey();

return 0;

}

使用Java语言进行图像编程处理(涉及SIFT算法),是该学习Javacv、swt吗?求教大师~~

应该先从你兴趣开始,有兴趣再决定编程领域,有了编程领域在决定语言.

不同的语言对应着不同编程领域,如果你要学完那是有点不现实.

因此你要回想一下你兴趣来源是什么?比如喜欢做黑客,喜欢研究反病毒,喜欢为Windows桌面开发一些实用的小软件等等.

要分析好兴趣来由,在决定你的发展方向,就好了.

比如你喜欢为WINDOWS开发软件,那么 C语言是必备基础,学好好了然后在扩展一门面向对象的语言比如C++ C# JAVA 等.这些是不错的选择。

然后光有语言不行,为了软件的质量保证,还需要研究一下系统理论基础,这样你的软件才能做到对系统的作家兼容性和获取最佳性能。

也可百度一下, 80x86汇编小站, 这个网站里面有几篇关于编程入门文章或许会对你有帮助, 或者 你直接联系 这个站长 跟他交流编程方面的事情。 赞同

0| 评论

2011-10-30 13:44 诺言已成空白 | 二级

java stl priorityq 是通过heap实现的吗

下面的_First与_Last为可以随机访问的迭代器(指针),_Comp为比较函数(仿函数),其规则——如果函数的第一个参数小于第二个参数应返回true,否则返回false。

1.make_heap():

make_heap(_First, _Last)

make_heap(_First, _Last, _Comp)

默认是建立最大堆的。对int类型,可以在第三个参数传入greaterint()得到最小堆。

2.push_heap(_First, _Last):

新添加一个元素在末尾,然后重新调整堆序。也就是把元素添加在底层vector的end()处。

该算法必须是在一个已经满足堆序的条件下,添加元素。该函数接受两个随机迭代器,分别表示first,end,区间范围。

关键是我们执行一个siftup()函数,上溯函数来重新调整堆序。具体的函数机理很简单,可以参考我的编程珠玑里面堆的实现的文章。

3.pop_heap(_First, _Last):

这个算法跟push_heap类似,参数一样。不同的是我们把堆顶元素取出来,放到了数组或者是vector的末尾,用原来末尾元素去替代,然后end迭代器减1,执行siftdown()下溯函数来重新调整堆序。

注意算法执行完毕后,最大的元素并没有被取走,而是放于底层容器的末尾。如果要取走,则可以使用底部容器(vector)提供的pop_back()函数。

4.sort_heap(_First, _Last):

既然每次pop_heap可以获得堆中最大的元素,那么我们持续对整个heap做pop_heap操作,每次将操作的范围向前缩减一个元素。当整个程序执行完毕后,我们得到一个非降的序列。注意这个排序执行的前提是,在一个堆上执行。

下面是这几个函数操作vector中元素的例子。

#includeiostream

#includevector

#includealgorithm

using namespace std;

int main()

{

int a[] = {15, 1, 12, 30, 20};

vectorint ivec(a, a+5);

for(vectorint::iterator iter=ivec.begin();iter!=ivec.end();++iter)

cout*iter" ";

coutendl;

make_heap(ivec.begin(), ivec.end());//建堆

for(vectorint::iterator iter=ivec.begin();iter!=ivec.end();++iter)

cout*iter" ";

coutendl;

pop_heap(ivec.begin(), ivec.end());//先pop,然后在容器中删除

ivec.pop_back();

for(vectorint::iterator iter=ivec.begin();iter!=ivec.end();++iter)

cout*iter" ";

coutendl;

ivec.push_back(99);//先在容器中加入,再push

push_heap(ivec.begin(), ivec.end());

for(vectorint::iterator iter=ivec.begin();iter!=ivec.end();++iter)

cout*iter" ";

coutendl;

sort_heap(ivec.begin(), ivec.end());

for(vectorint::iterator iter=ivec.begin();iter!=ivec.end();++iter)

cout*iter" ";

coutendl;

return 0;

}

二、priority queue

优先队列(priority_queue)首先是一个queue,那就是必须在末端推入,必须在顶端取出元素。除此之外别无其他存取元素的途径。 内部元素按优先级高低排序,优先级高的在前。缺省情况下,priority_heap利用一个max-heap完成,后者是一个以vector表现的完全二叉树。 我们说优先队列不是一个STL容器,它以底部容器而实现,修改了接口,形成另一种性质,这样的东西称之为适配器(adapter)。详情参见:

主要函数包括:

bool empty() const

size_type size() const

const_reference top() const

返回顶端元素。不取走。

void push(const value_type x)

内部调用push_back(x)和push_heap()

void pop()

内部调用pop_heap()和pop_back();

在优先队列中,优先级高的元素先出队列。

标准库默认使用元素类型的操作符来确定它们之间的优先级关系。

优先队列的第一种用法,也是最常用的用法:

priority_queueint qi;

通过操作符可知在整数中元素大的优先级高。

第二种方法:

在示例1中,如果我们要把元素从小到大输出怎么办呢?

这时我们可以传入一个比较函数,使用functional.h函数对象作为比较函数。

priority_queueint, vectorint, greaterint qi2;

其中

第二个参数为容器类型。

第三个参数为比较函数。

第三种方法:

自对自定义的数据类型自定义优先级,

1.通过自定义operator操作符来比较元素中的优先级。

struct Node

{

int key;

int value;

bool operator (const Node a,const Node b)

{

return a.keyb.key;

}

bool operator (const Node a,const Node b)

{

return a.keyb.key;

}

};

在该结构中,value为值,priority为优先级,使用示例:

priority_queueNode,vectorNode,lessNode pqLess;

priority_queueNode,vectorNode,greaterNode pqGreater;

2.自定义一个比较“类”,重载括号,operator (),这这种方式可以由less“继承”。

struct Node

{

int key;

int value;

};

struct cmpLess

{

bool operator ()(const Node a,const Node b)

{

return a.keyb.key;

}

};

struct cmpGreater

{

bool operator ()(const Node a,const Node b)

{

return a.keyb.key;

}

};

使用示例:

priority_queueNode,vectorNode,cmpLess pqLess;

priority_queueNode,vectorNode,cmpGreater pqGreater;

一个简单的例子如下:

#includeiostream

#includevector

#includequeue

#includefunctional

using namespace std;

int main()

{

const int len = 5;

int i;

int a[len] = {3,5,9,6,2};

priority_queueint qi;

for(i = 0; i len; i++)

qi.push(a[i]);

for(i = 0; i len; i++)

{

coutqi.top()" ";

qi.pop();

}

coutendl;

priority_queueNode,vectorNode,lessnode pq2;

//priority_queueNode,vectorNode,cmpLess pq2;

vectorNode b(len);

b[0].key = 6; b[0].value = 1;

b[1].key = 9; b[1].value = 5;

b[2].key = 2; b[2].value = 3;

b[3].key = 8; b[3].value = 2;

b[4].key = 1; b[4].value = 4;

for(i = 0; i len; i++)

pq2.push(b[i]);

cout"优先级"'\t'"值"endl;

for(i = 0; i len; i++)

{

coutpq2.top().key'\t'pq2.top().valueendl;

pq2.pop();

}

return 0;

}

如何使用SIFT进行角点匹配?

一、特征点(角点)匹配

图像匹配能够应用的场合非常多,如目标跟踪,检测,识别,图像拼接等,而角点匹配最核心的技术就要属角点匹配了,所谓角点匹配是指寻找两幅图像之间的特征像素点的对应关系,从而确定两幅图像的位置关系。

角点匹配可以分为以下四个步骤:

1、提取检测子:在两张待匹配的图像中寻找那些最容易识别的像素点(角点),比如纹理丰富的物体边缘点等。

2、提取描述子:对于检测出的角点,用一些数学上的特征对其进行描述,如梯度直方图,局部随机二值特征等。检测子和描述子的常用提取方法有:sift,harris,surf,fast,agast,brisk,freak,brisk,brief/orb等。

3、匹配:通过各个角点的描述子来判断它们在两张图像中的对应关系,常用方法如 flann等。

4、消噪:去除错误匹配的外点,保留正确的匹配点。常用方法有KDTREE,BBF,Ransac,GTM等。

二、SIFT匹配方法的提出

为了排除因为图像遮挡和背景混乱而产生的无匹配关系的关键点,SIFT的作者Lowe提出了比较最近邻距离与次近邻距离的SIFT匹配方式:取一幅图像中的一个SIFT关键点,并找出其与另一幅图像中欧式距离最近的前两个关键点,在这两个关键点中,如果最近的距离除以次近的距离得到的比率ratio少于某个阈值T,则接受这一对匹配点。因为对于错误匹配,由于特征空间的高维性,相似的距离可能有大量其他的错误匹配,从而它的ratio值比较高。显然降低这个比例阈值T,SIFT匹配点数目会减少,但更加稳定,反之亦然。

Lowe推荐ratio的阈值为0.8,但作者对大量任意存在尺度、旋转和亮度变化的两幅图片进行匹配,结果表明ratio取值在0. 4~0. 6 之间最佳,小于0. 4的很少有匹配点,大于0. 6的则存在大量错误匹配点,所以建议ratio的取值原则如下:

ratio=0. 4:对于准确度要求高的匹配;

ratio=0. 6:对于匹配点数目要求比较多的匹配;

ratio=0. 5:一般情况下。

三、常见的SIFT匹配代码

1、vlfeat中sift toolbox中的vl_ubcmatch.c使用的是普通的欧氏距离进行匹配(该SIFT代码贡献自Andrea

Vedaldi)。

2、Lowe的C++代码中使用的是欧氏距离,但是在matlab代码中为了加速计算,使用的是向量夹角来近似欧氏距离:先将128维SIFT特征向量归一化为单位向量(每个数除以平方和的平方根),然后点乘来得到向量夹角的余弦值,最后利用反余弦(acos函数)求取向量夹角。实验证明Lowe的办法正确率和耗时都很不错。

同样,也可以采用knnsearch函数求最近点和次近点:knnsearch采用euclidean距离时得到的结果与lowe采用的近似方法结果几乎一致,正好印证了模拟欧氏距离的效果。

3、Rob Hess的OpenSIFT采用了KDTREE来对匹配进行优化。

4、CSDN大神v_JULY_v实现了KDTREE+BBF对SIFT匹配的优化和消除错误匹配:从K近邻算法、距离度量谈到KD树、SIFT+BBF算法

- 结构之法 算法之道 - 博客频道 - CSDN.NET。

5、OpenCV中features2d实现的SIFT匹配有多种matcher:VectorDescriptorMatcher,BFMatcher(Brute-force descriptor matcher),FernDescriptorMatcher,OneWayDescriptorMatcher,FlannBasedMatcher 等等。目前只知道采用knnsearch,提供了多种距离度量方式,具体区别不懂。

 

写一个简单的JAVA排序程序

// 排序

public class Array

{

public static int[] random(int n) //产生n个随机数,返回整型数组

{

if (n0)

{

int table[] = new int[n];

for (int i=0; itable.length; i++)

table[i] = (int)(Math.random()*100); //产生一个0~100之间的随机数

return table; //返回一个数组

}

return null;

}

public static void print(int[] table) //输出数组元素

{

if (table!=null)

for (int i=0; itable.length; i++)

System.out.print(" "+table[i]);

System.out.println();

}

public static void insertSort(int[] table) //直接插入排序

{ //数组是引用类型,元素值将被改变

System.out.println("直接插入排序");

for (int i=1; itable.length; i++) //n-1趟扫描

{

int temp=table[i], j; //每趟将table[i]插入到前面已排序的序列中

// System.out.print("移动");

for (j=i-1; j-1 temptable[j]; j--) //将前面较大元素向后移动

{

// System.out.print(table[j]+", ");

table[j+1] = table[j];

}

table[j+1] = temp; //temp值到达插入位置

System.out.print("第"+i+"趟: ");

print(table);

}

}

public static void shellSort(int[] table) //希尔排序

{

System.out.println("希尔排序");

for (int delta=table.length/2; delta0; delta/=2) //控制增量,增量减半,若干趟扫描

{

for (int i=delta; itable.length; i++) //一趟中若干组,每个元素在自己所属组内进行直接插入排序

{

int temp = table[i]; //当前待插入元素

int j=i-delta; //相距delta远

while (j=0 temptable[j]) //一组中前面较大的元素向后移动

{

table[j+delta] = table[j];

j-=delta; //继续与前面的元素比较

}

table[j+delta] = temp; //插入元素位置

}

System.out.print("delta="+delta+" ");

print(table);

}

}

private static void swap(int[] table, int i, int j) //交换数组中下标为i、j的元素

{

if (i=0 itable.length j=0 jtable.length i!=j) //判断i、j是否越界

{

int temp = table[j];

table[j] = table[i];

table[i] = temp;

}

}

public static void bubbleSort(int[] table) //冒泡排序

{

System.out.println("冒泡排序");

boolean exchange=true; //是否交换的标记

for (int i=1; itable.length exchange; i++) //有交换时再进行下一趟,最多n-1趟

{

exchange=false; //假定元素未交换

for (int j=0; jtable.length-i; j++) //一次比较、交换

if (table[j]table[j+1]) //反序时,交换

{

int temp = table[j];

table[j] = table[j+1];

table[j+1] = temp;

exchange=true; //有交换

}

System.out.print("第"+i+"趟: ");

print(table);

}

}

public static void quickSort(int[] table) //快速排序

{

quickSort(table, 0, table.length-1);

}

private static void quickSort(int[] table, int low, int high) //一趟快速排序,递归算法

{ //low、high指定序列的下界和上界

if (lowhigh) //序列有效

{

int i=low, j=high;

int vot=table[i]; //第一个值作为基准值

while (i!=j) //一趟排序

{

while (ij vot=table[j]) //从后向前寻找较小值

j--;

if (ij)

{

table[i]=table[j]; //较小元素向前移动

i++;

}

while (ij table[i]vot) //从前向后寻找较大值

i++;

if (ij)

{

table[j]=table[i]; //较大元素向后移动

j--;

}

}

table[i]=vot; //基准值的最终位置

System.out.print(low+".."+high+", vot="+vot+" ");

print(table);

quickSort(table, low, j-1); //前端子序列再排序

quickSort(table, i+1, high); //后端子序列再排序

}

}

public static void selectSort(int[] table) //直接选择排序

{

System.out.println("直接选择排序");

for (int i=0; itable.length-1; i++) //n-1趟排序

{ //每趟在从table[i]开始的子序列中寻找最小元素

int min=i; //设第i个数据元素最小

for (int j=i+1; jtable.length; j++) //在子序列中查找最小值

if (table[j]table[min])

min = j; //记住最小元素下标

if (min!=i) //将本趟最小元素交换到前边

{

int temp = table[i];

table[i] = table[min];

table[min] = temp;

}

System.out.print("第"+i+"趟: ");

print(table);

}

}

private static void sift(int[] table, int low, int high) //将以low为根的子树调整成最小堆

{ //low、high是序列下界和上界

int i=low; //子树的根

int j=2*i+1; //j为i结点的左孩子

int temp=table[i]; //获得第i个元素的值

while (j=high) //沿较小值孩子结点向下筛选

{

if (jhigh table[j]table[j+1]) //数组元素比较(改成为最大堆)

j++; //j为左右孩子的较小者

if (temptable[j]) //若父母结点值较大(改成为最大堆)

{

table[i]=table[j]; //孩子结点中的较小值上移

i=j; //i、j向下一层

j=2*i+1;

}

else

j=high+1; //退出循环

}

table[i]=temp; //当前子树的原根值调整后的位置

System.out.print("sift "+low+".."+high+" ");

print(table);

}

public static void heapSort(int[] table)

{

System.out.println("堆排序");

int n=table.length;

for (int j=n/2-1; j=0; j--) //创建最小堆

sift(table, j, n-1);

// System.out.println("最小堆? "+isMinHeap(table));

for (int j=n-1; j0; j--) //每趟将最小值交换到后面,再调整成堆

{

int temp = table[0];

table[0] = table[j];

table[j] = temp;

sift(table, 0, j-1);

}

}

public static void mergeSort(int[] X) //归并排序

{

System.out.println("归并排序");

int n=1; //已排序的子序列长度,初值为1

int[] Y = new int[X.length]; //Y数组长度同X数组

do

{

mergepass(X, Y, n); //一趟归并,将X数组中各子序列归并到Y中

print(Y);

n*=2; //子序列长度加倍

if (nX.length)

{

mergepass(Y, X, n); //将Y数组中各子序列再归并到X中

print(X);

n*=2;

}

} while (nX.length);

}

private static void mergepass(int[] X, int[] Y, int n) //一趟归并

{

System.out.print("子序列长度n="+n+" ");

int i=0;

while (iX.length-2*n+1)

{

merge(X,Y,i,i+n,n);

i += 2*n;

}

if (i+nX.length)

merge(X,Y,i,i+n,n); //再一次归并

else

for (int j=i; jX.length; j++) //将X剩余元素复制到Y中

Y[j]=X[j];

}

private static void merge(int[] X, int[] Y, int m, int r, int n) //一次归并

{

int i=m, j=r, k=m;

while (ir jr+n jX.length) //将X中两个相邻子序列归并到Y中

if (X[i]X[j]) //较小值复制到Y中

Y[k++]=X[i++];

else

Y[k++]=X[j++];

while (ir) //将前一个子序列剩余元素复制到Y中

Y[k++]=X[i++];

while (jr+n jX.length) //将后一个子序列剩余元素复制到Y中

Y[k++]=X[j++];

}

public static void main(String[] args)

{

// int[] table = {52,26,97,19,66,8,49};//Array.random(9);{49,65,13,81,76,97,38,49};////{85,12,36,24,47,30,53,91,76};//;//{4,5,8,1,2,7,3,6};// {32,26,87,72,26,17};//

int[] table = {13,27,38,49,97,76,49,81}; //最小堆

System.out.print("关键字序列: ");

Array.print(table);

// Array.insertSort(table);

// Array.shellSort(table);

// Array.bubbleSort(table);

// Array.quickSort(table);

// Array.selectSort(table);

// Array.heapSort(table);

// Array.mergeSort(table);

System.out.println("最小堆序列? "+Array.isMinHeap(table));

}

//第9章习题

public static boolean isMinHeap(int[] table) //判断一个数据序列是否为最小堆

{

if (table==null)

return false;

int i = table.length/2 -1; //最深一棵子树的根结点

while (i=0)

{

int j=2*i+1; //左孩子

if (jtable.length)

if (table[i]table[j])

return false;

else

if (j+1table.length table[i]table[j+1]) //右孩子

return false;

i--;

}

return true;

}

}

/*

程序运行结果如下:

关键字序列: 32 26 87 72 26 17 8 40

直接插入排序

第1趟排序: 26 32 87 72 26 17 8 40

第2趟排序: 26 32 87 72 26 17 8 40

第3趟排序: 26 32 72 87 26 17 8 40

第4趟排序: 26 26 32 72 87 17 8 40 //排序算法稳定

第5趟排序: 17 26 26 32 72 87 8 40

第6趟排序: 8 17 26 26 32 72 87 40

第7趟排序: 8 17 26 26 32 40 72 87

关键字序列: 42 1 74 25 45 29 87 53

直接插入排序

第1趟排序: 1 42 74 25 45 29 87 53

第2趟排序: 1 42 74 25 45 29 87 53

第3趟排序: 1 25 42 74 45 29 87 53

第4趟排序: 1 25 42 45 74 29 87 53

第5趟排序: 1 25 29 42 45 74 87 53

第6趟排序: 1 25 29 42 45 74 87 53

第7趟排序: 1 25 29 42 45 53 74 87

关键字序列: 21 12 2 40 99 97 68 57

直接插入排序

第1趟排序: 12 21 2 40 99 97 68 57

第2趟排序: 2 12 21 40 99 97 68 57

第3趟排序: 2 12 21 40 99 97 68 57

第4趟排序: 2 12 21 40 99 97 68 57

第5趟排序: 2 12 21 40 97 99 68 57

第6趟排序: 2 12 21 40 68 97 99 57

第7趟排序: 2 12 21 40 57 68 97 99

关键字序列: 27 38 65 97 76 13 27 49 55 4

希尔排序

delta=5 13 27 49 55 4 27 38 65 97 76

delta=2 4 27 13 27 38 55 49 65 97 76

delta=1 4 13 27 27 38 49 55 65 76 97

关键字序列: 49 38 65 97 76 13 27 49 55 4 //严书

希尔排序

delta=5 13 27 49 55 4 49 38 65 97 76

delta=2 4 27 13 49 38 55 49 65 97 76 //与严书不同

delta=1 4 13 27 38 49 49 55 65 76 97

关键字序列: 65 34 25 87 12 38 56 46 14 77 92 23

希尔排序

delta=6 56 34 14 77 12 23 65 46 25 87 92 38

delta=3 56 12 14 65 34 23 77 46 25 87 92 38

delta=1 12 14 23 25 34 38 46 56 65 77 87 92

关键字序列: 84 12 43 62 86 7 90 91

希尔排序

delta=4 84 7 43 62 86 12 90 91

delta=2 43 7 84 12 86 62 90 91

delta=1 7 12 43 62 84 86 90 91

关键字序列: 32 26 87 72 26 17

冒泡排序

第1趟排序: 26 32 72 26 17 87

第2趟排序: 26 32 26 17 72 87

第3趟排序: 26 26 17 32 72 87

第4趟排序: 26 17 26 32 72 87

第5趟排序: 17 26 26 32 72 87

关键字序列: 1 2 3 4 5 6 7 8

冒泡排序

第1趟排序: 1 2 3 4 5 6 7 8

关键字序列: 1 3 2 4 5 8 6 7

冒泡排序

第1趟排序: 1 2 3 4 5 6 7 8

第2趟排序: 1 2 3 4 5 6 7 8

关键字序列: 4 5 8 1 2 7 3 6

冒泡排序

第1趟排序: 4 5 1 2 7 3 6 8

第2趟排序: 4 1 2 5 3 6 7 8

第3趟排序: 1 2 4 3 5 6 7 8

第4趟排序: 1 2 3 4 5 6 7 8

第5趟排序: 1 2 3 4 5 6 7 8

关键字序列: 38 26 97 19 66 1 5 49

0..7, vot=38 5 26 1 19 38 66 97 49

0..3, vot=5 1 5 26 19 38 66 97 49

2..3, vot=26 1 5 19 26 38 66 97 49

5..7, vot=66 1 5 19 26 38 49 66 97

关键字序列: 38 5 49 26 19 97 1 66

0..7, vot=38 1 5 19 26 38 97 49 66

0..3, vot=1 1 5 19 26 38 97 49 66

1..3, vot=5 1 5 19 26 38 97 49 66

2..3, vot=19 1 5 19 26 38 97 49 66

5..7, vot=97 1 5 19 26 38 66 49 97

5..6, vot=66 1 5 19 26 38 49 66 97

关键字序列: 49 38 65 97 76 13 27 49

0..7, vot=49 49 38 27 13 49 76 97 65

0..3, vot=49 13 38 27 49 49 76 97 65

0..2, vot=13 13 38 27 49 49 76 97 65

1..2, vot=38 13 27 38 49 49 76 97 65

5..7, vot=76 13 27 38 49 49 65 76 97

关键字序列: 27 38 65 97 76 13 27 49 55 4

low=0 high=9 vot=27 4 27 13 27 76 97 65 49 55 38

low=0 high=2 vot=4 4 27 13 27 76 97 65 49 55 38

low=1 high=2 vot=27 4 13 27 27 76 97 65 49 55 38

low=4 high=9 vot=76 4 13 27 27 38 55 65 49 76 97

low=4 high=7 vot=38 4 13 27 27 38 55 65 49 76 97

low=5 high=7 vot=55 4 13 27 27 38 49 55 65 76 97

关键字序列: 38 26 97 19 66 1 5 49

直接选择排序

第0趟排序: 1 26 97 19 66 38 5 49

第1趟排序: 1 5 97 19 66 38 26 49

第2趟排序: 1 5 19 97 66 38 26 49

第3趟排序: 1 5 19 26 66 38 97 49

第4趟排序: 1 5 19 26 38 66 97 49

第5趟排序: 1 5 19 26 38 49 97 66

第6趟排序: 1 5 19 26 38 49 66 97

最小堆

关键字序列: 81 49 76 27 97 38 49 13 65

sift 3..8 81 49 76 13 97 38 49 27 65

sift 2..8 81 49 38 13 97 76 49 27 65

sift 1..8 81 13 38 27 97 76 49 49 65

sift 0..8 13 27 38 49 97 76 49 81 65

13 27 38 49 97 76 49 81 65

sift 0..7 27 49 38 65 97 76 49 81 13

sift 0..6 38 49 49 65 97 76 81 27 13

sift 0..5 49 65 49 81 97 76 38 27 13

sift 0..4 49 65 76 81 97 49 38 27 13

sift 0..3 65 81 76 97 49 49 38 27 13

sift 0..2 76 81 97 65 49 49 38 27 13

sift 0..1 81 97 76 65 49 49 38 27 13

sift 0..0 97 81 76 65 49 49 38 27 13

最大堆

关键字序列: 49 65 13 81 76 27 97 38 49

sift 3..8 49 65 13 81 76 27 97 38 49

sift 2..8 49 65 97 81 76 27 13 38 49

sift 1..8 49 81 97 65 76 27 13 38 49

sift 0..8 97 81 49 65 76 27 13 38 49

97 81 49 65 76 27 13 38 49

sift 0..7 81 76 49 65 49 27 13 38 97

sift 0..6 76 65 49 38 49 27 13 81 97

sift 0..5 65 49 49 38 13 27 76 81 97

sift 0..4 49 38 49 27 13 65 76 81 97

sift 0..3 49 38 13 27 49 65 76 81 97

sift 0..2 38 27 13 49 49 65 76 81 97

sift 0..1 27 13 38 49 49 65 76 81 97

sift 0..0 13 27 38 49 49 65 76 81 97

关键字序列: 52 26 97 19 66 8 49

归并排序

子序列长度n=1 26 52 19 97 8 66 49

子序列长度n=2 19 26 52 97 8 49 66

子序列长度n=4 8 19 26 49 52 66 97

关键字序列: 13 27 38 49 97 76 49 81 65

最小堆序列? true

*/

网上找到的SIFT特征提取代码,怎么使用

哈哈,我有一个基于opencv实现的sift,我把代码贴出来,你自己看看吧~~~

void sift_detector_and_descriptors(IplImage* i_left,IplImage* i_right)

{

Mat mat_image_left=Mat(i_left,false);

Mat mat_image_right=Mat(i_right,false);

cv::SiftFeatureDetector *pDetector=new cv::SiftFeatureDetector;

pDetector-detect(mat_image_left,left_key_point);

pDetector-detect(mat_image_right,right_key_point);

Mat left_image_descriptors,right_image_descriptors;

cv::SiftDescriptorExtractor *descriptor_extractor=new cv::SiftDescriptorExtractor;

descriptor_extractor-compute(mat_image_left,left_key_point,left_image_descriptors);

descriptor_extractor-compute(mat_image_right,right_key_point,right_image_descriptors);

Mat result_l,result_r;

drawKeypoints(mat_image_left,left_key_point,result_l,Scalar::all(-1),0);

drawKeypoints(mat_image_right,right_key_point,result_r,Scalar::all(-1),0);

//imshow("result_of_left_detector_sift",result_l);

//imshow("result_of_right_detector_sift",result_r);

Mat result_of_sift_match;

BruteForceMatcherL2float matcher;

matcher.match(left_image_descriptors,right_image_descriptors,result_of_point_match);

drawMatches(mat_image_left,left_key_point,mat_image_right,right_key_point,result_of_sift_match,result_of_sift_match);

imshow("matches_of_sift",result_of_sift_match);

imwrite("matches_of_sift.jpg",result_of_sift_match);

}

void main()

{

IplImage *n_left_image=cvLoadImage("D:\\lena.jpg");

IplImage *n_right_image=cvLoadImage("D:\\lena_r.jpg");

sift_detector_and_descriptors(n_left_image,n_right_image);

cvWaitKey(0);

}

这就是核心代码了,至于opencv所要用到的库,你自己弄一下吧,每个人的opencv版本不一样,这个都市不同的,希望能够帮到你~

关于siftjava实现和的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

The End

发布于:2022-11-24,除非注明,否则均为首码项目网原创文章,转载请注明出处。