当前位置:  编程技术>移动开发
本页文章导读:
    ▪【转】RSA选用小公钥指数(e=三)真的不安全吗        【转】RSA选用小公钥指数(e=3)真的不安全吗? 引言现有的大部分RSA算法实现都遵循PKCS#1 v2.1/v1.5 (2002/1993)。根据PKCS#1的建议,公钥指数e是可以选取较小的素数3或65537(=2^16+1)。这样选取主要是为.........
    ▪ 施用 SharedPreferences        使用 SharedPreferences SharedPreferences是一种轻量级的数据存储方式,学过Web开发的同学,可以想象它是一个小小的Cookie。它可以用键值对的方式把简单数据类型(boolean、int、float、long和String)存储.........
    ▪ 学习SIFT算法历程中的释疑       学习SIFT算法过程中的释疑介绍SIFT算法的文章 David G. Lowe, "Distinctive image features from scale-invariant keypoints,"International Journal of Computer Vision, 60, 2 (2004), pp. 91-110 文章一开始就给出了sift特征的关.........

[1]【转】RSA选用小公钥指数(e=三)真的不安全吗
    来源: 互联网  发布时间: 2014-02-18
【转】RSA选用小公钥指数(e=3)真的不安全吗?

引言

现有的大部分RSA算法实现都遵循PKCS#1 v2.1/v1.5 (2002/1993)。根据PKCS#1的建议,公钥指数e是可以选取较小的素数3或65537(=2^16+1)。这样选取主要是为了提高加密或签名验证的性能,因为3或65537分别只需要2或17次模乘运算,而一个随机选择的e(假设n是1024-bit)则大约需要1000次。这种选用小公钥指数的方法使用户相信RSA在签名验证和加密操作方面确实要比“以高效著称的ECC”还要高效很多。

 
然而在选用小公钥指数时,有很多人则更倾向于选e=65537而不是e=3,他们认为3“似乎不安全”,然而又给不出所以然。今天我想说的是,在“正确使用”RSA算法的情况下,至今为止还没有发现公开的攻击方法能有效攻击e=3。那么何为正确使用呢?很简单,如果你不是密码专家,那么实现时请遵守PKCS#1 v2.1或IEEE P1363的建议,而不要局限于自己对RSA的教科书式的理解。或者使用公开的密码算法库,如OpenSSL,这些算法的实现一般都会遵守相关标准或建议。

选择e=3究竟有什么问题?

对于e=3的情形,至今以来,其签名验证或加密的性能优势是任何公钥密码算法都无法超越的。但对其所存在的安全脆弱性,我们应实事求是地进行分析,而不要轻易放弃使用e=3。下面我来梳理一下自从1977年RSA算法诞生以来针对小公钥指数(e=3)的密码分析中值得一提的结论。
 
(1) Hastad攻击
 
Hastad描述的攻击经常也被称为广播攻击[1]。
 
攻击场景:如果Alice打算将消息M加密发送给一组用户,并且这组用户选择的公钥指数e=3,那么攻击者Malice可以通过截获3个密文
C1 = M^3 mod N1, C2 = M^3 mod N2, C3 = M^3 mod N3
便能够有效地恢复出明文M。Hastad进一步指出,即使Alice在加密M之前对M进行了f运算(这里f是一个公开的多项式函数),攻击者仍然能有效地恢复出明文M。所以建议在进行消息填充时一定要选择随机化填充方法,比如OAEP[2],而不是一个确定的填充方法。
 
影响:PKCS#1 v2.1和v1.5均不受此攻击的影响。
 
(2) Franklin-Reiter攻击
 
Franklin-Reiter攻击是一种明文相关性攻击[3]。
 
攻击场景:假设Bob的公钥为(3, N),Alice发送消息M1和M2给Bob,并且M1 = f(M2) mod N,f是一个已知的多项式。那么攻击者Malice可以截获密文
C1 = M1^3 mod N, C2 = M2^3 mod N
便能够有效地恢复出明文M。所以建议明文在加密前一定要做随机化处理。
 
影响:PKCS#1 v2.1和v1.5均不受此攻击的影响。
 
(3) Coppersmith攻击
 
首先我们介绍Coppersmith发现的短填充攻击[4]。
 
攻击场景:假设Bob的公钥为(3, N),Alice发送消息M给Bob。消息M的填充方法是遵循PKCS#1 v1.5,即在消息尾部或头部直接填充随机串。如果攻击者截获到Alice发送给Bob的关于消息M的两个不同的密文,即
C1 = (0002||r1||M)^3 mod N, C2 = (0002||r2||M)^3 mod N
如果填充的随机串r的长度低于消息长度的1/9,那么攻击者便能够有效地恢复出明文M。注意该攻击对e = 65537无效。
 
影响:PKCS#1 v2.1不受影响,但PKCS#1 v1.5受此攻击的影响。
 
[补充说明] Coppersmith在密码分析领域做了很多杰出的工作,比如Coppersmith定理[4]已经成为一个密码分析工作的奠基石。
 
Coppersmith定理:令N为大整数,f是度为e的多项式。给定N和f,可以有效地计算出方程f(x)=0 mod N所有小于N^(1/e)的解。
 
应用该定理,另一个简单的攻击如下:当e=3时,给定一个密文,如果攻击者已知2/3的明文比特,则能恢复出整个明文。
 
(4) BDF攻击
 
BDF攻击[5]是针对私钥d在部分暴露之后的攻击。
 
攻击结论:令(N, d)为私钥,N的长度为n-bit。假若d的n/4个低位比特信息被泄露,那么在e < sqrt(N)条件下,攻击者可以有效地恢复出私钥d。
 
另外值得一提的是,如果e = 3,我们很容易知道d的取值范围,而且这个取值范围的区间为sqrt(N)量级。这也就是说,如果e = 3,RSA就天然地泄露了d的一半比特位信息,只不过泄露的是高位比特,而不是低位比特。但是目前还没有发现针对d的高位比特泄露的有效攻击。
 
影响:PKCS#1 v2.1和v1.5均不受此攻击的影响。

(5) 其它攻击

关于RSA的其它相关攻击,如小私钥指数攻击、共模攻击、盲化攻击、时间攻击等,请参见[6, 7].

结论

(I) 对于RSA加密来说,如果在实现上遵循PKCS#1 v2.1 (OAEP填充),目前还没有发现有效的攻击;但如果是遵循PKCS#1 v1.5 (明文尾部直接填充),那么存在Coppersmith攻击。

(II) 对于RSA签名来说,目前对于PKCS#1 v2.1 (PSS填充)和PKCS#1 v1.5 (填充方法:0001FF...FF00||ASN.1||H(M))来说都还没有发现有效的攻击。

综上所述,选用e=3作为RSA的公钥指数,只要使用正确的填充方案,目前仍然是安全的。

关于e=65537的说明

这是一个推荐使用的公钥指数,我认为选这个值的目的只是一个介于低指数攻击和运算效率之间的一个折中考虑,即以防万一"e=3"被攻破而侥幸"e=65537"可能还是安全的。另外,NIST SP800-78 Rev 1 (2007) 也曾强调“不允许使用比65537更低的公钥指数e”,但对于该限制却没有给出任何理由。而PKCS#1却从未有过类似的建议。

参考文献:

[1] J. Hastad, Solving simultaneous modular equations of low degree. SIAM J. of Computing, 17: 336-341, 1988
[2] M. Bellare and P. Rogaway. Optimal asymmetric encryption. In EUROCRYPT'94, LNCS 950, pp 92-111, 1994.
[3] M. Franklin and M. Reiter, Low-exponent RSA with related messages. In EUROCRYPT'96, LNCS 1070, pp 1-9, 1996.
[4] D. Coppersmith. Small solutions to polynomial equations, and low exponent RSA vulnerabilities. Journal of Cryptology, 10: 233-260, 1997.
[5] D. Boneh, G. Durfee, and Y. Frankel. An attack on RSA given a fraction of the private key bits. In AsiaCrypt'98, LNCS 1514, pp 25-34, 1998
[6] D. Boneh, Twenty years of attacks on the RSA cryptosystem, 1999.
[7] http://www.rsa.com/rsalabs/node.asp?id=2216
 

    
[2] 施用 SharedPreferences
    来源: 互联网  发布时间: 2014-02-18
