2008年7月10日 星期四

資料結構操作與運算-IplImage資料結構操作(1)

前面的IplImage資料結構介紹的部份,是用直接存取的方式對IplImage資料結構直接提取它的值,而實際上,OpenCV的程式人員希望能刻意的將IplImage包起來,用副程式間接存取的方式去給使用者操作,由於OpenCV是以C語言為基礎的,因此它無法做到物件導向封裝的操作,因此資料結構內的數值是可以任意檢視的,不會有public及private的影響,而OpenCV提供了以下對IplImage操作的函式.

IplImage資料結構的操作
#include <cv.h>
#include <highgui.h>
#include <stdio.h>


int Dims;
int Height;
int Width;
int COIChannel;

int main()
{
    IplImage *Image1;
    CvRect Rect1,Rect2;

    uchar *ptr1;
    CvSize Size1;
    CvScalar Scalar1;

    Image1=cvLoadImage("bower.jpg",1);

    Dims=cvGetDims(Image1,0);
    Height=cvGetDimSize(Image1,0);
    Width=cvGetDimSize(Image1,1);

    Rect1=cvRect(140,305,115,165);
    cvSetImageCOI(Image1,1);
    cvSetImageROI(Image1,Rect1);

    COIChannel=cvGetImageCOI(Image1);
    Rect2=cvGetImageROI(Image1);
    Size1=cvGetSize(Image1);

    ptr1=cvPtr2D(Image1,50,40);

    Scalar1=cvGet2D(Image1,50,40);

    printf("pic ROI Information==\n");
    printf("Dims is : %d\n",Dims);
    printf("Height is : %d\n",Height);
    printf("Width is : %d\n",Width);
    printf("Set COI is : %d\n",COIChannel);
    printf("ROI Size is : (%d,%d)\n\n",Size1.height,Size1.width);

    printf("The Pointer 2D (50,40)Channels is : %d %d %d\n",*ptr1,*(ptr1+1),*(ptr1+2));
    printf("The Scalar 2D (50,40) Channels is : %.1f %.1f %.1f\n",Scalar1.val[0],Scalar1.val[1],Scalar1.val[2]);

    cvSet2D(Image1,50,40,cvScalar(255,255,255));
    printf("The Pointer 2D (50,40)Channels is : %d %d %d\n",*ptr1,*(ptr1+1),*(ptr1+2));

    cvNamedWindow("Bower ROI",1);

    cvShowImage("Bower ROI",Image1);
    cvResetImageROI(Image1);
    cvNamedWindow("Bower",1);
    cvShowImage("Bower",Image1);
    cvWaitKey(0);

}

原始圖片:


執行結果:


一開始,開啟圖檔設定給ROI的CvRect資料結構大小空間,用cvSetImageCOI()設定感興趣的顏色(Color Of Interesting)設定為通道一,藍色,用cvSetImageROI()選定感興趣的區域而相對的,cvGetImageCOI()跟cvSetImageROI()則是取得資訊,cvGetDims()為取得維度,因為是圖片,所以當然是二維,再來是取得寬跟高,它也可以使用cvGetSize()取得CvSize資料結構的寬跟高資訊,cvPtr2D()是用指標的方式取得圖片座標位置,並且數據為通道一,藉由指標運算+1的方式如*(ptr1+1),可以取得通道二,通道三...由於取得的是指標位置,所以可以直接對它做直接修改數值,而cvGet2D()是傳值呼叫,必須要對它做cvSet()2D才能完成存取的動作,這是物件導向裡很基本Get跟Set的概念,而後面就直接用指標*ptr1得方式直接printf()修改的值出來,最後的部份cvResetImageROI()將ROI重置,因此就還原成原來的圖片了,值得注意的是,這邊修改了其中的一個點,而重置後,被修改的點的部份仍然不會恢復原狀,ROI只是對圖形做平移及縮小檢視範圍罷了.另一個比較重要的部份cvPtr2D()輸出為uchar *型別,cvGet2D()為CvScalar資料結構,在存取的時候千萬不能搞錯了,尤其是cvPtr2D()這個函式.

