1. 程式人生 > >在ubuntu下使用cmake進行opencv的配置和Windows下進行使用cmake編譯原始碼比較,opencv3進行g++例子程式編譯、動態庫的製作

在ubuntu下使用cmake進行opencv的配置和Windows下進行使用cmake編譯原始碼比較,opencv3進行g++例子程式編譯、動態庫的製作

1.首先安裝的是cmake軟體,使用指令:

apt-get install cmake
接著檢視版本,測試是否安裝成功:
[email protected]:/home# cmake --version
cmake version 2.8.10.2

由於我們需要時有的是cmake介面來配置,所以我麼要安裝器ui介面,其指令是:

apt-get install cmake-gui
如果覺得自帶的cmake版本不符合要求,可以自行下載安裝包,其安裝過程是:
下載最新版的安裝包:
http://www.cmake.org/cmake/resources/software.html
這裡下載已經編譯好的,這樣只需要解壓至需要的目錄下即可使用:
tar zxvf cmake-2.8.10.2-Linux-i386.tar.gz –C /usr/local/
設定環境變數:
sudo gedit /home/emouse/.bashrc
在開啟的檔案後新增:
export PATH=$PATH:/usr/local/cmake-2.8.10.2-Linux-i386/bin
安裝完成後就可以使用上面通過檢查其版本來看是否安裝完成。

2、先安裝 libgtk2.0-dev 和 pkg-config,,否則後期編譯執行程式會出現類似如下的問題:
OpenCV Error: Unspecified error (The function is not implemented. Rebuild the library with Windows, GTK+ 2.x or Carbon support. If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, then re-run cmake or configure script) in cvNamedWindow, file /usr/local/opencv/OpenCV-2.0.0/src/highgui/window.cpp, line 100
terminate called after throwing an instance of 'cv::Exception'
通過網路獲取安裝:

# apt-get install libgtk2.0-dev
# apt-get install pkg-config

2、下載OpenCV ,檔名:OpenCV-2.4.3.tar.bz2,下載地址:
http://www.opencv.org.cn/index.php/Download
解壓:
#tar jxvf OpenCV-2.4.3.tar.bz2
得到資料夾 OpenCV-2.4.3

此時在同級目錄下新建一個資料夾opencv-x86作為PC編譯目錄,記住其實這個檔案是為了存放一些編譯過程生成的雜碎檔案和一個最重要的makefile檔案。

注意:不過現在的opencv提供的linux不是tar包了,而是zip包,其解壓指令要使用unzip,當使用cd定位到檔案所在目錄後,使用指令為

:unzip OpenCV-2.4.4.zip  

3、#cmake-gui 開啟cmake的gui介面,開始進行配置。
cmake主要用於進行一些配置設定,從而生成用於編譯安裝的makefile檔案,通過介面進行引數的配置和設定,非常直觀、方便。在配置中指定原始碼和編譯目錄以及生成方式。
按照下圖的步驟進行配置:

點選Finish後cmake即載入預設配置,如下圖所示:

當第一次configure配置完後,再次點選configure,最後點選generate,當出現有generate Done則表示完成。其中的/usr/local是用於存放生成的lib與dll檔案,上面的CONFIGURATION_TYPES指的是進行兩鐘模式的lib和dll文夾生成,其是這一步還不會生成lib和dll,而是生成makefile檔案,裡面包含了我們的一些設定,為了生成lib和dll。下圖是我們在Windows下安裝opencv後自帶的庫檔案目錄(這是opencv以為我們編譯好的,所以我們可以直接使用,而不需再自行編譯產生庫檔案,但是當VS的版本與opencv的版本不相容時,可以自行編譯產生相應的庫檔案來解決)


另一種通過終端指令來配置相應的引數來生成makefile檔案:

$ cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/home/OpenCV  

(這裡的PREFIX路徑是自己定義的位置,其替代了預設路徑/usr/local)如果使用全部使用預設路徑則可以直接使用指令:

cmake .
注意別忘了這個點。只是這裡通過圖形介面的方式來進行配置,更加直觀方便。 4.接下來使用cd定位到opencv-x86資料夾下使用指令:
make
make install

這上面的兩條指令主要是為了對應編譯器下的dll、lib檔案,我們可以通過指令來檢視make是否成功,然後再執行make install指令,檢測正確與否指令是:

<span style="font-size:18px;">echo  $?</span>

     輸入這條命令回車後,輸出的結果是0,那麼就說明成功編譯,否則就是出錯了,echo  $?表示檢查上一條命令的退出狀態,程式正常退出返回0!所以這是為什麼我們的main函式要有返回值並且是正確返回0。

其跟我們在Windows下使用cmake生成庫的步驟相同,其在使用cmake後也分為兩步:

第一步:在debug模式下,選擇解決方案“Opencv”,點選右鍵,執行“重新生成解決方案”;

第二步:生成成功後,再CMakeTargets目錄下選擇INSTALL,右鍵執行。

而release模式下也是這樣子的兩個步驟即可,其流程圖如下:



5.接下來就是配置lib庫:

 在linux系統下安裝了帶有動態庫的程式後,會在ld.so.conf.d檔案目錄下生產相應程式的.conf檔案,其裡面包含了

此軟體執行需要裝載的動態庫路徑,所以我們需要把我們使用cmake配置時的路徑,我們使用的是預設路徑,則我們的指令是:

sudo gedit /etc/ld.so.conf.d/opencv.conf
開啟配置檔案後就輸入路徑(這個資料夾一般是空的),其為:
/usr/local/lib
注意:在預設路徑下在生成lib是會自動生成一個lib資料夾的。完成上的步驟後,這裡的庫檔案仍然不能被呼叫,因為為linux系統的特性是,新載入的庫檔案需要快取到一個叫ld.so.cache檔案裡(其裡面包含了/etc/ld.so.conf中指定的目錄中查詢到的所有的庫,按順序排列),否則使用該軟體是會報錯,說缺少xxx庫,而使用的指令是:
ldconfig
6.最後配置環境變數

其中pkgconfig資料夾裡包含了軟體的.pc檔案,這個是包含了庫的路徑之類得東西,使用的指令是:

gedit /etc/bash.bashrc
在檔案後新增:
PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig 
export PKG_CONFIG_PATH
儲存退出,重啟計算機後就可以使用opencv例程來測試配置成功與否。

下面的一些是一些小知識,看與不看都可以,可以直接進入步驟7環節,其中ubuntu裡的檔名字與其他linux系統有些差別,其如下:





注意:  在預設情況下,每個支援 pkgconfig 的庫對應的 .pc 檔案在安裝後都位於安裝目錄中的 lib/pkgconfig 目錄下。例如,我們在上面已經將 Glib 安裝在 /opt/gtk 目錄下了,那麼這個 Glib 庫對應的 .pc 檔案是 /opt/gtk/lib/pkgconfig 目錄下一個叫 glib-2.0.pc 的檔案,這裡麵包含有軟體的庫lib位置,dll位置等,其內容為:

prefix=/opt/gtk/
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include

glib_genmarshal=glib-genmarshal
gobject_query=gobject-query
glib_mkenums=glib-mkenums

Name: GLib
Description: C Utility Library
Version: 2.12.13
Libs: -L${libdir} -lglib-2.0 
Cflags: -I${includedir}/glib-2.0 -I${libdir}/glib-2.0/include 
注意:為什麼需要配置上面的路徑呢?因為其是為了加快庫的讀取。

下面以Glib庫為例子:

安裝完 Glib 後,在 bash 中應該進行如下設定:

$ export PKG_CONFIG_PATH=/opt/gtk/lib/pkgconfig:$PKG_CONFIG_PATH

可以執行下面的命令檢查是否 /opt/gtk/lib/pkgconfig 路徑已經設定在 PKG_CONFIG_PATH 環境變數中:

$ echo $PKG_CONFIG_PATH

這樣設定之後,使用 Glib 庫的其它程式或庫在編譯的時候 pkg-config 就知道首先要到 /opt/gtk/lib/pkgconfig 這個目錄中去尋找 glib-2.0.pc 了(GTK+ 和其它的依賴庫的 .pc 檔案也將拷貝到這裡,也會首先到這裡搜尋它們對應的 .pc 檔案)。之後,通過 pkg-config 就可以把其中庫的編譯和連線引數提取出來供程式在編譯和連線時使用。

7.使用opencv例子程式來進行測試配置成功與否。

先在root目錄下建立一個opencv_samples檔案,然後把opencv自帶的C資料夾下的例子程式複製到opencv_samples資料夾下,

其中在make install過程時會預設把資原始檔放到/usr/local/share/OpenCV/檔案下,其裡面包含的內容是一些人臉、人眼級聯器等資料,所以複製檔案的指令是:

cd ~
mkdir openCV_samples
cp OpenCV-2.1.0/samples/c/* openCV_samples
cd openCV_samples/
chmod +x build_all.sh
./build_all.sh
接著就是執行可執行檔案,在當前目錄下使用 ls 指令來檢視哪些檔案是可以執行的(一般可執行檔案的顏色是不同的),接著就是執行它,並輸入一些資料,如下:
./facedetect --cascade="/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml" --scale=1.5 lena.jpg
結果為:




8.到此步位置如果沒問題的話,opencv的配置已經完成,但是我們如何判斷配置沒有問題呢?

我們通過如下指令:

pkg-config --cflags opencv
輸出結果為:


解釋:上面的指令指的是輸出opencv.pc裡面的標頭檔案路徑,因為在編譯程式的時候需要把標頭檔案的路徑、庫檔案告訴編譯器,在include包含的標頭檔案才不會出現未定義的情況。

第二個指令是:

pkg-config --libs opencv
輸出結果為:


這條指令的作用是把所需的庫檔案進行載入進來,而不是純粹的指出路徑。如果這兩條指令都有結果輸出,則證明opencv的配置路徑正確,

下面主要是對自己寫的例子進行編譯,剛開始我使用的是opencv開啟攝像頭然後抓取幀進行顯示的例子,當時遇到了兩個問題,第一個就是編譯,沒有區別gcc、g++。第二個是opencv自身讀取攝像頭的介面問題,出現讀取的影象亂碼等,要使用V4l2。

首先,我使用的是opencv3裡的例程,例子隨便,正確的編譯指令是使用g++,為:


其中包含pkg的兩個點是鍵盤左上角的那個按鍵---這個很重要,還有就是這兩個pkg在linux下使用了第三方庫時都是必須寫上去的,
到此步位置,祝賀完成任務。

小知識:就是關於修改了bash.bashrc裡的檔案後,因為其是開機時載入的,修改後要生效就必須重新載入,有兩個辦法:第一重新開機;第二使用指令 source /etc/bash.bash.rc  其中的source也可以使用‘ . ’黑點代替。

     接著就是裡面載入pkgconfig檔案的方法,因為我們的**.pc檔案是存在pkgconfig資料夾下的,所以我們需要在bash.bashrc檔案(這個檔案是ubuntu系統裡的,其它系統的檔案可能不一樣,我們只是需要把其pc檔案的載入路徑放大開機載入的檔案裡就行)裡指出其路徑,我的指令是:


其中,pkg_congfig_path名字可以修改的,

其中linux下的動態庫與靜態庫的製作:

linux 下動態連結庫的製作與使用
動態連結庫*.so的編譯與使用- -
動態庫*.so在linux下用c和c++程式設計時經常會碰到,最近在網站找了幾篇文章介紹動態庫的編譯和連結,總算搞懂了這個之前一直不太瞭解得東東,這裡做個筆記,也為其它正為動態庫連結庫而苦惱的兄弟們提供一點幫助。
1、動態庫的編譯
下面通過一個例子來介紹如何生成一個動態庫。這裡有一個頭檔案:so_test.h,三個.c檔案:test_a.c、test_b.c、test_c.c,我們將這幾個檔案編譯成一個動態庫:libtest.so。
so_test.h:
#include <stdio.h>
#include <stdlib.h>
void test_a();
void test_b();
void test_c();
test_a.c:
#include "so_test.h"
void test_a()
{
printf("this is in test_a...\n");
}
test_b.c:
#include "so_test.h"
void test_b()
{
printf("this is in test_b...\n");
}
test_a.c:
#include "so_test.h"
void test_c()
{
printf("this is in test_c...\n");
}
將這幾個檔案編譯成一個動態庫:libtest.so
$ gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so
2、動態庫的連結
在1、中,我們已經成功生成了一個自己的動態連結庫libtest.so,下面我們通過一個程式來呼叫這個庫裡的函式。程式的原始檔為:test.c。
test.c:
#include "so_test.h"
int main()
{
test_a();
test_b();
test_c();
return 0;
}
       將test.c與動態庫libtest.so連結生成執行檔案test:
$ gcc test.c -L. -ltest -o test
       測試是否動態連線,如果列出libtest.so,那麼應該是連線正常了
$ ldd test
       執行test,可以看到它是如何呼叫動態庫中的函式的。
3、編譯引數解析
最主要的是GCC命令列的一個選項:
      -shared 該選項指定生成動態連線庫(讓聯結器生成T型別的匯出符號表,有時候也生成弱連線W型別的匯出符號),不用該標誌外部程式無法連線。相當於一個可執行檔案
       -fPIC:表示編譯為位置獨立的程式碼,不用此選項的話編譯後的程式碼是位置相關的所以動態載入時是通過程式碼拷貝的方式來滿足不同程序的需要,而不能達到真正程式碼段共享的目的。
       -L.:表示要連線的庫在當前目錄中
       -ltest:編譯器查詢動態連線庫時有隱含的命名規則,即在給出的名字前面加上lib,後面加上.so來確定庫的名稱
       LD_LIBRARY_PATH:這個環境變數指示動態聯結器可以裝載動態庫的路徑。
       當然如果有root許可權的話,可以修改/etc/ld.so.conf檔案,然後呼叫 /sbin/ldconfig來達到同樣的目的,不過如果沒有root許可權,那麼只能採用輸出LD_LIBRARY_PATH的方法了。
4、注意
   呼叫動態庫的時候有幾個問題會經常碰到,有時,明明已經將庫的標頭檔案所在目錄 通過 “-I” include進來了,庫所在檔案通過 “-L”引數引導,並指定了“-l”的庫名,但通過ldd命令察看時,就是死活找不到你指定連結的so檔案,這時你要作的就是通過修改LD_LIBRARY_PATH或者/etc/ld.so.conf檔案來指定動態庫的目錄。通常這樣做就可以解決庫無法連結的問題了

附加的常識:

 編譯時,標準的標頭檔案在 /usr/include 下,系統編譯時預設自動到這搜尋。

 若要自定義的標頭檔案,使用者可通過在命令中加I(include的第一個字母) <庫路徑到額外指定的標頭檔案搜尋自己要包含的標頭檔案。

 而系統預設的連結庫搜尋路徑在 /usr/lib , /lib 下,若要連結自己制定的庫要在命令中加上 -l<庫名>  -L <庫的路徑>

 其中:–l指定要連結的具體庫名(lib的第一個字母)

-L到額外庫搜尋的路徑

 例:g++ hello.cpp –o hello –I /usr/lib/qt-3.1/include –lqt –L /usr/lib/qt-3.1/lib

解釋-lqt 代表連結 qt 庫,其中qt 庫在/usr/lib/qt-3.1/lib下的名是libqt.so

–L /usr/lib/qt-3.1/lib 代表路徑在/usr/lib/qt-3.1/lib 


參考文獻: