29
11

[转]Emgu cv中的SIFT算法实现

0
归档:2012年11月分类:C#和.NET

SIFT算法大家都比较熟悉,网上的版本很多,刚开始接触时我主要研究的是C++,因为相对于C#,基于OPEN CV C++的SIFT算法资料更多,但是由于想要实现较为理想的界面效果,最终还是放弃了使用C++转而使用C#。

 

C#中SIFT算法主要分为三种:

1)脱离Emgu cv平台,完全手动实现所有SIFT算法函数,这样的程序虽然实现有些困难,但是完全可借助已有的C++程序做更改,而且这样做最大的好处就是对SIFT算法的原理有更深的理解。

2)实现时使用少量Emgu cv函数(例如影像的读取,灰度值获得等),但是大部分工作还是依赖于.net平台自行完成。

3)基本上程序完全借助于Emgu cv提供的接口,核心函数完全由Emgu cv提供。

 

前两类程序资源较多,大家也很容易下载,第三类程序资源相对较少,因此我今天简单为大家介绍第三类算法的实现方法,首先回顾一下SIFT算法计算步骤:

 

1. 尺度空间极值检测:搜索所有尺度上的图像位置。通过高斯微分函数来识别潜在的对于尺度和旋转不变的兴趣点。

2. 关键点定位:在每个候选的位置上,通过一个拟合精细的模型来确定位置和尺度。关键点的选择依据于它们的稳定程度。

3. 方向确定:基于图像局部的梯度方向,分配给每个关键点位置一个或多个方向。所有后面的对图像数据的操作都相对于关键点的方向、尺度和位置进行变换,从而提供对于这些变换的不变性。

4. 关键点描述:在每个关键点周围的邻域内,在选定的尺度上测量图像局部的梯度。这些梯度被变换成一种表示,这种表示允许比较大的局部形状的变形和光照变化。

使用Emgu cv实现上述步骤非常简单,程序如下:

//确定匹配图像

Bitmap bt1 = new Bitmap(@"C:\Users\GAOXIANG\Desktop\111.jpg");
Bitmap bt2 = new Bitmap(@"C:\Users\GAOXIANG\Desktop\222.jpg");

//将图像转为Emgu cv的处理格式

Image<Gray, byte> img1 = new Image<Gray, byte>(bt1);
Image<Gray, byte> img2 = new Image<Gray, byte>(bt2);

//使用Emgu cv探测图片特征点

SIFTDetector sift = new SIFTDetector();
var f1 = sift.DetectFeatures(img1, null);
var f2 = sift.DetectFeatures(img2, null);

到此已经获得了两张相片的特征点f1,f2,接下来就是将相互匹配的特征点相连:

for (int i = 0; i < f1.Length; i++)
{
double[] dist = new double[f2.Length];
int n = 0;
int index = 0;
for (int j = 0; j < f2.Length; j++)
{

//计算待比较特征点描述子的欧式距离
dist[n++] = diedai(f1[i].Descriptor, f2[j].Descriptor);
}

//排序,获得欧式距离最近点以及次近点
for (int k = 0; k < 2; k++)
{
for (int k1 = k+1; k1 < dist.Length; k1++)
{
if (dist[k] > dist[k1])
{
double temp = dist[k];
dist[k] = dist[k1];
dist[k1] = temp;

//记录最近点在相片2中的序列
if (k == 0)
{ index = k1; }
}
}
}

//若最近点与次近点比值小于阈值0.49,绘制特征点连线
if (dist[0]/dist[1] < 0.49)
{
PointF point1 = f1[i].KeyPoint.Point;
PointF point2 = f2[index].KeyPoint.Point;

Graphics g = this.CreateGraphics();
Pen p1 = new Pen(Color.Blue, 3);
g.DrawLine(p1, point1,  point2);//注意:point1,point2位置与具体控件,图像布局有关,请自行调整
}
}

//描述子距离计算函数

private double diedai(float[] p1, float[] p2)
{
double sub=0;
double sqrt=0;
for (int i = 0; i < p1.Length; i++)
{
sub += Math.Pow(p1[i] - p2[i], 2);
}
sqrt = Math.Sqrt(sub);
return sqrt;
}

via:http://blog.csdn.net/xiang__jiangsu/article/details/8116618

21
5

在类库项目(或者其他非Web项目中)有时候需要HttpContext.Current这个方法,我们发现在类里面添加了引用“using System.Web;”之后还是不行,其实解解这个问题很简单,只需要在该项目的“引用”中添加System.Web这个引用就可以了。
另外值得注意的是,在非Web项目中使用HttpContext.Current.Cache、HttpContext.Current.Session等的时候,最好进行判断HttpContext.Current是否为空:
if (HttpContext.Current != null && HttpContext.Current.Session != null)
{
string test = HttpContext.Current.Session["Session"].ToString();
}
这是因为有些情况下Session或者Cache等会被截断,比如在.ashx文件中,默认情况下就会截断Session。当然也可以通过设置在.ashx文件中使用Session,但是为了安全,最后进行判断。
如果要在.ashx文件中使用Session,那么要先引用“using System.Web.SessionState;”,然后继承接口“IRequiresSessionState”,下面是一个例子:
using System;
using System.Data;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.SessionState;
namespace Lemon.Life.WebData
{

/// 演示“在.ashx中使用Session”

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Xml : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
context.Session["Test"] = "Test";
string test = context.Session["Test"].ToString();
context.Response.Write("Hello World");
}
public bool IsReusable
{
get
{ return false;}
}
}
}

21
5

设置Session永不过期,Session不过期

0
归档:2011年5月分类:C#和.NET

很多时候为了需要,必须使用Session,但是Session过期问题一直困扰很多人,我也是。通过网上的搜索,发现了可以通过两种方式了设置,但是只有一个可以永不过期。
保持Session的方法:
(1)、设Session.timeout=-1,或小于0的数。这种方法肯定是不行的,session计算时间以分钟为单位,必须是大于等于1的整数。
(2)、设Session.timeout=99999。这种同样不行,Session有最大时间限制。
其实,Session最大值为24小时,也就是说你最大可以Session.timeout=1440,1441都是不可以有。
所以想通过设Session.timeout的过期时间让Session永不过期是不可能的。写到Cookies里是比较好的方法,但是Cookie非常的危险,如果在外面的电脑很容易被别人劫持,不安全!
那么有没有一种方法可以保持Session呢,可以使用一种办法,就是在要保持session的页里设隐藏iframe
这个Iframe每隔一段时间刷新一次这个Iframe页面就可以了。

21
5

在开发过程中,常常遇到这样的问题:文件,包括图片和文件上传到服务器,而Web服务器和文件服务器不是同一个,而且不在同一个域里面,那么针对于.NET应该如何处理这样的问题呢?
可能很多高手一下子就知道如何解决,但是我确实是经过了一番努力才弄明白,下面就结束如何使用.NET的Windows模拟身份验证。
1、首先引用两个名称空间

using System.Security.Principal;
using System.Runtime.InteropServices;

2、其次定义好模拟权限的调用方法

region 权限模拟

public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern int LogonUser(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)]
public static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken);<summary>/// 验证用户,并生成WindowsIdentity 实例
</summary>private static WindowsIdentity GetIdentity(String userName, String domain, String password)
{
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
if (LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref token) == 0)
return null;
else if (DuplicateToken(token, 2, ref tokenDuplicate) == 0)
return null;
else
return new WindowsIdentity(tokenDuplicate);
}
public WindowsImpersonationContext GetContext()
{
WindowsIdentity identity = null;
WindowsImpersonationContext impersonationContext = null;
identity = string.IsNullOrEmpty(user) ? null : GetIdentity(user, null, pwd);
// 使用用户凭证进行用户模拟
impersonationContext = (identity == null) ? null : identity.Impersonate();
return impersonationContext;
}
#endregion

3、在调用身份模拟的函数中使用

WindowsImpersonationContext impersonationContext = Instance.GetContext("identityValues");
//中间是处理函数
// 取消用户模拟
if (impersonationContext != null)
{
impersonationContext.Undo();
impersonationContext = null;
}
21
5

很多公司都使用代理上网,这样当然是有原因的,因为要对公司员工访问网络进行监视,但是这很令开发人员郁闷,因为在程序中访问网络资源是需要自己设置代理认证的,我们公司就是这样的。幸亏不要紧,因为C#提供了针对访问网络资源代理的设置,今天来讲解WebClient代理问题。下面是一个实现的例子:
private static string GetHtml(string url, EncodingType type, bool isByProxy)
{
WebClient webClient = new WebClient();//创建WebClient实例myWebClient
if (isByProxy)
{
//创建代理服务器设置对象的实例
System.Net.WebProxy wp = new System.Net.WebProxy("ISASRV:80");//代理名称很端口,要根据你的情况来设置
//代理服务器需要验证
wp.BypassProxyOnLocal = false;
//用户名密码,要根据你的情况来设置
wp.Credentials = new NetworkCredential("UserName", "PWD", "hold");
//将代理服务器设置对象赋予全局设定
GlobalProxySelection.Select = wp;
//获取或设置用于对向Internet 资源的请求进行身份验证的网络凭据。
webClient.Credentials = CredentialCache.DefaultCredentials;
}
byte[] pagedata = webClient.DownloadData(url);//先获取二进制的资源
}

21
5

学习C#编程语言的几个阶段

0
归档:2010年5月分类:C#和.NET

很多人在自己的简历里都写着精通C#编程语言,可是现实中真的有那么多高手吗?下面是李建忠(《Microsoft .NET框架程序设计》作者)对学习C#语言达到的境界的几个层次:
1. 基本运用C#语法,在各种工具和示例代码的支持下,完成一些基本程序任务
2. 熟练掌握面向对象与组件构造,知其然亦知其所以然,完成一般小规模信息管理类软件项目开发任务
3. 深入理解CLR内核机制,对各种类型与.NET平台机制的优缺点、适用场合、效率有清晰把握,能够完成技术复杂度比较高的项目。
4. 能够游刃有余把握松耦合原则,精准运用各种语言构造,架构大型软件项目。
5. 能够站在计算机抽象、系统和历史发展的高度来理解和把握编程语言
个人觉得自己只能够是出于2到3这个阶段。

21
5

C#语言编程常用知识介绍

0
归档:2010年5月分类:C#和.NET

1)decimal,即十进制类型,是一种高精度、128位数据类型,它所表示的范围从大约1.0*10^-28到7.9*102^28的28至29位有效数字,注意该精度是以位数(digits)而不是以小数位(decimal places)来表示的。
2)decimal类型的变量在赋值时要在值后面加m下标,否则将被编译器当作double类型处理。
3)System.delegate 代表,引用类型,用于指向一个方法,定义方法:delegate int MyDelegate();
4)多维数组定义一例:int[,] a=new int[,]{{1,2,3},{4,5,6}}
5)多维数组定义另一例:int[][] b=new int[3][];b[0]=new int[]{1,2,3};b[1]=new int[]{1,2,3,4,5,6};b[2]=new int[]{1,2,3,4,5,6,7,8,9};
6)可以在变量名前面加上@,这主要是为了在与其他语言交互时避免冲突,一般情况下不推荐使用。
7)变量有以下以种:静态变量、非静态变量、数组元素、值能数、引用参数、输出参数、局部参数。
8)常量const修饰符有:new,public,protected,internal,private。
9)隐式枚举类型允许把十进制整数0转换为任何枚举类型,对应其他的整数则不存在这种隐式转换。
10)显式转换有可能丢失信息或导致异常抛出。
11)常量1.0默认为double类型,若要使用float型,可写成1.0f,即在数值后面加个f。
12)在逻辑表达式的求值过程中,不是所有的逻辑操作符都被执行,这种情况称为“短路”。
13)一般来说每个switch项都以break,goto case,goto default结束,但实际上任何一种不导致“遍历”的结构都是允许的。
14)C#中提供了析构函数,用于专门释放被占用的系统资源;析构函数的名称为“~类名”,它不接收任何参数,不返回值,不能被继承;C#提供垃圾收集器帮助我们解决释放资源的工作。
15) 方法修饰符可以是:new,public,protected,internal,private,static,virtual,sealed, override,abstract,extern。对于使用了abstract,extern修饰符的方法,方法的执行体仅仅只有一个简单的分号。其他的方法执行体应包含调用该方法所要执行的语句。
16)方法参数四种类型:值类型(不需修饰符)、引用类型(以ref修饰符声明)、输出类型(以out修饰符声明)、数组型类型(以params修饰符声明)
17)如果方法的形参表中包含了数组型参数,那么它必须在参数表中位于最后。另外,参数只允许是一维数组。比如:string[],string[][]类型都可以作为数组型参数,而string[,]则不能。最后,数组型参数不能再有ref和out修饰符。
18)静态方法只能访问类中的静态成员。
19)操作符重载方法:在定义类方法时,在方法名称后面加上“[空格]operator[空格][具体的操作符]”,如以下方法:public static Player operator ++(Player p){method body...}
20)可重载的操作符:+,-,!,~,++,--,true,false,*,/,%,&,,^,<<,>>,==,!=,>,<,>=,<=。注:这里列出的操作符之间用“,”隔开。
21)不可重载的操作符:=,&&,,?:,new,typeof,sizeof,is
22)域的修饰符:new,public,protected,internal,private,static,readonly
23) 属性的修饰符:new,public,protected,internal,private,static,virtual,sealed, override,abstract,以上修饰符中,static,virtual,override,abstract不能同时使用。
24)事件的修饰符:new,public,protected,internal,private,static,virtual,sealed, override,abstract,以上修饰符中,static,virtual,override,abstract不能同时使用。
25)构造函数和析构函数不能被继承。
26)在派生类中覆盖基类中的方法时,在方法前面加上new关键字可关闭编译器的警告。
27)base关键字主要是为派生类调用基类成员提供一个简写的方法。
28)C#中的多态性有两种:编译时的多态性和运行时的多态性;编译时的多态性是通过重载实现的,运行时的多态性是通过虚成员实现的;编译时的多态性为我们提供了运行速度快的特点,而运行时的多态性则带来了高度的灵活和抽象的特点。
29)方法在使用了virtual修饰符之后,不允许再有static,abstract或override修饰符。
30)在派生类中重新定义基类的虚方法时,要求方法名称、返回值类型、参数表中的参数个数、类型、顺序都必须与基类中的虚方法完全一致。
31)在派生类中声明对虚方法的重载,要求在声明中加上override关键字,而且不能有new,static或virtual修饰符。
32)抽象类只能作为其他类的基类,不能被实例化。
33)只能在抽象类中声明抽象方法,抽象方法不包含具体的实现内容,不能再使用static或virtual修饰符,不能出现{},如:public abstract void speak();
34)抽象类中的抽象方法在派生类中不能使用base关键字来进行访问。
35)可以利用抽象方法来重载基类的虚方法,这时基类中的虚方法的执行代码这被“拦截”了。
36)密封类(使用sealed修饰符的类)不能被其他类继承。
37)将方法密封可防止方法所在的类的派生类对该方法重载。
38)不是类的每个成员方法都可以作为密封方法,密封方法必须对基类的虚方法进行重载,提供具体的实现方法。
39)和类的成员方法一样,我们也可以定义属性的重载、虚属性、抽象属性、以及密封属性的概念。
40)接口仅可以使用下列修饰符:new,public,protected,internal,private。
41)接口的成员可以是属性、方法、事件和索引指示器。
42)C#中类继承只允许单继承,但接口允许多继承,多个父接口之间用“,”隔开,被继承的接口应该是可以访问的,如从private类型和internal类型的接口中继承就是不允许的。
43)接口成员的默认访问方式是public,接口成员不能包含任何修饰符。
44)由于接口允许多继承,所以要注意接口成员的是否有二义性。
45)显式接口成员只能通过接口调用。
46)显式接口成员执行体不能使用任何访问修饰符。
47)使用private,protected和static修饰符的成员不能参与实现接口映射。
48)如果不显式地重新实现接口,派生类就无法改变从基类中继承来的接口映射。但是,当一个接口方法被映射到类的一个虚方法时,派生类就可以重载这个虚方法,并且改变这个接口的实现。
49)继承了接口实现的类可以对接口进行重实现。
50)有关接口的几个概念:显式接口成员执行体、
50) 各个流:Stream,BinaryReader,BinaryWriter,File,Directory,FileStream, TextReader,TextWriter,StringReader,StringWriter,StreamReader,StreamWriter, BufferedStream,MemoryStream,NetworkStream;对网络文件进行操作使用IsolatedStorage类处理,不用流。

21
5

.NET内核揭秘

0
归档:2010年5月分类:C#和.NET

这两年来,越来越多的国内软件企业开始深入.NET底层开发,我也接到了不少企业的深度.NET培训邀约,在培训课程方面也有较为成熟的积累。决定动笔写作《.NET内核揭秘》(暂定名)一书。目前大致蓝图如下:
1. 对象里面到底装的是什么--揭秘.NET类型封装
议题:程序构造的历史;代码段与数据段;对象、数据成员与函数成员;.NET对象到底有多大;.NET对象布局;简单值类型;string揭秘;数组揭秘…..
2. 程序运行之来龙去脉 --揭秘CLR虚拟机执行系统
议题:JIT编译如何进行;系统如何加载类型;堆栈模型;如何使用应用程序域隔离代码;异常如何层层抛出…..
3. 对象的前生后世 --揭秘.NET类型继承
议题:子类从父类继承了什么;子类与父类之间的类型关联;为什么可以将子类看作一个父类;静态类型与动态类型……
4. 不要调用我,让我来调用你 --揭秘.NET多态机制
议题:callvirt如何调用虚方法;虚方法表上都有什么;虚表指针什么时候使用;虚方法效率到底有多低….
5. 数据与代码的博弈 --揭秘.NET委托调用
议题:委托如何实现动态调用;委托类型内部构造;委托调用的效率;异步委托调用……
6 托管对象的生与死 --揭秘.NET垃圾收集
议题:垃圾收集器如何分配内存;垃圾收集器如何构造对象图;垃圾收集器如何搬移内存;垃圾收集器如何更新托管引用;垃圾收集器的性能到底如何…..
7. 插上元数据的翅膀 -- 揭秘.NET反射机制
议题:元数据是什么;元数据在哪里;如何反射类型;反射类型内部是什么;反射的效率到底有多低;反射的边界在哪里…..
8. 运行时泛型的算盘 --揭秘.NET泛型实现
议题:泛型类型到底是什么;泛型类型与元数据;泛型类型到底如何实例化;泛型的约束与效率…..
如果这些问题是各位面临.NET所困惑的,我希望在本书中能够解答大家的疑惑。印象中有些读者对《.NET框架程

公告栏

欢迎大家来到我的博客,我是dodoro,希望我的博客能给你带来帮助。