您的位置:首页 > 编程语言 > MATLAB

.NET与Matlab结合 —— 最小二乘法直线拟合(C#)

2010-03-18 18:37 393 查看
写在前面的:

还以为这辈子都没有机会把Matlab与自己的程序结合起来,因为一直都没有时间去学习Matlab与C语言混合编程,而且也觉得那玩意儿有点难,需要很多时间;

还以为这辈子都没有可能自己写一个图形拟合程序,因为一直觉得那个太D,认为是科学家干的事情......

但是学习了几天C#之后,让我有些蠢蠢欲动,特别是作者的这句话:

“本章完成了基类的讨论。仍有许多内容没有包含进来,但前面涉及到的技术已经足够我们创建相当复杂的应用程序了!”

而我又一直对《计算机图形学-几何工具算法详解(Geometric Tools for Computer Graphics)》这本书敬仰得五体投地,总觉得最小二乘法的直线拟合这种牛X而又基本的算法真的很值得去亲手实现一下,但一直欠于掌握的技术不够,即手法还不够丰富!如今,作者说我们已经可以创建相当复杂的应用程序了,恩......我可以试试了......

PS:《Geometric Tools for Computer Graphics》这本书的内容也许并不对每个人都有用,但是它的序言值得每个学者去阅读,至少是一次(我已经看了不下百次了)。我的脑里每天都会回忆其中的这三句:

“但是基本的原理保持不变,故而,在把有关DirectX9和Intel的64位Itanium体系结构的书籍从书架上撤下多年以后,你很可能还会在书架上保留本书的一些版本。”

“本书中的算法更是如此,因为它们与特定硬件、网络协议或其他短暂的事物并不相关。”

“就像想获得世界上大部分有价值的东西一样,完全地理解本书的内容,是需要付出努力和奋斗的。”



首先是一个.m文件drawgraph.m,确保它能够在Matlab里运行。

我这里是最小二乘法直线拟合程序。

%最小二乘法直线拟合

%Created by Safirst C. Ke 2007.8.29 Wed 14:51

function drawgraph(coords)

%传入的参数为两行向量,第一行为x坐标,第二行为坐标。

%axis ([0 100 0 100]);

grid on;

hold on;

%显示欲拟合的点的位置

plot(coords(1,:), coords(2,:), '*');

%分解x,y坐标

x = coords(1,:)

y = coords(2,:)'

b = size(coords);

c = ones(1, b(2));

MT = [c; x];

M = MT';

%f为直线函数,f = mx + b;

f = inv(MT * M) * MT * y

['y = ', num2str(f(2)), 'x + ', num2str(f(1))]

%显示最终拟合的直线

x = -max(x):max(x);

y = f(1) + f(2) * x;

plot(x, y);

xlabel('X轴');

ylabel('Y轴');

title('最小二乘法直线拟合 by Safirst C. Ke');

legend(['y = ', num2str(f(2)), 'x + ', num2str(f(1))]);

然后将这个文件包含在.NET的类库工程中,并进行编译。

这里需要理解它的过程,毕竟.NET不能编译.m文件。怎么做到的呢?

通过设置这个工程的生成事件属性,添加为

call PlotDemoBuild.bat

然后在PlotDemoBuild.bat这个文件里面写好用Matlab编译器mcc编译的命令行,最重要的部分就是

mcc -M -silentsetup -vg -B "dotnet:PlotDemoComp,Plotter,2.0,private" -d ../../src ../../drawgraph.m

这样的话,点击生成,就会通过mcc产生dll,即我们需要的类库。

然后建立我们真正的C#工程,添加引用为刚才的类库,并开始写程序program.cs

using System;

using System.Collections.Generic;

using System.Text;

using MathWorks.MATLAB.NET.Utility;

using MathWorks.MATLAB.NET.Arrays;

//这两个引用显然要添加,不过好在这两个命名空间属于一个库MWArray.dll

//C:/Program Files/MATLAB/R2007a/toolbox/dotnetbuilder/bin/win32/v2.0/MWArray.dll

using PlotDemoComp;

namespace ConsoleApplication2

{

class Program

{

//[STAThread]

static void Main(string[] args)

{

try

{

Console.WriteLine("Please Input the points you want to fit:");

string[] y = Console.ReadLine().Trim().Split();

int size = y.Length;

double[] x = new double[size];

for(int i = 0; i < size; i++)

{

x[i] = Convert.ToDouble(y[i]);

}

double[,] pointValues = new double[2, size / 2];

//从开头算起,相邻的两个数为一个点,所以x和y都是间隔一个的。如1,2,3,4代表两点(1,2),(3,4)

for(int i = 0; i < size; i += 2)

{

int index = i / 2;

pointValues[0, index] = x[i];

}

for(int i = 1; i < size; i += 2)

{

int index = (i - 1) / 2;

pointValues[1, index] = x[i];

}

Plotter plotter = new Plotter();

plotter.drawgraph((MWNumericArray)pointValues);

Console.ReadLine();

}

catch(Exception exception)

{

Console.WriteLine("Error: {0}", exception);

}

}

}

}

运行结果如下:

Please Input the points you want to fit:

1 2 3 4 5 6 -1 -2 -3 -4 -5 -6


*号标记欲拟合的点,直线为拟合直线!

就写这么多,以后再加入一个曲线拟合的程序。

原帖: http://blog.csdn.net/safirst/archive/2007/08/29/1763873.aspx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: