2012年7月17日 星期二

android架構

在Android架構,總共是由5個部份來組成。分別是:
(1)Applications(應用程式)
(2)Application Framework(應用程式架構)
(3)Libraries(函式庫)
(4)Android Runtime(Android執行環境)
(5)Linux Kernel(Linux核心)
大多數的網路資訊引用了類似這樣的圖形
我注意到比較有趣的是Binder (IPC) driver被嵌入了kernel,印象中這是android創建的IPC機制。許多人也知道android上的app開發大多是java,也就是java透過application framework在與底層的JNI以及Native的library做溝通,而我感興趣的就是底層的部分(application framework以下)
為何會對這部分有興致,主要想要操作camera以及最近遇到一個有人release出來的ICS版本,但是SD卡卻無法順利掛載,開始追蹤Vold這個deamon(android藉由uevent實作出來的一個動態掛載volumn的機制),或許就是為了喝牛奶養了一條牛吧XD
最後補上一個camera個架構圖
參考資料:
http://my.opera.com/ozzyyngwie/blog/android-an-open-mobile-platform
http://www.kandroid.org/online-pdk/guide/camera.html

Learning OpenCV -- chapter 3之一

OpenCV的主要四種基本資料結構
CvPoint => CvPoint2D32f, CvPoint3D32f,最前面為兩個整數變數x,y 後者則為浮點數
CvSize => CvSize2D32f,兩個整數變數width, height或者為浮點數的結構
CvRect有成員x, y, width, height
CvScalar,四個double的數值,再不考量記憶體使用量可以用來取代前面三者
通常constructor為cvPoint()或者cvSize,也就是第一個字母為小寫的function,在這裡雖然OpenCV是用c語言寫成,但是其實有不少物件的觀念,所以就借用了constructor一詞,但是並非真的是constructor

圖形的資料結構
CvArr
CvMat
IplImage
如果有個function要求CvArray*,則可以放入CvMat*或者IplImage*,同理要求CvMat*則可放入IplImage*,可以將關係視為繼承,也就是說is-a的關係



CvMat * cvCreateMat(int rows,int cols, int type);
表示這為一個二維陣列,望文生義,rows跟cols表示列跟行,type則是
CV_<bit_depth>(S|U|F)C<number_of_channels>
bit_depth也就是色階,S|U|F表示signed|unsigned|floating-point,C表示channel個數
CV8UC3,表示每個pixels由3個channel構成,每個channel用8bits表示
data則是實際儲存資料的地方
而cvCreateMat實際上呼叫了cvCreateMatHeader()與cvCreateMatData(),前者填充rows/cols/type等等,後者對儲存資料的空間作配置,所以如果不需配置記憶體的時候,或者共享某個區塊的時候,就只要呼叫cvCreateMatHeader就可以了。如果是複製某個區塊,使用cvCloneMat(CvMat*),有配置就必要釋放cvReleaseMat(CvMat*)

存取CvMat資料的方式有用Macro
CvMat *mat=cvCreateMat(5,5,CV_32FC1);
CV_MAT_ELE(*mat,float,3,2);
*((float*)CV_MAT_ELE_PRT(*mat,float,3,2))=5.5
由參數得知,必須要知道data的type才能計算到正確位置,還有就是它是一次性計算,也就是非指標運算,對於連續存取很沒效率

另外一種為cvPtr*D與cvGet*D的方式取得指標,用於各種維度
uchar* cvPtr1D(const CvArr* arr, int idx0, int *type=NULL)
uchar* cvPtr2D(const CvArr* arr, int idx0, int idx1, int *type=NULL)
uchar* cvPtr3D(const CvArr* arr, int idx0, int idx1, int idx2, int *type=NULL)
uchar* cvPtrND(const CvArr* arr, int *idx, int *type=NULL, int create_node=1, unsigned* precalc_hashval=NULL)
或者
double cvGetReal1D(const CvArra *arr, int idx0)
double cvGetReal2D(const CvArra *arr, int idx0, int idx1)
double cvGetReal3D(const CvArra *arr, int idx0, int idx1, int idx2)
double cvGetRealND(const CvArra *arr, int *idx)

CvScalar cvGet1D(const CvArr *arr, int idx0)
CvScalar cvGet2D(const CvArr *arr, int idx0, int idx1)
CvScalar cvGet3D(const CvArr *arr, int idx0, int idx1, int idx2)
CvScalar cvGetND(const CvArr *arr, int *idx)

其中cvPtr*D取得為每個pixel,如果有3個channel,則為rgbrgbrgb...等地排列方式,這部分區自行處理,好處是可以快速地訪問,另外有cvGet*D就有cvSet*D
另外要注意的是CvMat未必是連續空間,最多保證每個row是連續的

從上面可以看到IplImage的成員,大多可以望文生義
重要的有origin,表示原點座標是放置在IPL_ORIGIN_TL左上角(一般電腦圖形)或者IPL_ORIGIN_BL左下角(一般數學座標)
dataOrder表示資料是每個IPL_DATA_ORDER_PIXEL或者IPL_DATA_ORDER_PLANE,前者表示rgbrgbrg這樣的資料排列,後者表示rrrrr...ggggg...bbbbb....這樣三面的排列,所以儲存影像資料的imageData就受到這個參數的影響,必須知道資料正確的排列才能正確處理資料
ROI則是感興趣的範圍,用以將圖形特定範圍切出,用來處理這部分,有mask的觀念,可以使用
void cvSetImageROI(IplImage *img, CvRect rect)
void cvResetImageROI(IplImge *img)
可見一個IplImage只能設定一個ROI,但是要保留多個ROI,書中有範例技巧
參考資料:
http://yester-place.blogspot.tw/2008/07/cvmat.html
http://yester-place.blogspot.tw/2008/07/iplimage1.html

2012年7月16日 星期一

Learning OpenCV -- chapter 2

載入image到記憶體
IplImage *img=cvLoadImage(filepath);
載入avi檔案,並且使用cvQueryFrame取得下一個frame
CvCapture *capture=cvCreateFileCapture(path);
IplImage *frame;
for(...){ frame=cvQueryFrame(caputre);}
調整capture,cvSetCaptureProperty與cvGetCaputreProperty
cvSetCaptureProperty(caputre,CV_CAP_PROP_POS_FRAME,pos);
建立影像,第一個參數為大小,第二個為每個channel的bits數,第三個為通道數目
IplImage *out=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,3);
使用演算法
cvSmooth(img,out,CV_GAUSSIAN,3,3);
建立一半大小的影像
IplImage *out=cvCreateImage(cvSize(img->width/2,img->height/2),img->depth,img->nChannel);
cvPyrDown(img,out);
從上面可以知道,所有重要的資料都被封裝成struct,然後以指標的形式在傳遞

總結以上,OpenCV是一個C lib的library,提供一個快速開發的介面,有效的節省programmer的時間,我想主要的目的是驗證一些演算法吧,真的還蠻方便的

2012年7月15日 星期日

OpenCV 2.4與Visual C++ 2010 Express

主要參考這裡
http://www.cnblogs.com/freedomshe/archive/2012/04/25/2470540.html

大致上就是設定include、設定lib,還要設定linker lib,最後記得把環境變數加進來,讓程式找的到dll,之前裝VC 2008 Express因為忘記設定(其實是找不到orz,好個VS,設定改來改去),結果就一堆symbol找不到的問題

2012年7月14日 星期六

udev的流程

udev主要功能

  • 允許動態建立刪除裝置
  • 自行配置裝置編號
  • 根據規則建立名稱,而非固定名稱
  • 建立kobject物件


udev其實利用了kobject在/sys下面建立的動態的系統資訊,udev主要成分,namedev、libsys、udev

udev配合hotplug機制,每當有裝置加入的時候,建立sysfs(kobject)下的相對應節點,跟著呼叫namedev在/dev下建立相對應的裝置
如果理解bus、device與driver三者的關係,可以理解到udev功能是可以達成的,但是接著升起的疑問是,流程是如何呢?

bus會利用match這個操作方式尋找合適的device以及driver,但是因為需要kobject來在sysfs下建立相對應的結構,是否意味著要改寫driver?從參考資料的解說,應該是不必。udev會監控linux載入的module,自動生成kobject

所以一開始就註冊了bus,udev會在module載入的時候紀錄準備生成kobject,當裝置插入主機的時候,跟著建立device,使用bus尋找到相關driver,最後udev會生成kobject,也就是在/sys下建立相對應的目錄

bus(開機時候)=>driver/udev(載入module時候)=>device(裝置插入主機接上某個bus)=>/dev/xxx與/sys/bus/xxx建立(udev透過bus.match建立)

以上就是我的理解,不知道有沒有錯誤

參考資料:
http://daydreamer.idv.tw/rewrite.php/read-49.html

2012年7月4日 星期三

character driver的岔路上

不能免俗,絕大多數入門的linux driver,除了第一個hello world module之外,跟的就是character driver,因為他最貼近一般人使用fopen, fread, fwrite, fclose的直覺
推薦服用宋寶華的範例,但是在2ed chapter 6使用的測試指令為
echo "hello world"> /dev/globalmem
cat /dev/globalmem
以上可以正常運作,可是跟著我就開始試著其他組合
echo "hello world"> /dev/globalmem
echo "again"> /dev/globalmem
cat /dev/globalmem
開始似乎不大正常的運作,即使使用
echo "hello world"> /dev/globalmem
echo "again">> /dev/globalmem
cat /dev/globalmem
也於事無補,我開始懷疑ppos這個表示目前檔案位置的參數有沒以正確運作,在經過一番追蹤,似乎發現不如預期。我恍然大悟,原來要從process、file、inode角度去切入,就明白這一切了。


過程中我也寫了個簡單的程式,使用fopen, fread, fwrite, fclose去操作,因為一點點小小的失誤反而讓我看到一些覺得奇怪的地方,首先fopen, fread, fwrite, fclose的應該是對應到了driver內的operations,但是我在fopen的時候,最後讀寫模式寫錯了"w+",只寫了"w",結果編譯過程還是通過了,但是fread沒有作用,照樣有輸出,真是好神奇阿@@a有興趣的人可以用strace試驗看看

cross compile strace

指令如下
CC=arm-linux-gcc LD=arm-linux-ld RANLIB=arm-linux-ranlib ./configure --host=arm-linux --target=arm-linux --prefix=./install_dir
完成之後直接放到Target上就可以了
相關資料
https://www.ibm.com/developerworks/cn/linux/l-tsl/