Showing posts with label Linux. Show all posts
Showing posts with label Linux. Show all posts

Monday, June 21, 2010

How to Install OpenCV on Linux (Ubuntu)

前言
對許多人來講, 在Windows下安裝OpenCV會比在Linux下安裝相對來得輕鬆Windows下, 沒錯, 您幾乎只需要重複「下一步」的動作就可以安裝大部分的程式, 但其實在Linux下亦不難, 或許只是您不熟悉如何去下指令? 沒關係, 這篇文章簡單整理了在Ubuntu底下安裝OpenCV的兩種方法其一, 是當您想更改OpenCV的source code並自己重新編譯的方法;  另外, 則是一般的apt-get安裝方式。底下我將一步步來介紹整個流程

Before the installation」
  • 為了可以重新編譯OpenCV, 系統中必須要有C++ compiler, 如果沒有, 我們可以透過以下指令來安裝

    $ sudo apt-get install g++
    
  • 為了圖片的播放, 我們需要GTK+, 它是一個跨平台的圖形介面函式庫, GNOME即是利用GTK+來開發的。首先, 我們可以藉由以下命令來查看系統安裝了哪個版本的GTK+

    $ dpkg -l | grep libgtk
    or, 可以直接安裝

    $ sudo apt-get install libgtk2.0-dev


「Install OpenCV on Ubuntu (method 1)」
  1. http://sourceforge.net/projects/opencvlibrary/files/下載原始碼(Linux版
  2. 解壓該原始碼檔案, 且切換至該目錄假設下載的是opencv-1.0.0.tar.gz, 則我們可以使用下列命令

    tar zxvf opencv-1.0.0.tar.gz
    cd opencv-1.0.0
  3. 檢查系統所需環境是否已經安裝完畢
  4. ./configure
    當出現「Now run make...」則表示可以開始編譯了, 否則, 必須安裝所需安裝的套件
  5. 編譯OpenCV
  6. make
  7. 使用root權限來安裝OpenCV
  8. sudo make install
  9. 增加路徑/usr/local/lib」到/etc/ld.so.conf」中, 這一步主要是在設定動態函式庫的路徑,  其中/etc/ld.so.conf就是目前系統中主要用來放置函式庫的目錄
  10. 設定完路徑後, 必須重建動態函式庫目錄
  11. ldconfig



「Install OpenCV on Ubuntu (method 2)
Ubuntu底下的Synaptic Package Manager方便了我們對於各種軟體的安裝, 並且隨時可以線上更新最新版本。對於利用Synaptic來安裝OpenCV, 我們只需收尋OpenCV且套用所收尋到的套件, 就可以直接安裝了, 安裝畫面如下


或者, 您也可以打開terminal輸入想安裝的套件, 如下面指令
$ sudo apt-get install libcv4 libcvaux4 libhighgui4
$ sudo apt-get install libcv-dev libcvaux-dev libhighgui-dev
當然, 指令會因函式庫的版本名稱不同而有所不一樣最後, 設定環境變數
export LD_LIBRARY_PATH=/home/opencv/lib
export PKG_CONFIG_PATH=/home/opencv/lib/pkgconfig

「執行OpenCV範例程式
底下, 我測試了OpenCV給的範例程式camshiftdemo.c,切換到範例所在目錄且利用以下命令編譯及執行
$ g++ -I/usr/include/opencv -lcxcore -lhighgui -lm camshiftdemo.c
$ ./a.out
執行畫面如下

Sunday, January 31, 2010

Locks for Data Synchronization

「簡介」

在OS課程中提到,Process Communication分為兩大類: 「Shared Memory」、「Message Passing」,接下來即是一大串的討論,所針對的便是Shared Memory所可能產生的問題,以及其解決方案,並提出一些有名的例子,像是「Producer/Consumer Problem」、「Dining Philosophers」等等的例子,我們可以發現重點在於怎麼讓其共享的變數或資料能夠「一致」,為了使其一致,必須規定一些存取上的機制,也就是說,當某個process在存取某個變數時,我們希望其它process可以暫緩存取該變數,這樣才能維持資料的一致性以及使其同步(synchronization),因此,我們必須設計一些鎖(Locks),這些鎖使得process可以鎖定正在使用的區段,而避免被其它process存取,這篇文章的目的就是要描述不同鎖的特性。

「Locks」
不同的系統,提供其各自不同特性的鎖,例如SQL Server,在資料庫的處理上需要透過鎖來幫忙整頓transaction,而這邊要介紹的是在Linux系統中「fcntl」 這個system call所提供的locks。

「Shared Lock」VS「Exclusive Lock」
以下這段描述來自IBM solidDB系統的文件[Ref.1],
    An exclusive lock allows only one user/connection to access (read or update) a particular piece of data. A shared lock allows multiple users to read data, but doesn't allow any of them to update the data.
   
    .........

    Shared and exclusive locks cannot be mixed. If you have an exclusive lock on a record, I cannot get a shared lock (or an exclusive lock) on that same record.
其實Linux系統中的「fcntl」所提供的「Shared Lock」及「Exclusive Lock」除了名稱跟IBM solidDB的Locks取得一樣,其功能亦相同。所以說,Shared Lock是可以由多個process所共享,即共同鎖定某個檔案的某個區塊,然而,當已經有一個process對某檔案的某區塊設定了Shared Lock,則其它任何的process就無法對該區塊設定Exclusive Lock;而關於Exclusive Lock,對於某個檔案的某個區塊只能被唯一一個process對其設定Exclusive Lock。


「fcntl系統呼叫的使用」

  • 標頭檔的引入及變數宣告
#include<fcntl.h>
struct flock region1;

  • 使用Shared Lock來鎖定區塊的第5位元組到第10位元組
region1.l_type = F_RDLCK;
region1.l_whence = SEEK_SET;
region1.l_start = 5;
region1.l_len = 5;

  • 使用Exclusive Lock來鎖定區塊的第5位元組到第10位元組      
region1.l_type = F_WRLCK;
region1.l_whence = SEEK_SET;
region1.l_start = 5;
region1.l_len = 5;


 「Examples」
舉例來說,假設有個Process1開啟了fileA並對這個檔案做一些鎖定如下:
  • Process1利用Shared Lock來鎖定fileA的第5個Byte到第10個Byte

  • Process1利用Exclusive Lock來鎖定fileA的第20個Byte到第30個Byte

  • fileA的第20個Byte到第30個Byte只允許Process1讀寫 

那麼,當另外有個Process2要來對fileA做存取時,我們可以看到:
  • Process2可以存取fileA未被Process1鎖定的部份

  • Process2對於fileA第5個Byte到第10個Byte只能read不能「write

  • Process2對於fileA第20個Byte到第30個Byte不能read,也不能「write

以上就是Shared Lock以及Exclusive Lock的介紹


[Reference]
[1] http://publib.boulder.ibm.com/infocenter/soliddb/v6r3/index.jsp
[2] Beginning Linux Programming 4/e, Richard Stones and Neil Matthew

Saturday, October 10, 2009

POSIX termios interface for canonical/non-canonical mode switching


前言
POSIX termios interface,提供一個介面讓我們可以做Termios Programming然而,Termios Programming是一個很大的主題,並且有許多的應用我們可以透過它來控制terminal在處理字元上的一些設定此外Serial Programming也是需要透過它來做一些設定,例如:設定Baud Rate或Parity Checking。甚至,它可以用來存取RS-232的serial port,並且做client-server終端控制的一些應用。而在這篇我想介紹的是利用termios來切換終端機接收字元的標準/非標準模式(canonical/non-canonical mode

Termios簡介
Termios是一個符合POSIX的介面有定義一些函式或巨集除了控制I/O; 它還可以控制硬體,例如決定使用多少位元來傳送跟接收字元; 並且,它也可以控制終端機的特性,例如決定終端機接收字元的模式(接下來本篇文章將以此來舉例); 最後,它也針對一些字元提供特殊的控制

標準/非標準模式(canonical/non-canonical mode)
不管在MS-DOS或是LINUX的終端機相信大家較常使用的是標準模式,而簡單的說,它就是允許使用者在按下Enter鍵前仍然可以修改輸入的字元(例如使用Backspace鍵來修改),所以按下Enter鍵,程式才會讀取字元。相對來說,非標準模式會讀取使用者輸入的任何字元,當然,我們可以利用termios來控制這些輸入,例如我們可以決定在非標準模式下,當使用者輸入多少個字元時即把這些字元傳送給終端機

如何利用termios來切換標準與非標準模式
底下就開始介紹如何使用termios來切換標準與非標準模式
1) 首先,要使用termios我們當然需要先把它include進來

#include <termios.h>

2) 接下來,宣告兩個termios結構(需要宣告兩個是因為,程式在做完任何只有程式本身所需的設定後,在程式結束前必須負責切換回終端機原本的設定,以免影響其它使用)

struct termios initial_settings, new_settings;

3) 取得目前終端機初始設定,並將設定存到initial_settings

tcgetattr(fileno(stdin),&initial_settings);

4) initial_settings複製給new_settings

new_settings = initial_settings;

5) 利用new_settings來做我們想要的設定,以我們的例子來講,我們需要切換成非標準模式

new_settings.c_lflag &= ~ICANON
6) 復原終端機原本的設定

tcsetattr(fileno(stdin),TCSANOW,&initial_settings);

如此,便可以切換成非標準模式,此外,在非標準模式下termios還有很多功能例如使用VTIMEVMIN來控制輸入舉個例子,每當使用者輸入兩個字元,終端機就自動接收這兩個字元,可以這麼寫

new_settings.c_cc[VMIN] = 2;
new_settings.c_cc[VTIME] = 0;

VMIN代表的是非canonical模式讀的最小字元數目。而VTIME代表讀取字元跟字元中間的延遲時間,設定成0代表不可慮VTIME。然而VMIN跟VTIME有許多不同組合,各代表著不同的意義,這就不是本篇文章討論範圍了

結論
termios允許我們去跟一些硬體做溝通,例如透過serial port跟其他設備溝通,目前又以嵌入式系統比較常需要使用,然而在PC上,由於各種傳輸規格日益增進,因此serial port的方法也慢慢被取代了

[Reference]
Beginning Linux Programming 4/e, Richard Stones and Neil Matthew