使用 SharedPreferences

SharedPreferences是一种轻量级的数据存储方式,学过Web开发的同学,可以想象它是一个小小的Cookie。它可以用键值对的方式把简单数据类型(boolean、int、float、long和String)存储在应用程序的私有目录下(data/data/包名/shared_prefs/)自己定义的xml文件中。

    SharedPreferences接口主要负责读取应用程序的Preferences数据,它提供了如下常用方法来访问SharedPreferences的key_value键值对。

   

SharedPreferences常用的属性和方法

 

方法名称

描述

public abstract boolean contains (String key)

判断SharedPreferences是否包含特定key的数据

public abstract SharedPreferences.Editor edit ()

返回一个Edit对象用于操作SharedPreferences

public abstract Map<String, ?> getAll ()

获取SharedPreferences数据里全部的key-value对

getXXX(String key,XXX defvlaue)

获取SharedPreferences数据指定key所对应的value,如果该key不存在,返回默认值defValue。其中XXX可以是boolean、float、int、long、String等基本类型的值

 

由于SharedPreference是一个接口,而且在这个接口里并没有提供写入数据和读取数据的能力。但是在其内部有一个Editor内部的接口,Edit这个接口有一系列的方法用于操作SharedPreference。

Editor接口的常用方法

 

方法名称

描述

public abstract SharedPreferences.Editor clear ()

清空SharedPreferences里所有的数据

public abstract boolean commit ()

当Editor编辑完成后,调用该方法可以提交修改,而且必须要调用这个数据才修改

public abstract SharedPreferences.Editor putXXX (String key, boolean XXX)

向SharedPreferences存入指定的key对应的数据,其中XXX可以是boolean、float、int、long、String等基本类型的值

public abstract SharedPreferences.Editor remove (String key)

删除SharedPreferences里指定key对应的数据项

 

SharedPreferences是一个接口,程序是无法创建SharedPreferences实例的,可以通过Context.getSharedPreferences(String name,int mode)来得到一个SharedPreferences实例

name:是指文件名称,不需要加后缀.xml,系统会自动为我们添加上。一般这个文件存储在/data/data/<package name>/shared_prefs下(这个面试常问到)

mode:是指定读写方式,其值有三种,分别为:

Context.MODE_PRIVATE:指定该SharedPreferences数据只能被本应用程序读、写

Context.MODE_WORLD_READABLE:指定该SharedPreferences数据能被其他应用程序读,但不能写

Context.MODE_WORLD_WRITEABLE:指定该SharedPreferences数据能被其他应用程序读写。

Java代码  
  • package com.learn.android;   
  •   
  • import android.app.Activity;   
  •   
  • import android.content.SharedPreferences;   
  • import android.content.SharedPreferences.Editor;   
  • import android.os.Bundle;   
  • import android.view.View;   
  • import android.view.View.OnClickListener;   
  • import android.widget.Button;   
  • import android.widget.EditText;   
  •   
  • public class SharedPreferences_LearnActivity extends Activity {   
  •     EditText edit1;   
  •     EditText edit2;   
  •     Button write;   
  •     Button read;   
  •     SharedPreferences sp;   
  •     Editor edit;   
  •     /** Called when the activity is first created. */  
  •     @Override  
  •     public void onCreate(Bundle savedInstanceState) {   
  •         super.onCreate(savedInstanceState);   
  •         setContentView(R.layout.main);   
  •         initComponent();   
  •         //可以让其他应用程序读取   
  •         sp = this.getSharedPreferences("preferences",MODE_WORLD_READABLE);   
  •         edit = sp.edit();   
  •     }   
  •   
  •     private void initComponent() {   
  •         // TODO Auto-generated method stub   
  •         edit1 = (EditText) this.findViewById(R.id.editText1);   
  •         edit2 = (EditText) this.findViewById(R.id.editText2);   
  •         write = (Button) this.findViewById(R.id.button1);   
  •         read = (Button) this.findViewById(R.id.button2);   
  •         write.setOnClickListener(writeListener);   
  •         read.setOnClickListener(readListener);   
  •     }   
  •     OnClickListener writeListener = new OnClickListener(){   
  •   
  •         @Override  
  •         public void onClick(View arg0) {   
  •             // TODO Auto-generated method stub   
  •             String name = edit1.getText().toString();   
  •             System.out.println("name="+name);   
  •             edit.putString("name",name);   
  •             int count = sp.getInt("count",0);   
  •             System.out.println("count="+count);   
  •             edit.putInt("count",++count);   
  •             edit.commit();   
  •         }   
  •            
  •     };   
  •     OnClickListener readListener = new OnClickListener(){   
  •   
  •         @Override  
  •         public void onClick(View v) {   
  •             // TODO Auto-generated method stub   
  •             String name = sp.getString("name","");   
  •             int count = sp.getInt("count",0);   
  •             edit1.setText(name);   
  •             edit2.setText(count+"");   
  •         }   
  •            
  •     };   
  • }  
  • package com.learn.android;
    
    import android.app.Activity;
    
    import android.content.SharedPreferences;
    import android.content.SharedPreferences.Editor;
    import android.os.Bundle;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    
    public class SharedPreferences_LearnActivity extends Activity {
    	EditText edit1;
    	EditText edit2;
    	Button write;
    	Button read;
    	SharedPreferences sp;
    	Editor edit;
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            initComponent();
            //可以让其他应用程序读取
            sp = this.getSharedPreferences("preferences",MODE_WORLD_READABLE);
            edit = sp.edit();
        }
    
    	private void initComponent() {
    		// TODO Auto-generated method stub
    		edit1 = (EditText) this.findViewById(R.id.editText1);
    		edit2 = (EditText) this.findViewById(R.id.editText2);
    		write = (Button) this.findViewById(R.id.button1);
    		read = (Button) this.findViewById(R.id.button2);
    		write.setOnClickListener(writeListener);
    		read.setOnClickListener(readListener);
    	}
    	OnClickListener writeListener = new OnClickListener(){
    
    		@Override
    		public void onClick(View arg0) {
    			// TODO Auto-generated method stub
    			String name = edit1.getText().toString();
    			System.out.println("name="+name);
    			edit.putString("name",name);
    			int count = sp.getInt("count",0);
    			System.out.println("count="+count);
    			edit.putInt("count",++count);
    			edit.commit();
    		}
    		
    	};
    	OnClickListener readListener = new OnClickListener(){
    
    		@Override
    		public void onClick(View v) {
    			// TODO Auto-generated method stub
    			String name = sp.getString("name","");
    			int count = sp.getInt("count",0);
    			edit1.setText(name);
    			edit2.setText(count+"");
    		}
    		
    	};
    }

     效果图:

     

    读写其他应用SharedPreferences

    在有时的开发过程中,我们可能要访问其他的应用程序的SharedPreferences,要实现这样的功能,我们必须要保证要访问的那个应用程序的SharedPreferences的访问权限要是MODE_WORLD_READABLE,这表明该SharedPreferences可以被其他应用程序读取,如果指定的MODE_WORLD_WRITEABLE表明该SharedPreferences可以被其他应用程序读取写入其实现思路如下

    1、  获得其他应用程序对应的Context

    2、  通过这个Context得到这个应用程序的SharedPreferences,然后再利用这个SharedPreferences读取内容

    以上一例的SharedPreference为例。实现代码:

    Java代码  
  • package com.learn.android;   
  •   
  • import android.app.Activity;   
    • import android.content.Context;   
    • import android.content.SharedPreferences;   
    • import android.content.pm.PackageManager.NameNotFoundException;   
    • import android.view.View;   
    • import android.view.View.OnClickListener;   
    • import android.os.Bundle;   
    • import android.widget.Button;   
    • import android.widget.TextView;   
    •   
    • public class GetOtherSharedPreferencesActivity extends Activity {   
    •     Button button;   
    •     TextView view;   
    •     Context othercontext;   
    •     SharedPreferences sp;   
    •     /** Called when the activity is first created. */  
    •     @Override  
    •     public void onCreate(Bundle savedInstanceState) {   
    •         super.onCreate(savedInstanceState);   
    •         setContentView(R.layout.main);   
    •         button = (Button) this.findViewById(R.id.button1);   
    •         view = (TextView) this.findViewById(R.id.view);   
    •         try {   
    •             othercontext = createPackageContext("com.learn.android",   
    •                     Context.CONTEXT_IGNORE_SECURITY);   
    •             sp = othercontext.getSharedPreferences("preferences",othercontext.MODE_PRIVATE);   
    •         } catch (NameNotFoundException e) {   
    •             // TODO Auto-generated catch block   
    •             e.printStackTrace();   
    •         }   
    •         button.setOnClickListener(l);   
    •     }   
    •     OnClickListener l = new OnClickListener(){   
    •   
    •         @Override  
    •         public void onClick(View v) {   
    •             // TODO Auto-generated method stub   
    •             String name = sp.getString("name","");   
    •             int count = sp.getInt("count",0);   
    •             view.setText("name="+name+"操作次数="+count);   
    •         }   
    •            
    •     };   
    • }  
    package com.learn.android;
    
    import android.app.Activity;
    import android.content.Context;
    import android.content.SharedPreferences;
    import android.content.pm.PackageManager.NameNotFoundException;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.os.Bundle;
    import android.widget.Button;
    import android.widget.TextView;
    
    public class GetOtherSharedPreferencesActivity extends Activity {
    	Button button;
    	TextView view;
    	Context othercontext;
    	SharedPreferences sp;
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            button = (Button) this.findViewById(R.id.button1);
            view = (TextView) this.findViewById(R.id.view);
            try {
    			othercontext = createPackageContext("com.learn.android",
    					Context.CONTEXT_IGNORE_SECURITY);
    			sp = othercontext.getSharedPreferences("preferences",othercontext.MODE_PRIVATE);
    		} catch (NameNotFoundException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
            button.setOnClickListener(l);
        }
        OnClickListener l = new OnClickListener(){
    
    		@Override
    		public void onClick(View v) {
    			// TODO Auto-generated method stub
    			String name = sp.getString("name","");
    			int count = sp.getInt("count",0);
    			view.setText("name="+name+"操作次数="+count);
    		}
        	
        };
    }

     

    SharedPreferences的注意事项:

    编辑完SharedPreferences一定要记得调用Editor的commit()方法,否则不会将数据写入到文件里的。

    回顾总结:

    1、  如何得到SharedPreferences

    SharedPreferences preferences=getPreferences(“test”,MODE_PRIVATE);

    2、  如何编辑SharedPreferences

    得到Editor对象实例

    SharedPreferences.Editor editor=preferences.editor();

    3、  SharedPreferences的存储位置

    /data/data/<package name>/shared_prefs


        
    [3] 学习SIFT算法历程中的释疑
        来源: 互联网  发布时间: 2014-02-18
    学习SIFT算法过程中的释疑

    介绍SIFT算法的文章

    David G. Lowe, "Distinctive image features from scale-invariant keypoints,"International Journal of Computer Vision, 60, 2 (2004), pp. 91-110

    文章一开始就给出了sift特征的关键步骤:

    1. 利用尺度空间,检测极值点

    2. 对极值点(关键点)精确定位,以及剔除一些不好的特征点

    3. 对关键点生成方向参数

    4. 生成关键点的特征描述符


    一开始接触SIFT算法,在这些步骤中,还有很多不理解的地方,看了原文和一些blog,才有点感觉,这里总结下这个过程中的疑问和答案。


    1. 一些基本概念

    2. 为什么是DOG算子,Gaussian算子,为什么不是LOG算子? 

    3. 为什么原图像有时长宽扩大一倍?为什么需要高斯金字塔的降采样,形成octave的形式?

    4. 多尺度是指哪些?

    5. 什么是octave?

    6. 空间尺度的连续性怎么理解?

    7. 对旋转不变性、亮度变化不变性体现在什么地方?


    参考的一些blog,写的真不错:

    http://blog.csdn.net/sunminmin2011/article/details/8130090

    http://wenku.baidu.com/view/dc5fffec102de2bd9605886e.html

    http://www.360doc.com/content/11/1230/23/3054335_176200661.shtml

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

    有关特征的一些概念:

    图像的变化形式: 旋转、尺度变换、仿射变换、视角变换、光照变化等。

    不变量:     同一场景下,图像有些变化,但图像中仍有保持稳定不变的特征,对这些特征的描述,就称为不变量

    尺度不变量: 图像尺度有变化时,那些不变的特征就称为尺度不变量

    旋转不变量: 图像旋转时,那些不变的特征就称为旋转不变量

    常用的图像特征: 角点(局部极值点)、边缘、轮廓

    稳定的特征向量: 将多种特征组合、变换,形成稳定的特征向量,即不受图像尺度、旋转等变换的影响。

    多尺度下的极值点:一般来说,测试一点是否是极值点,就是比较此点与周围的点,当此点比周围的点都大时,其就是极值点;但多尺度下的极值点,不仅要求此点在原图上是极值点,还要求其比其他尺度空间的同范围的点值都大。这个性质就是尺度不变量,这个是定义。

    特征描述子(符):拿到特征点后,利用特征点及其邻域的信息,如梯度等,转化为一个数值向量,最好与特征点的位置,scale等空间特征无关。这个数值向量形成了特征空间。无论特征点的空间位置及其他环境如何变化,特征空间对其的描述表示,保持稳定。

    -------------------

    1. 基础知识:尺度空间理解

    一般的尺度变换理解:

    尺度,首先从信号处理来理解这个概念,对信号的尺度变换,就对信号进行缩放,比如对时域扩展,频域就收缩 !!!-_-, 要复习信号的一些知识。

    对图像的尺度变换的形式: 一种就是将图像直接缩放成不同的大小。常见金字塔抽样,就是这种尺度变换的一种。

    其他尺度变换的形式:

    高斯尺度变换

    小波变换

    以及更泛化的 多分辨率尺度变换

    http://blog.csdn.net/tanxinwhu/article/details/7048370 尺度空间理解介绍


    2. 为什么是DOG算子,Gaussian算子,为什么不是LOG算子? 

    DOG/LOG算子就是借助高斯尺度变换的特征。确切的说应该是LOG特征,Mikolajczyk发现LOG的极值点(极大值和极小值)比梯度(一阶导数),Hessian(二阶导数矩阵),及harris角点具有更稳定的特征。而DOG具有近似LOG的性质,且比LOG的运算效率更高。

    Gaussian滤波器,压制高频信息,而DOG算子在Gaussian滤波器压制高频的基础上,又压制了低频的区域,形成一个带通滤波器。带通,指指定频带通过,在空域上,表现为指定尺度的细节图像保留下来。这个要比普通的高频锐化算法 检测细节的效果好,因为高频锐化不仅增强了细节,还增强了高频噪声。图像增强时,DOG算法中两个高斯核的半径之比通常为4:1或5:1。

        DOG算子如何简化计算?

        而与LOG算子比较,DOG算子其尺度变化更自由,当高斯核半径比为1:1.6时,才是LOG算子的近似。

        DOG算子具有LOG归一化的近似的性质,计算更方便、速度更快,所以采用DOG算子。


    3. 为什么原图像有时长宽扩大一倍?

    有时采用双线性插值扩大一倍,目的同高斯金字塔降采样一样,是为了scale上扩大采集特征点的范围,以实用多尺度scale的匹配


    有了高斯尺度空间,大的标准差对应图像概貌,提取云朵之类的低频特征比较丰富的特征点,小的标准差对应图像细节,提取高频细节比较丰富的特征点,为什么还需要高斯金字塔的降采样,形成octave的形式?

    应该是为了达到图像匹配时,有尺度缩放不变性的能力。形成了关键点的坐标(scale, x, y)三维空间的形式。尺度不变性,其实就是具有提取多尺度的特征,以适应各种尺度的场景。


    4. 多尺度是指哪些?

    1. 高斯系数的变化:  在图像大小不变的情况下,改变高斯函数标准差的大小,其比例系数1, k, k^2,... , k^n

    2. 空间分辨率的变化: 金字塔式抽样,改变图像大小,对图像进行间隔抽样,或者双线性插值抽样。

    如下图:



    5. 什么是octave?

    octave不一定就是高斯系数变化从1到 K^7,得到八个图像,一般不需要这么多,3-5个处理层次就可以了。每一级空间抽样(空间分辨率变化)都会有自己独立的octave高斯尺度处理。这样原文里的scale图示就比较好理解了。



    6. 空间尺度的连续性怎么理解?

    每相邻两个octave之间的序列 高斯函数有一定联系。

    如octave1,其序列高斯函数为 1, k, k^2,... , k^n, octave2 高斯序列函数为 2*1,2 * k, 2 * k^2,... ,2 * k^n.

    由于取k = 2^(1/s), octave1中第s层的高斯函数,就等于octave2中的第一层的高斯函数。从这个层面上,高斯空间尺度就连起来了。

    其好处是什么? 应该是针对特征点的选取,尺度空间连续,那么如特征点的选取,在不同尺度就不会有遗漏。若值选取一个最大尺度,和一个最小尺度, 那么就只会选取出最大尺度的特征点,以及最细节的特征点,而中间尺度的细节特征点就没选取到,这就是尺度空间不连续造成的。个人理解。

    而空间分辨率上,降采样还是要做的,即octave1与octave2即使部分序列的高斯函数一样,但其图像的大小还是不同的。


    7. 对旋转不变性体现在什么地方?

    特征点是依赖于位置信息的,所以也隐含着角度旋转的信息。要除去旋转角度信息的依赖性,就是设计一种旋转不变的特征描述子。

    一般特征点附近的 梯度 方向,加上特征点的位置,尺度,都是特征点的信息。将这些信息转换为方向无关的信息。

    计算出这个特征点的16*16邻域的所有点的梯度和方向。再划分为4*4的小窗口,计算每个小窗口的8个主方向,形成4*4*8=128的描述子。文章里介绍的更清楚。


    对亮度变化不变性体现在什么地方?

    对上述描述子,进行归一化,这样就降低了亮度变化的不变性。


    与视角变化、仿射变换保持一定稳定性体现在图像处理的哪些地方?

    什么样的点是不好的特征点?为什么?

    (待续)


        
    最新技术文章:
    ▪Android开发之登录验证实例教程
    ▪Android开发之注册登录方法示例
    ▪Android获取手机SIM卡运营商信息的方法
    ▪Android实现将已发送的短信写入短信数据库的...
    ▪Android发送短信功能代码
    ▪Android根据电话号码获得联系人头像实例代码
    ▪Android中GPS定位的用法实例
    ▪Android实现退出时关闭所有Activity的方法
    ▪Android实现文件的分割和组装
    ▪Android录音应用实例教程
    ▪Android双击返回键退出程序的实现方法
    ▪Android实现侦听电池状态显示、电量及充电动...
    ▪Android获取当前已连接的wifi信号强度的方法
    ▪Android实现动态显示或隐藏密码输入框的内容
    ▪根据USER-AGENT判断手机类型并跳转到相应的app...
    ▪Android Touch事件分发过程详解
    ▪Android中实现为TextView添加多个可点击的文本
    ▪Android程序设计之AIDL实例详解
    ▪Android显式启动与隐式启动Activity的区别介绍
    ▪Android按钮单击事件的四种常用写法总结
    ▪Android消息处理机制Looper和Handler详解
    ▪Android实现Back功能代码片段总结
    ▪Android实用的代码片段 常用代码总结
    ▪Android实现弹出键盘的方法
    ▪Android中通过view方式获取当前Activity的屏幕截...
    ▪Android提高之自定义Menu(TabMenu)实现方法
    ▪Android提高之多方向抽屉实现方法
    ▪Android提高之MediaPlayer播放网络音频的实现方法...
    ▪Android提高之MediaPlayer播放网络视频的实现方法...
    ▪Android提高之手游转电视游戏的模拟操控
     


    站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3