64位 WIN 7/8 下VS2010配置CLAPCAK3.2.1和Levmar2.6
由於在影象拼接程式中要用到LM演算法,本人程式設計能力太弱,只好藉助於庫函式。看到網上教程有用Levmar(FAQ)來做LM演算法的。Levmar可用於C++, Matlab,Perl, Python, Haskell and Tcl。本人在VS2010下程式設計,所以下面只談談如何在VS2010下配置。
經過測試,win7與win8 64位系統下的VS2010用下面的方法配置可以成功。
準備工具:
1. cmake-2.8.12.1-win32-x86.zip (選擇Binary distributions欄下的第二個)。
2.
3. levmar-2.6
步驟:
1. 先將上面下載的三個壓縮包都解壓。解壓後的cmake-2.8.12.1-win32-x86是編譯工具,建議放在常用的工具資料夾下(英文目錄,不要有中文)。解壓後的clapack-3.2.1-CMAKE和levmar-2.6等會要用到,而且程式設計的時候也用到其做包含目錄,因此不建議放在桌面。
2. 針對clapack-3.2.1-CMAKE的操作。雙擊開啟cmake-gui.exe(該檔案在cmake-2.8.12.1-win32-x86資料夾裡的bin資料夾下)首先要對clapack-3.2.1-CMAKE進行編譯。如圖
對於箭頭1,點選右邊的Browse Source...將資料夾定位到第一步解壓出的clapack3.2.1-CMAKE,對於箭頭2,Browse Build..則是你要編譯到的位置,為了方便我選擇C:\CLAPACK。選擇完之後,我們點選左下角的configure按鈕,彈出的框裡我們選擇Visual Studio 10 Win64,點Finish等幾秒鐘,Configure結束後畫面中間會出來一些紅色的條框,不管它,我們再點Configure右邊的Generate按鈕,根據下面提示Generate done後,可以先關掉這個視窗了。現在我們到C:\CLAPACK下,找到CLAPACK.sln這個檔案,並雙擊,這時候會在VS2010裡出來一個工程,等待載入完成後,我們選擇生成解決方案。這裡需要花點時間,等程式跑完之後會提示成功了33個專案(這一步是為了生成4個lib檔案)。下面我們可以先關掉VS2010。然後再次到C:\CLAPACK資料夾下,我們要尋找4個.lib檔案(為了在levmar中要連結他們),這4個檔案分別是:
l C:\Clapack\BLAS\SRC\Debug: blas.lib
l C:\Clapack\F2CLIBS\libf2c\Debug: libf2c.lib
l C:\Clapack\SRC\Debug: lapack.lib
l C:\Clapack\Testing\MATGEN\Debug: tmglib.lib
為了便於我們在後面連結他們,我們先在C:\CLAPACK下新建一個LIB資料夾,然後複製上面四個lib檔案到這個資料夾下。到這裡第二步基本完成了。
注意:複製libf2c.lib的時候我們將檔名改為f2c.lib(因為後面連結的預設名是f2c.lib)
3. 針對LEVMAR2.6部分接下去我們再次開啟cmake-gui.exe, Browse Source...選擇第一步解壓出來的levmar-2.6,Browse Build..選擇要編譯到的位置,這裡我選的是C:\lm26。然後點選Configure,選擇Visual Studio 10 Win64,之後彈出如下所示:
將LAPACKBLAS_DIR 後面的usr/lib資料夾路徑改成第二步中我們自己建的那個資料夾路徑 C:\CLAPACK\LIB。然後再次點選左下角的Configure,紅色變白色,之後再點選Generate。下面我們到 C:\lm26資料夾下找到LEVMAR.sln檔案,執行它,點生成解決方案,全部成功後關掉。這一步是為裡生成C:\lm26\Debug\levmar.lib檔案。到這裡配置部分基本完成了,下面講如何在我們自己的程式裡用。
4. 新建一個VS2010的c++工程lm_test,點頂部選單欄的專案,再點屬性,點左側的配置屬性,再點右側的配置管理器,點活動平臺解決方案的下拉選單,點新建,然後把Itanium換成x64點確定,如圖
這樣,我們就將我們的工程配置成了64位的。
然後右鍵點選左側解決方案資源管理器中lm_test,選擇屬性,彈出的視窗左側點選配置屬性下的VC++目錄,然後在右側的包含目錄中新增我們在第一步中解壓出的levmar2.6的資料夾,如圖
確定後,我們再在庫目錄下再新增兩個資料夾,一個是我們在第二步中自己新建的那個C:\CLAPACK\LIB,另一個是C:\lm26\Debug,為的就是這兩個資料夾裡面的lib檔案,如圖
確定後我們點選左側的連結器、輸入,附加依賴項新增第二步生成4個lib檔案和第三步生成的1個lib檔案: lapack.lib, blas.lib, f2c.lib,tmglib.lib.levmar.lib。
現在把下面的程式拷貝進去執行看看吧。
// testlevmar.cpp : Defines the entry point for the console application.
//
////////////////////////////////////////////////////////////////////////////////////
// Example program that shows how to use levmar in order to fit the three-
// parameter exponential model x_i = p[0]*exp(-p[1]*i) + p[2] to a set of
// data measurements; example is based on a similar one from GSL.
//
// Copyright (C) 2008-11 Manolis Lourakis (lourakis at ics forth gr)
// Institute of Computer Science, Foundation for Research & Technology - Hellas
// Heraklion, Crete, Greece.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
////////////////////////////////////////////////////////////////////////////////////
#include stdio.h //自己加一下尖括號,新浪部落格加了就不顯示內容了
#include stdlib.h
#include string.h
#include math.h
#include "levmar.h"
#ifdef _cplusplus
extern "C"{
#include "f2c.h"
#include "clapack.h"
}
#endif
#ifndef LM_DBL_PREC
#error Example program assumes that levmar has been compiled with double precision, see LM_DBL_PREC!
#endif
#define M_PI 3.14
#undef REPEATABLE_RANDOM
#define DBL_RAND_MAX (double)(RAND_MAX)
#ifdef _MSC_VER // MSVC
#include
#define GETPID _getpid
#elif defined(__GNUC__) // GCC
#include
#include
#define GETPID getpid
#else
#warning Do not know the name of the function returning the process id for your OS/compiler combination
#define GETPID 0
#endif
#ifdef REPEATABLE_RANDOM
#define INIT_RANDOM(seed) srandom(seed)
#else
#define INIT_RANDOM(seed) srandom((int)GETPID()) // seed unused
#endif
double gNoise(double m, double s)
{
double r1, r2, val;
r1=((double)rand())/DBL_RAND_MAX;
r2=((double)rand())/DBL_RAND_MAX;
val=sqrt(-2.0*log(r1))*cos(2.0*M_PI*r2);
val=s*val+m;
return val;
}
struct xtradata{
char msg[128];
};
void expfunc(double *p, double *x, int m, int n, void *data)
{
register int i;
struct xtradata *dat;
dat=(struct xtradata *)data;
for(i=0; i
x[i]=p[0]*exp(-p[1]*i) + p[2];
}
}
void jacexpfunc(double *p, double *jac, int m, int n, void *data)
{
register int i, j;
struct xtradata *dat;
dat=(struct xtradata *)data;
for(i=j=0; i
jac[j++]=exp(-p[1]*i);
jac[j++]=-p[0]*i*exp(-p[1]*i);
jac[j++]=1.0;
}
}
int main()
{
const int n=40, m=3; // 40 measurements, 3 parameters
double p[m], x[n], opts[LM_OPTS_SZ], info[LM_INFO_SZ];
register int i;
int ret;
struct xtradata data;
// INIT_RANDOM(0);
for(i=0; i
x[i]=(5.0*exp(-0.1*i) + 1.0) + gNoise(0.0, 0.1);
p[0]=1.0; p[1]=0.0; p[2]=0.0;
opts[0]=LM_INIT_MU; opts[1]=1E-15; opts[2]=1E-15; opts[3]=1E-20;
opts[4]=LM_DIFF_DELTA; // relevant only if the finite difference Jacobian version is used
strcpy(data.msg, "Hello there!");
ret=dlevmar_der(expfunc, jacexpfunc, p, x, m, n, 1000, opts, info, NULL, NULL, (void *)&data); // with analytic Jacobian
//ret=dlevmar_dif(expfunc, p, x, m, n, 1000, opts, info, NULL, NULL, (void *)&data); // without Jacobian
printf("Levenberg-Marquardt returned in %g iter, reason %g, sumsq %g [%g]\n", info[5], info[6], info[1], info[0]);
printf("Best fit parameters: %.7g %.7g %.7g\n", p[0], p[1], p[2]);
exit(0);
system("pause");
}