2016年5月11日 星期三

網路概論,OSI七層,以及各層封包的英文名稱

下圖是OSI七層的架構圖,TCP/IP則將七層簡化為五層,另外圖片最右邊則是各層相對應的應用


















其中每一階層都會對封包有個別的名稱,其對應稱謂如下所示
 - 應用層(Application Layer)        Message
 - 傳送層(Transport Layer)           Segment
 - 網路層(Network Layer)             Datagram
 - 鏈結層(Data Link Layer)           Frame

了解以上稱謂,我們就可以清楚的知道是在講哪一層的封包處理




Router實作了OSI底下三層,如下圖










而Switch實作OSI底下兩層,如下圖










2016年2月5日 星期五

在Linux上使用類似system("PAUSE")的方法

system("PAUSE");
上面的語法使用在windows上的功能,可以等待使用者按了任意Key再繼續動作

然而這段語法放在Linux上是沒有任何作用的,如果在Linux上想使用類似的功能請使用如下的語法,可以讓使用者按了Enter再繼續:

====================================================
#include <stdio.h>

#define PAUSE {printf("Press Enter key to continue..."); fgetc(stdin);}

int main()
{
    PAUSE
    return 0;
}
====================================================

以上紅字的部分,就是使用方法~

2016年2月4日 星期四

Opencv,Mat的研究:depth(), channels(), elemSize(), dims, step

今天稍為花了一點時間 研究了一下使用Mat讀進了一張圖之後以下這些參數與函式所代表的意義   ===> depth(), channels(), elemSize(), dims, step


假設我們現在使用了下面這行程式碼讀了一張  780x1040(寬x高),彩色的圖片
Mat img1 = imread(test.jpg, IMREAD_UNCHANGED);


img1.depth(): 

代表每個pixel的位元(bit)數,在opencv中的Mat.depth()中得到的是一個0~6的數字,分別代表不同的位數,enum{ CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6}; 0和1都代表8位, 2和3都代表16位, 4和5代表32位,6代表64位,test.jpg為CV_8U因此img1.depth()=0。

img1.channels(): 

代表每個pixel的通到個數,以test.jpg為例為彩色的RGB圖,因此                                                   img1.channels()=3。

img1.elemSize(): 

img1.elemSize() = 3 (每一個元素包含3個uchar值), img1.elemSize1() = 1 (elemSize/channels); 矩陣中每一個元素的數據大小,如果Mat中的數據類型是CV_8U,則elemSize=1,若是CV_8UC3則elemSize=3,若是CV_16UC2則eleSize=4。

img1.dims: 

這張圖片的維度,以這張圖為例,寬x高是二為陣列的資料,所以img1.dims=2。

img1.step: 

step這個部分有兩個值可以取,第一個是img1.step[0],另一個是img1.step[1]。 img1.step[0]代表一列所有的數據大小,而img1.step[1]代表一個pixel的數據大小,所以img1.step[0]=img1 .cols * img1 .elemSize() = ˙780*3 = 2340,img1.step[1]=3,另外如果看到(int)img1.step這樣的寫法,也就是取img1.step[0]的意思。



以上~

2016年1月8日 星期五

OpenCV3.0 + VS2012 配置設定,並在此環境上編譯Depth_Map(SSCA專案)

看到Depth Map有一篇改善的Paper有附上原始碼,因此拿來編譯作測試。此專案需要使用到openCV的Library。
Paper名為: Cross-Scale Cost Aggregation for Stereo Matching
Source Code Path: https://github.com/rookiepig/CrossScaleStereo (VS2010專案)

要編譯此專案,首先必須先安裝好win7端的openCV(Extract到資料夾)以及VS2012,openCV部分我選擇比較新版的OpenCV 3.0版本,安裝部分我就不再贅述。

openCV的下載網址: http://opencv.org/downloads.html



下面開始說明如何讓一個Visual Studio專案檔能夠使用到openCV的Library,並且順利編譯專案:

1.配置Win7端的openCV環境變數
    電腦 =>(按滑鼠右鍵) 選內容 => 進階系統設定 => 進階(標籤)選環境變數 => 變數名Path上點     兩下 => 最後在變數值欄位的最後面加上自己的openCV路徑
假設opencv3.0安裝在 D:\opencv_win\    請加入值 ";D:\opencv_win\opencv\build\x64\vc11\bin;D:\opencv_win\opencv\build\x86\vc11\bin",如下圖所示:


















**這裡路徑裡的vc11代表是Visual Studio 2012。
另外其他的對應如下: vc8 = Visual Studio 2005, vc9=Visual Studio 2008, vc10=Visual Studio 2010,  vc11=Visual Studio 2012, vc12=Visual Studio 2013



2. 接下來就請開啟VS2012專案,專案名稱會是XXX.sln請使用VS2012把他開啟,由於我的專案當初是用VS2010撰寫的,所以會先跳出一個提示視窗,請直接選擇update,VS2012會幫你轉成VS2012可用的。





3. 再專案上按滑鼠右鍵,選擇Properties,如下圖:





4. 接著會出現如下圖的視窗,把Configuration選為All Configurations,另外Platform暫時不作更改維持Win32即可,如下圖所示:





5. 選擇左邊的 Configuration Properties  => C/C++  => General     點選右邊Additional Include Directories右邊的小箭頭會出現Edit選項,請點選Edit。接著會出現一個小視窗,請在空白地方填入 openCV的Include表頭檔的路徑,請分別填入下面3個路徑:

D:\opencv_win\opencv\build\include
D:\opencv_win\opencv\build\include\opencv
D:\opencv_win\opencv\build\include\opencv2

如下圖所示:

  


6. 選擇左邊的 Linker => General   點選右邊Additional Library Directories右邊的小箭頭會出現Edit選項,請點選Edit。接著會出現一個小視窗,請在空白地方填入 openCV的lib函式庫的路徑,請填入下面路徑:

      32位元請填:  D:\opencv_win\opencv\build\x86\vc11\lib(此SSCA專案填這個值)

      64位元請填:  D:\opencv_win\opencv\build\x64\vc11\lib(如果專案須用到64位元的請填這個)

如下圖所示:

  



7. 選擇左邊的 Linker => Input   點選右邊Additional Dependencies 右邊的小箭頭會出現Edit選項,請點選Edit。接著會出現一個小視窗,請在空白地方填入 openCV的dll函式庫名稱,請填入:
opencv_ts300.lib
opencv_ts300d.lib
opencv_world300.lib
opencv_world300d.lib

如下圖所示:

  


基本上照上面的步驟作完,Project就可以正常的編譯過了!!


附註:
############################################################ 
如果你編譯的Project跟作者一樣是 SSCA這個Project的話,記得要去修改兩個檔案才可以順利編譯過關,分別是:
SSCA\CAST\StereoDisparity.h
SSCA\CommFunc.h


裡面的Code原本是引用openCV 2.4.6 請把它改成引用 openCV 3.0的,請改成如下:
// Opencv Lib 3.0
#pragma comment( lib, "opencv_ts300.lib" )
#pragma comment( lib, "opencv_ts300d.lib" )
#pragma comment( lib, "opencv_world300.lib" )

#pragma comment( lib, "opencv_world300d.lib" )

#####################################################################



2015年10月13日 星期二

使用printf印出有顏色的Console訊息

有時候Console訊息很多,如果能把自己想看的訊息加點顏色,可以加快Debug速度

下面記錄了一個基於printf可以印出彩色訊息的function。

====================================================================
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

#define NONECOLOR "\033[m"
#define RED "\033[0;32;31m"
#define LIGHT_RED "\033[1;31m"
#define GREEN "\033[0;32;32m"
#define LIGHT_GREEN "\033[1;32m"
#define BLUE "\033[0;32;34m"
#define LIGHT_BLUE "\033[1;34m"
#define DARY_GRAY "\033[1;30m"
#define CYAN "\033[0;36m"
#define LIGHT_CYAN "\033[1;36m"
#define PURPLE "\033[0;35m"
#define LIGHT_PURPLE "\033[1;35m"
#define BROWN "\033[0;33m"
#define YELLOW "\033[1;33m"
#define LIGHT_GRAY "\033[0;37m"
#define WHITE "\033[1;37m"


//**********************************************************
// Usage Example:
// int num=7;
// COLOR_DBG("%s Lucky Number is %d", GREEN, num);     
//
// Description:
// This message will show Green color.
//
// viod COLOR_DBG(const char* Format, const char* Color, const char* str, ...)
void COLOR_DBG(const char* Format, ...)
{
char str[255];
va_list ap;
va_start(ap,Format);
vsprintf(str,Format,ap);
sprintf(str,"%s%s",str,NONECOLOR);
printf("%s",str);
va_end(ap);
}


int main()
{
COLOR_DBG("%s Hello World!!!!!\n", YELLOW);
return 0;
}
=====================================================================

以下是使用gcc compiler後執行結果的截圖!


2015年10月7日 星期三

將C++的function包裝成Library(so檔)給C的程式使用

今天要練習的是,把C++的Function包給C程式使用時該怎麼作

首先我們先撰寫一支簡單的C++程式,如下所示
////////////////////  cplus_lib.cpp  ////////////////////////
#include <iostream>
using std::cout;

void cout_func()
{
cout << "Hello World!\n";
}
//////////////////////////////////////////////////////////////////

接著我們將她打包成動態連結檔libcplus_lib.so,步驟如下:
1. gcc -Wall -O2 -c -o cplus_lib.o cplus_lib.cpp
2. gcc -shared -o libcplus_lib.so cplus_lib.o

經過以上兩個步驟,我們可以得到動態連結檔的函式庫 libcplus_lib.so






接著我們試著再寫一支C程式,此程式去使用函式庫的cout_func()來印出"Hello World"
///////////////////////  main_cout.c  //////////////////////////////
#include <stdio.h>

int main()
{
        cout_func();
        return 0;
}
/////////////////////////////////////////////////////////////////////////////

接著編譯過程如下,注意要額外指定C++ 標準函式庫 libstdc++:
1.gcc -o main_cout_dynamic main_cout.c -L. -lcplus_lib -lstdc++

結果會出下以下的錯誤訊息:












解決方法,要在產生library的程式當中加入一些東西,如下所示:
////////////////////  cplus_lib.cpp  ////////////////////////
#include <iostream>
using std::cout;

#ifdef __cplusplus
extern "C" {
#endif
void cout_func()
{
cout << "Hello World!\n";
}
#ifdef __cplusplus
}
#endif
//////////////////////////////////////////////////////////////////
註:上面程式碼的意思是: 如果這是一段cpp的程式碼,就加入extern "C"{} 來處理其中的程式碼


這樣子編譯器才看得懂,所以再整個重新編譯一次,就成功了!
















註: 上圖第三行,作者把產生出來的library複製到library環境變數的預設路徑下,如果不這樣作,當執行main_cout_dymanic時,會出現找不到library的錯誤訊息,關於這部分作者正在尋找可以自己指定吃特定路徑的library的方法.....

如果有朋友知道方法,也請給予指教,謝謝!

2015年9月23日 星期三

linux下使用ping指令來快速知道網路是否連上Internet

最近再作NTP(網路同步時間)的功能,因此在使用者選擇好要同步的NTP Server之前,我必須先確認網路是可以連上Internet的

ping -q -c1 -W1 168.95.1.1

上面是關鍵的command,使用ping再加上它的一些參數,可以很快的知道網路是否有連上Internet。

這裡先說明一下ping參數的意義:
-q     => 不顯示任何傳送封包的資訊,只顯示最後的結果
-c1   => 在發送指定數目的包後停止,c1也就是只發一次的意思
-W1 => 等待回應的時間,W1就是只等待一秒


詳細的程式碼如下:
===================================================================

// NTP Server
#define NTP_SERVER_1 "tock.stdtime.gov.tw"      //response time is short.
#define NTP_SERVER_2 "tw.pool.ntp.org"
#define CH_TELECOM "168.95.1.1"                       //中華電信DNS

int ping_result(char *server)
{
        char cmd[64]={0};
        int ping_ret, status;

        sprintf(cmd, "ping -q -c1 -W1 %s 1>/dev/null 2>&1", server);
        status = system(cmd);
        if(-1 != status)
                ping_ret = WEXITSTATUS(status);

        if((status == 0) && (ping_ret == 0))    // If network can work on internet, these two value will be zero.
                return 1;
        else
                return 0;
}

void ping_ntp()
{
        int pingResult = ping_result(CH_TELECOM);    //ping CHT DNS first.
        if(pingResult == 1)
        {
                pingResult = ping_result(NTP_SERVER_1);      //second ping NTP Server.
        }

        if(pingResult == 0 )
        {
                printf("NETWORK_ERROR");
        }
        else
        {
                printf("RESPONSE_SUCCESS");
        }
}
=================================================================

這裡再說明一下,上面的ping_ntp的function當中,我會先去ping中華電信的DNS(168.95.1.1),這樣可以先知道是否有通Internet,第二步才去確認NTP SERVER是可以work的,若是連Internet都不通,也不必再花時間去ping NTP SERVER了~