2008年7月14日 星期一

資料結構操作與運算-IplImage的標頭實作

一般的Bitmap格式圖片都會有標頭檔,而IplImage資料結構也不例外,IplImage有它自己的標頭資訊,而它可以只做到初始化或創立標頭資訊的部份,對於圖形資料的部份可以不存在,這部份,當在做圖片格式轉換,或是讀取.raw檔都可以應用到.

簡單的標頭製作
#include <cv.h>
#include <highgui.h>
#include <stdio.h>


int main()
{

    CvSize Size1;

    Size1=cvSize(320,240);
    IplImage *Image1=cvCreateImageHeader(Size1,IPL_DEPTH_8U,3);

    cvCreateData(Image1);
    cvSetZero(Image1);

    cvNamedWindow("Image1 Header",1);
    cvShowImage("Image1 Header",Image1);

    cvWaitKey(0);
    cvReleaseImage(&Image1);
    cvDestroyWindow("Image1 Header");
}

執行結果:


這個就只有簡單的做到創立一個標頭資訊cvCreateImageHeader(),在新增Image1格式的圖形RGB資料,cvCreateData()將會創立Channel三的一個uchar資料格式,照著Image1的標頭資訊,如果不用cvCreateData(),則Image1的空間將會是空的!無法在裡面新增圖形資料,再來cvSetZero()則是對他所有的BGR數值設為0.出來結果將會是黑色的.

標頭實作,圖形數據的轉換
#include <cv.h>
#include <highgui.h>
#include <stdio.h>


uchar imageData1[240][960];
float imageData2[240][960];

int main()
{
    CvSize Size1;

    Size1=cvSize(320,240);
    IplImage *Image1=cvCreateImageHeader(Size1,IPL_DEPTH_8U,3);

    cvSetImageData(Image1,imageData1,Image1->widthStep);
    cvSet(Image1,cvScalar(24.4,15.7,100.1));

    printf("%.1f ",cvGet2D(Image1,20,20).val[0]);
    printf("%.1f ",cvGet2D(Image1,20,20).val[1]);
    printf("%.1f\n",cvGet2D(Image1,20,20).val[2]);
    cvNamedWindow("Image1 Header",1);
    cvShowImage("Image1 Header",Image1);

    cvInitImageHeader(Image1,Size1,IPL_DEPTH_32F,3);

    cvSetImageData(Image1,imageData2,Image1->widthStep);
    cvSet(Image1,cvScalar(24.4,15.7,100.1));
    printf("%.1f ",cvGet2D(Image1,20,20).val[0]);
    printf("%.1f ",cvGet2D(Image1,20,20).val[1]);
    printf("%.1f\n",cvGet2D(Image1,20,20).val[2]);

    cvNamedWindow("Image1 Header (modify)",1);
    cvShowImage("Image1 Header (modify)",Image1);

    cvWaitKey(0);
    cvReleaseImageHeader(&Image1);
    cvDestroyWindow("Image1 Header");
    cvDestroyWindow("Image1 Header (modify)");
}

執行結果:


首先,先用cvCreateImageHeader()創立標頭資訊,cvSetImageData()則是有cvCreateData()的功能,但是要自己給它圖形矩陣空間,這個空間可以借其他圖形空間來用,只要有符合CvSize資料結構的寬高大小就好,cvSetImageData()的第三個參數則是要輸入IplImage資料結構它的總寬度,也就是width*nChannel,而cvSet()跟前面的cvSetZero()差不多,可以自行設立初始的RGB數據這邊cvSet()有另一個用法,就是遮罩(Mask)的應用,會在後面提到,而cvGet2D(),這邊直接用.val[0],.val[1]...因為CvGet2D()實際回傳的結構是CvScalar,因此就直接這樣寫用CvScalar底下的變數摟.再來是重新初始化Image1,這邊用cvInitImageHeader初始化參數為IPL_DEPTH_32F,並且重新設定float型別的空間,重新放置資料.比較兩個型別printf()出來的結果,可以發現,當uchar型別輸入CvScalar浮點數的時候它會被自動四捨五入.

而上面的執行結果"Image1 Header (modify)"是白色的,但實際上,cvShowImage()無法執行float型別的圖形格式,所以開啟的圖形為白色,由於一般圖形格式RGB範圍為整數的0~255,而float型別的數據大小就超出範圍了,因此,要注意cvShowImage()只能支援uchar格式的圖檔,參數為IPL_DEPTH_8U類型的.

cvCreateImageHeader()
創立一個IplImage資料結構的標頭資訊及標頭空間,內部不具imageData空間,如果直接存取圖形陣列會產生錯誤.
cvCreateImageHeader(CvSize空間大小資料結構,IplImage參數或代號,通道數據)

cvCreateData()
依照IplImage標頭資訊產生imageData空間圖形陣列,cvCreateImageHeader()+cvCreateData()=cvCreateImage().
cvCreateData(IplImage標頭資訊資料結構)

cvSetZero()
將IplImage資料結構內的imageData圖形空間資料全部設0.而他也有另外一個定義

#define cvZero cvSetZero

而可以跟cvZero()互通.
cvSetZero(IplImage資料結構)

cvSetImageData()
近似cvCrateaData()這邊可以自由設定imageData圖形矩陣空間,也可以自行設定具有資料的陣列空間,但是必須要符合標頭資訊的空間大小.第一個參數為IplImage標頭資訊,第二個為設定imageData空間,第三個為寬的大小總數(widthStep),cvSetImageData()被定義為

#define cvSetImageData    cvSetData

實際上他跟cvSetData()是一樣的.
cvSetImageData(IplImage標頭資訊資料結構,imageData自定空間型別,寬的總長度數據)

cvSet()
設立數據到IplImage資料結構的imageData圖形空間,類似cvSetZero()但是它具有遮罩(Mask)功能,可以選定特定目標位置區域才進行設定CvScalar顏色,因為cvSet()具有預設值mask=0,因此它可以只填兩個引數即可.
cvSet(IplImage資料結構,CvScalar設定顏色資料結構,IplImage資料結構目標Mask區域)

cvReleaseImageHeader()
釋放IplImage結構標頭記憶體空間.
cvReleaseImageHeader(IplImage標頭資料結構)



0 意見:

Copyright 2008-2009,yester