摘要: 代碼風格和格式確實比較隨意, 但一個項目中所有人遵循同一風格是非常容易的. 個體未必同意下述每一處格式規則, 但整個項目服從統一的編程風格是很重要的, 只有這樣才能讓所有人能很輕松的閱讀和理解代碼. 閱讀全文
這段時間一直在做全景圖像拼接,略有小成。總結一下:
圖像拼接概括起來說,分兩大步驟。第一步,配準。第二步,融合。
配準有基于模板匹配的,有基于特征點匹配的。現在的主流是基于特征點匹配的,SIFT是熱點。
融合的方法有很多,有最簡單的線性過渡,有經典的拉普拉斯金字塔融合(多波段融合),有基于小波變換的融合,還有比較新而且效果很贊的泊松圖像編輯融合,可惜泊松圖像編輯的這個方法我還沒有實現出來,只是實現了基于拉普拉斯金字塔的融合,效果挺不錯。
以下三篇論文是權威和經典,如果有能力消化并實現,那么一個完整的全景拼接系統就有了。
1) Construction of panoramic mosaics with global and local alignment.
Heung-Yeung Shum and Richard Szeliski. 2000.
2) Eliminating Ghosting and Exposure Artifacts in Image Mosaics.
Matthew Uyttendaele, Ashley Eden and Richard Szeliski. 2001.
3) Automatic Panoramic Image Stitching using Invariant Features.
Matthew Brown and David G. Lowe. 2007.
ps: 上面論文作者其中的Richard Szeliski是計算機視覺界的翹楚,在微軟研究院工作,最近出了新書《Computer Vision: Algorithm and Applications》英文版,200多美刀。不過該大牛在他的個人網站上放了書稿,pdf格式,絕對值得下載。
在微博上看的:
六年前,我會好多古詩詞,提筆不忘字還會辨認錯別字,給個作文題五分鐘內就能動筆,會三角函數解析幾何立體幾何,懂英語語法,看得懂電路知道磁場電場動量動能洛倫茲力,分得清強酸弱酸共軛酸堿對,最愛實驗題……現在 現在我TM就是個文盲。
18歲那年,我們都是全才,我們會微積分、線性規劃、三角函數,會背《出師表》、《滕王閣序》,會分析虛擬語氣的N種用法,會看電路圖,會配方程式,會算遺傳概率。現在呢,你還會什么?
高考結束了,馬上又將會有這么一群孩子,迫不及待的扔下書包,去聚餐,通宵上網,旅行,KTV,閑逛,狂歡……認為自己終于解放了……殊不知的,你們離開的,就是天堂.
說的多好啊,感慨一個!
摘要: 下面是收集的一些開發工具包,主要是C/C++方面的,涉及圖形、圖像、游戲、人工智能等各個方面,感覺是一個比較全的資源。供參考!原文的出處:http://www.codemonsters.de/home/content.php?show=freelibraries Contents 2D Graphics3D Graphics3D Game EnginesArtificial Intelligenc... 閱讀全文
1. 必備組件
1. svn
2. cmake (http://www.cmake.org)
3. Android NDK(r5b或更高版本)
2. 在windows上構建
在opencv\android\scripts\目錄下,新建wincfg.cmd文件。設置如下變量:
l ANDROID_NDK
l CMAKE_EXE
l MAKE_EXE
關于wincfg.cmd文件的配置,可以參考opencv\android\scripts\wincmd.cfg.tmpl文件。
做完上述操作。即可打開命令行窗口。執行如下命令
cd opencv\android\scripts
cmake_android.cmd
編譯完成即可在opencv\android\build目錄下得到所有的靜態庫文件。
進入android-opencv目錄執行cmake_android.cmd。
執行完上步操作之后,就會得到一個標準的android工程。在該目錄下的libs文件夾下會生成libandroid-opencv.so文件。
至此,有了android-opencv.so和各個模塊的靜態庫。
將相應的頭文件都拷貝一個統一的目錄中,配合上述編譯出來的靜態庫和動態庫,就可以在android中使用opencv了。
Sobel算子主要用來做圖像邊緣檢測。在OpenCV中有現成的接口可以調用,即:cvSobel。
今天遇到一個問題是需要一個類似Sobel算子的功能,因為Sobel算子沒有考慮到像素點周圍的相似性,現在需要考慮這個問題。所以需要的算子的元素與Sobel算子不同。于是自己動手寫了sobel算子的實現,這樣對于不同的參數修改算子的元素值即可。代碼如下:
1 void MySobel(IplImage* gray, IplImage* gradient)
2 {
3 /* Sobel template
4 a00 a01 a02
5 a10 a11 a12
6 a20 a21 a22
7 */
8
9 unsigned char a00, a01, a02, a20, a21, a22;
10 unsigned char a10, a11, a12;
11
12 for (int i=1; i<gray->height-1; ++i)
13 {
14 for (int j=1; j<gray->width-1; ++j)
15 {
16 CvScalar color = cvGet2D(gray, i, j);
17
18 a00 = cvGet2D(gray, i-1, j-1).val[0];
19 a01 = cvGet2D(gray, i-1, j).val[0];
20 a02 = cvGet2D(gray, i-1, j+1).val[0];
21
22 a10 = cvGet2D(gray, i, j-1).val[0];
23 a11 = cvGet2D(gray, i, j).val[0];
24 a12 = cvGet2D(gray, i, j+1).val[0];
25
26 a20 = cvGet2D(gray, i+1, j-1).val[0];
27 a21 = cvGet2D(gray, i+1, j).val[0];
28 a22 = cvGet2D(gray, i+1, j+1).val[0];
29
30 // x方向上的近似導數
31 double ux = a20 * (1) + a21 * (2) + a22 * (1)
32 + (a00 * (-1) + a01 * (-2) + a02 * (-1));
33
34 // y方向上的近似導數
35 double uy = a02 * (1) + a12 * (2) + a22 * (1)
36 + a00 * (-1) + a10 * (-2) + a20 * (-1);
37
38 color.val[0] = ux;
39
40 cvSet2D(gradient, i, j, color);
41 }
42 }
43 }
上面代碼中訪問圖像的像素使用了OpenCV的接口,這個不如直接使用指針的效率高,可以修改。
我使用的是OpenCV 2.2版本。得到了一個透視矩陣,想把屏幕上的一個二維點經過這個透視矩陣進行變換,本身很簡單的一個事情,卻頗費了一番周折。原因是剛接觸OpenCV,而且使用了OpenCV新添加的C++部分的矩陣類Mat,使用起來還真有點不順手,因為OpenCV中沒有向量的說法。一個矩陣變換一個向量就讓我找了半天。
最終得以解決,還是使用了CvMat類而不是Mat類。代碼如下:
1 CvPoint transformPoint(const CvPoint pointToTransform, const CvMat* matrix)
2 {
3 double coordinates[3] = {pointToTransform.x, pointToTransform.y, 1};
4 CvMat originVector = cvMat(3, 1, CV_64F, coordinates);
5 CvMat transformedVector = cvMat(3, 1, CV_64F, coordinates);
6 cvMatMul(matrix, &originVector, &transformedVector);
7 CvPoint outputPoint = cvPoint((int)(cvmGet(&transformedVector, 0, 0) / cvmGet(&transformedVector, 2, 0)), (int)(cvmGet(&transformedVector, 1, 0) / cvmGet(&transformedVector, 2, 0)));
8 return outputPoint;
9 }
這個函數一個很有用的地方就在于,原本二維圖上的一個像素點位于(x,y)處,經過一個變換(仿射變換、透視變換)之后,求取它的新的坐標點(x', y')。
平臺是Ubuntu 10.04,Box2D版本為v2.1.2,Box2D采用cmake作為其編譯系統。
按照Building.txt的步驟如下:($BOX2DPATH為box2d源碼所在路徑)
cd $BOX2DPATH/Build
cmake -DBOX2D_INSTALL=ON -DBOX2D_BUILD_SHARED=ON ..
make
make install
也可以在調用cmake時增加-DCMAKE_INSTALL_PREFIX=/opt/Box2D來自定義安裝位置。
在make的過程中出現兩個小問題
1) error: X11/extensions/XInput.h: No such file or directory
解決辦法:
sudo apt-get install libxi-dev
2) 大量的OpenGL調用的引用沒找到,這是因為沒有鏈接Open GL的相關庫,GL和GLU。
解決辦法:
進入Build/Testbed/CMakeFiles/Testbed.dir/link.txt,在文件的指定鏈接Open GL的庫所在的路徑以及Open GL的庫。在我的機器上,我增加了如下內容:
-L/usr/lib/mesa -lGL -lGLU
至此,問題解決,Box2D編譯通過,Testbed可以運行了, enjoy it。
1. 切換屏幕導致Activity的onCreate調用兩次。
解決辦法:
AndroidManifest.xml文件中添加:android:label="@string/app_name" android:configChanges="keyboardHidden|orientation"
2. 使用DisplayMetrics獲取屏幕分辨率不正確。480x800的分辨率得到的結果卻是320x533。
解決辦法:
和android sdk版本有關,1.6以上版本沒有這個問題。AndroidManifest.xml文件中添加:<uses-sdk android:minSdkVersion="4"即可。
編譯幾個簡單的cpp文件。自己寫了makefile。編譯器使用g++,鏈接器指定ld。
鏈接器指定使用ld會出現如下錯誤:
cannot find entry symbol _start
這是因為ld的真正入口是_start而不是main。需要鏈接相應的c庫和c運行時庫。libc、libcrt等。
解決辦法是使用gcc。
但是鏈接器指定使用gcc會出現如下錯誤:
undefined reference to '__gxx_personality_v0'
這是因為缺少stdc++庫,加上-lstdc++即可。
或者更干脆的使用g++,讓g++去處理這些細枝末節吧。