在OpenCV對IplImage資料結構的操作是很隨意的,很多函式甚至可以直接跟CvMat資料結構共用,但實際上,這是危險的,OpenCV的開發沒有做到降低程式設計的耦合性,也因為IplImage跟CvMat所使用的副程式及變數是有衝突,對於那些共用的副程式的回傳值套用在兩個不同的資料結構上,對使用者來講會有凌亂的困擾,但是它仍是有優點,它會比一些被封裝整理過的程式快一些,這仍會是個事實.

cvSetImageCOI()
設定感興趣的顏色(Color Of Interesting),第一個引數為IplImage資料結構,第二個引數為通道數據,如果為0表示不設立
cvSetImageCOI(IplImage資料結構,通道數據)

cvSetImageROI()
設定感興趣的區域(Region Of Interesting),第一個引數為IplImage資料結構,第二個引數為CvRect選取的區域大小.
cvSetImageROI(IplImage資料結構,RvRect區塊資料結構)

cvGetImageCOI()
取得圖形設定COI數據.
cvGetImageCOI(IplImage資料結構)

cvGetImageROI()
取得圖形ROI數據
cvGetImageROI(IplImage資料結構)

cvResetImageROI()
重置圖形ROI,也就是將CvRect所選定的區域取消掉,但是CvRect區域內修改的值不會被復原.
cvResetImageROI(IplImage資料結構)

cvGetDims()
取得維度資訊,這邊可以跟IplImage,CvMat共用,當然,圖片一定是二維陣列
cvGetDims(IplImage資料結構或CvMat資料結構)

cvGetDimSize()
取得IplImage圖形或CvMat矩陣的空間大小數據0為高(height)/列(row),數據1為寬(width)/欄(colunm)
cvGetDimSize(IplImage資料結構或CvMat資料結構,空間大小代號)

cvGetSize()
取得IplImage圖形或CvMat矩陣的空間大小,回傳值是CvSize資料結構.
cvGetSize(IplImage資料結構或CvMat資料結構)

cvPtr2D()
取得二維空間的座標值,此為一整串的函式之一,包括有

cvPtr1D()
cvPtr2D()
cvPtr3D()
cvPtrND()

3D跟ND則不能用IplImage及CvMat實作,這系列函數回傳值都是uchar *型別的記憶體位址,利用指標+1,+2,+3可以選擇其他通道
cvPtr2D(IplImage資料結構或CvMat資料結構,X軸座標數據,Y軸座標數據)

cvPtr1D()
取得一維空間的座標值,回傳值為uchar *記憶體位址,也可以用來取得二維陣列座標值(因為IplImage,CvMat資料結構都是由一維陣列組合而成的),但是不建議用一維函式去實作二,三維空間只是增加程式設計得難度及降低可讀性
cvPtr1D(IplImage資料結構或CvMat資料結構,一維陣列Index數據)

cvGet2D()
取得二維空間的純量值(CvScalar),亦為一整串的函式之一,其中包括有

cvGet1D()
cvGet2D()
cvGet3D()
cvGetND()

3D及ND不支援IplImage資料結構及CvMat,回傳值皆為CvScalar資料結構,對應cvSet*D()系列函數.
cvGet2D(IplImage資料結構或CvMat資料結構,X軸座標數據,Y軸座標數據)

cvGet1D()
取得IplImage資料結構及CvMat資料結構一維空間的純量值(CvScalar),可以用來取得二維陣列座標值,但不建議二維陣列用cvGet1D()實作.
cvGet1D(IplImage資料結構或CvMat資料結構,一維陣列Index數據)

cvSet2D()
為cvGet*D()系列的對應,也為一整串函式之一,其中包括

cvSet1D()
cvSet2D()
cvSet3D()
cvSetND()

為設定IplImage,CvMat純量數據之用途.
cvSet2D(IplImage資料結構或CvMat資料結構,X軸座標數據,Y軸座標數據,CvScalar資料結構)

cvSet1D()
設定IplImage資料結構及CvMat資料結構一維空間的純量值(CvScalar),可以用來取得二維陣列座標值,但不建議二維陣列用cvSet1D()實作.
cvSet1D(IplImage資料結構或CvMat資料結構,一維陣列Index數據,CvScalar資料結構)



2 意見:

sbphsho 提到...

,cvGetImageCOI()跟cv"S"etImageROI()則是取得資訊

"筆誤"?

恩歪批居 提到...

cvGet2D和cvSet2D
的x,y座標要交換

Copyright 2008-2009,yester