日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

05-VTK在图像处理中的应用(2)

發(fā)布時間:2025/7/14 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 05-VTK在图像处理中的应用(2) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?

5.4 vtkImageData基本操作

圖像處理離不開一些基本的圖像數(shù)據(jù)操作,例如獲取和修改圖像的基本信息,訪問和修改圖像像素值,圖像顯示,圖像類型轉(zhuǎn)換等等。熟練掌握這些基本操作有助于使用VTK進(jìn)行圖像處理的快速開發(fā)。

?

5.4.1圖像信息訪問和修改

vtkImageData中提供了多個函數(shù)用于訪問或者獲取圖像的基本信息,這些函數(shù)通常使用Set或者Get加上相應(yīng)的信息名的形式,例如獲取圖像維數(shù)的方法定義為GetDimensions()。當(dāng)然這里主要從類的層次上進(jìn)行VTK的學(xué)習(xí),這里不再具體贅述每個函數(shù)的基本名稱和使用,用戶可以查閱相應(yīng)的類文檔。下面通過一個例子來說明怎樣訪問圖像的基本信息。程序運(yùn)行如圖5.8所示。

?

1:? ??vtkSmartPointer<vtkBMPReader>reader =

2:??? vtkSmartPointer<vtkBMPReader>::New();

3:? reader->SetFileName ( "..\\lena.bmp");

4:? reader->Update();

5:??

6:?? int dims[3];

7:??reader->GetOutput()->GetDimensions(dims);

8:?? std::cout<<"圖像維數(shù):"<<dims[0]<<" "<<dims[1]<<""<<dims[2]<<std::endl;

9:??

10:? double origin[3];

11:? reader->GetOutput()->GetOrigin(origin);

12:? std::cout<<"圖像原點(diǎn):"<<origin[0]<<" "<<origin[1]<<""<<origin[2]<<std::endl;

13:??

14:? double spaceing[3];

15:?reader->GetOutput()->GetSpacing(spaceing);

16:? std::cout<<"像素間隔:"<<spaceing[0]<<" "<<spaceing[1]<<""<<spaceing[2]<<std::endl;

17:??

18:??

19:? vtkSmartPointer<vtkImageViewer2>p_w_picpathViewer =

20:???vtkSmartPointer<vtkImageViewer2>::New();

21:?p_w_picpathViewer->SetInputConnection(reader->GetOutputPort());

22:?vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor=

23:???vtkSmartPointer<vtkRenderWindowInteractor>::New();

24:?p_w_picpathViewer->SetupInteractor(renderWindowInteractor);

25:? p_w_picpathViewer->Render();

26:?p_w_picpathViewer->GetRenderer()->ResetCamera();

27:? p_w_picpathViewer->Render();

28:??

29:? renderWindowInteractor->Start();

?

圖5.8 VTK圖像基本信息獲取

?

上例中主要獲取了圖像的三個信息,圖像維數(shù),圖像原點(diǎn)和像素間隔。VTK中二維和三維圖像都用vtkImageData表示,因此第六行中定義圖像維數(shù)為dims[3],然后利用GetDimensions()函數(shù)獲取圖像的維數(shù);圖像的原點(diǎn)和像素間隔都是物理空間數(shù)值,因此都是定義double類型。本例讀入了二維lena圖像,上圖中顯示了獲取的圖像信息。其中,圖像維數(shù)為512*512*1,通過維數(shù)可以看成z方向的維數(shù)為1,說明該圖像為二維圖像;而圖像的原點(diǎn)為(0,0,0)點(diǎn),而像素間隔為(1,1,1)。

?

vtkChangeImageInformation

vtkImageData中提供了多個Set函數(shù)用于設(shè)置圖像的基本信息。當(dāng)對一個管線的輸出修改圖像信息后,如果管線重新Update,那么這些修改都會恢復(fù)回原來的值。而vtkChangeImageInformation可以作為管線中的一個filter來修改圖像信息。利用這個filter可以修改圖像的原點(diǎn),像素間隔,以及范圍起點(diǎn)(extent),另外還可以對圖像平移縮放等操作。下面代碼說明了怎樣修改圖像的原點(diǎn),像素間隔。

?

1:???? vtkSmartPointer<vtkBMPReader> reader=

?? 2:????????vtkSmartPointer<vtkBMPReader>::New();

?? 3:????reader->SetFileName ( "..\\lena.bmp" );

?? 4:????reader->Update();

?? 5:??

?? 6:????int dims[3];

?? 7:????double origin[3];

?? 8: ????double spaceing[3];

?? 9:??

? 10:????reader->GetOutput()->GetDimensions(dims);

? 11:????std::cout<<"原圖像維數(shù):"<<dims[0]<<" "<<dims[1]<<""<<dims[2]<<std::endl;

? 12:????reader->GetOutput()->GetOrigin(origin);

? 13:????std::cout<<"原圖像原點(diǎn):"<<origin[0]<<" "<<origin[1]<<""<<origin[2]<<std::endl;

? 14:????reader->GetOutput()->GetSpacing(spaceing);

? 15:? std::cout<<"原像素間隔:"<<spaceing[0]<<" "<<spaceing[1]<<""<<spaceing[2]<<std::endl<<std::endl;

? 16:??

? 17:????vtkSmartPointer<vtkImageChangeInformation> changer =

? 18:????????vtkSmartPointer<vtkImageChangeInformation>::New();

? 19:????changer->SetInput(reader->GetOutput());

? 20:????changer->SetOutputOrigin(100, 100, 0);

? 21:????changer->SetOutputSpacing(5,5,1);

? 22:????changer->SetCenterImage(1);

? 23:????changer->Update();

? 24:??

? 25:??

? 26:????changer->GetOutput()->GetDimensions(dims);

? 27:????std::cout<<"修改后圖像維數(shù):"<<dims[0]<<" "<<dims[1]<<""<<dims[2]<<std::endl;

? 28:????changer->GetOutput()->GetOrigin(origin);

? 29:????std::cout<<"修改圖像原點(diǎn):"<<origin[0]<<" "<<origin[1]<<""<<origin[2]<<std::endl;

? 30:????changer->GetOutput()->GetSpacing(spaceing);

? 31:????std::cout<<"修改后像素間隔:"<<spaceing[0]<<" "<<spaceing[1]<<""<<spaceing[2]<<std::endl;

? 32:??

? 33:??

? 34:????vtkSmartPointer<vtkImageViewer2> p_w_picpathViewer =

? 35:????????vtkSmartPointer<vtkImageViewer2>::New();

? 36:????p_w_picpathViewer->SetInputConnection(changer->GetOutputPort());

? 37:????vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor=

? 38:????????vtkSmartPointer<vtkRenderWindowInteractor>::New();

? 39:????p_w_picpathViewer->SetupInteractor(renderWindowInteractor);

? 40:????p_w_picpathViewer->Render();

? 41:????p_w_picpathViewer->GetRenderer()->ResetCamera();

? 42:????p_w_picpathViewer->Render();

? 43:??

? 44:????renderWindowInteractor->Start();

?

上例中首先讀入圖像,由vtkImageData提供函數(shù)接口獲取圖像的維數(shù),原點(diǎn)和像素間隔。然后定義vtkImageChangeInformation指針,并設(shè)置輸出圖像原點(diǎn)為(100, 100, 0),輸出圖像像素間隔為(5, 5, 1),然后調(diào)用CenterImage()函數(shù)將圖像的原點(diǎn)置于圖像的中心。顯示結(jié)果如圖5.9:

?

圖5.9 vtkImageChangeInformation修改圖像信息

?

從上面結(jié)果中可以看出,操作后的結(jié)果使得圖像的原點(diǎn)位于(-1277.5, -1275.5, 0),SetOutputOrigin(100, 100, 0)并沒有起作用。原因在哪里呢?如果看下CenterImage()函數(shù)的注釋,可以發(fā)現(xiàn)該函數(shù)的作用是將(0, 0, 0)點(diǎn)置于圖像的中心。當(dāng)CenterImage該函數(shù)執(zhí)行時會重寫SetOutputOrigin(),所以SetOutputOrigin函數(shù)不會產(chǎn)生任何作用。那(-1277.5, -1275.5, 0)又是如何計算出來的呢?如圖5.10,根據(jù)圖像的維數(shù)和像素間隔計算得到新的圖像的寬度和高度為(512-1)*5 ,初始圖像的原點(diǎn)位于(0, 0,0),現(xiàn)在將圖像的中心平移至原點(diǎn),平移量為(-(512-1)*5/2,(512-1)*5/2, 0) = (-1277.5, -1275.5,0)。

?

圖5.10 CenterImage函數(shù)示意圖

?

5.4.2圖像像素值訪問和修改

圖像像素值的訪問與修改是最常用的一個操作。VTK中提供了兩種訪問圖像像素值的方法。第一種是直接訪問vtkImageData的數(shù)據(jù)數(shù)組。這種方式最直接。在第一節(jié)上新建圖像賦值也是采用的這種方法。vtkImageData中提供了GetScalarPointer()函數(shù)獲取數(shù)據(jù)數(shù)組指針,該函數(shù)有三種形式:

virtualvoid *GetScalarPointer(int coordinates[3]);

virtualvoid *GetScalarPointer(int x, int y, int z);

virtualvoid *GetScalarPointer();

前兩種形式根據(jù)給定的像素索引得到指定的像素值,注意返回的是第(x,y,z)個像素值的地址。而第三種方式是返回圖像數(shù)據(jù)數(shù)組的頭指針,然后根據(jù)頭指針可以依次訪問索引像素。在第一節(jié)中采用的就是這樣方式。下面看一個遍歷圖像像素的例子,結(jié)果如圖5.12。

?

1:? vtkSmartPointer<vtkBMPReader> reader =

?? 2:????vtkSmartPointer<vtkBMPReader>::New();

?? 3:?reader->SetFileName ( "…\\lena.bmp" );

?? 4:?reader->Update();

?? 5:??

?? 6:?int dims[3];

?? 7:?reader->GetOutput()->GetDimensions(dims);

?? 8:??

?? 9:?for(int k=0; k<dims[2]; k++)

? 10:? {

? 11:????for(int j=0; j<dims[1]; j++)

? 12:????{

? 13:???????for(int i=0; i<dims[0]; i++)

? 14:???????{

? 15:??????????if(i<100 && j<100)

? 16:??????????{

? 17:????????????? unsigned char * pixel =

? 18:???????????????? (unsigned char *) (reader->GetOutput()->GetScalarPointer(i, j, k) );

? 19:????????????? *pixel = 0;

? 20:????????????? *(pixel+1) = 0;

? 21:????????????? *(pixel+2) = 0;

? 22:??????????}

? 23:???????}

? 24:????}

? 25:? }

? 26:??

? 27:?vtkSmartPointer<vtkImageViewer2> p_w_picpathViewer =

? 28:????vtkSmartPointer<vtkImageViewer2>::New();

? 29:?p_w_picpathViewer->SetInputConnection(reader->GetOutputPort());

? 30:?vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor=

? 31:????vtkSmartPointer<vtkRenderWindowInteractor>::New();

? 32:?p_w_picpathViewer->SetupInteractor(renderWindowInteractor);

? 33:?p_w_picpathViewer->Render();

? 34:?p_w_picpathViewer->GetRenderer()->ResetCamera();

? 35:?p_w_picpathViewer->Render();

? 36:??

? 37:?renderWindowInteractor->Start();

?

上面代碼實(shí)現(xiàn)了將圖像的100*100大小的區(qū)域設(shè)置為黑色。首先定義一個reader讀取一副bmp圖像,通過vtkImageData函數(shù)GetDimensions()獲取圖像的大小。建立三次循環(huán),通過GetScalarPointer(i, j,k)函數(shù)獲取訪問圖像像素值。需要注意的是,GetScalarPointer()函數(shù)返回的是void*類型,因此需要根據(jù)圖像的實(shí)際類型進(jìn)行強(qiáng)制轉(zhuǎn)換。如上面代碼中將像素值數(shù)組的頭指針類型轉(zhuǎn)換為unsigned char *。如果對于數(shù)據(jù)類型不確定的話,還可以先通過vtkImageCast將圖像數(shù)據(jù)類型強(qiáng)制轉(zhuǎn)換為特定的數(shù)據(jù)類型,再進(jìn)行遍歷。

另外還有一個需要注意地方,彩色以及向量圖像采用的是類似圖5.11這種像素存儲格式。

?

圖5.11 VTK彩色以及向量圖像像素存儲格式

?

因此在修改RGB圖像以及向量圖像像素時,需要根據(jù)像素的元組的組分?jǐn)?shù)目來訪問。上例中,需要修改每個像素的RGB值時,首先獲得第(i, j, k)個像素的地址也就是R值的地址,然后將地址加1來訪問后續(xù)G值以及B值。如果對于像素的元組組分不確定時,可以通過函數(shù)GetNumberOfScalarComponents()來獲取。如下所示:

int?nbOfComp = reader->GetOutput()->GetNumberOfScalarComponents();

?

?

圖5.12 修改圖像像素值

?

另外VTK中提供了vtkImageIterator類來利用迭代器方法訪問圖像像素。該類是一個模板類,使用時,需要提供迭代的圖像像素類型以及迭代的區(qū)域大小。下面給出示例代碼。

?? 1:????? vtkSmartPointer<vtkBMPReader>reader =

?? 2:?????????vtkSmartPointer<vtkBMPReader>::New();

?? 3:?????reader->SetFileName ( "..\\lena.bmp" );

?? 4:?????reader->Update();

?? 5:??

?? 6:?????int subRegion[6] = {0,300, 0, 300, 0, 0};

?? 7:?????vtkImageIterator<unsigned char> it(reader->GetOutput(), subRegion);

?? 8:??

?? 9:?????while(!it.IsAtEnd())

? 10:?????{

? 11:?????????unsigned char *inSI = it.BeginSpan();

? 12:?????????unsigned char *inSIEnd = it.EndSpan();

? 13:??

? 14:?????????while(inSI != inSIEnd)

? 15:?????????{

? 16:????????????? *inSI = 255-*inSI;

? 17:????????????? ++inSI;

? 18:?????????}

? 19:?????????it.NextSpan();

? 20:?????}

? 21:??

? 22:?????vtkSmartPointer<vtkImageViewer2> p_w_picpathViewer =

? 23:?????????vtkSmartPointer<vtkImageViewer2>::New();

? 24:?????p_w_picpathViewer->SetInputConnection(reader->GetOutputPort());

? 25:?????vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor=

? 26:?????????vtkSmartPointer<vtkRenderWindowInteractor>::New();

? 27:?????p_w_picpathViewer->SetupInteractor(renderWindowInteractor);

? 28:?????p_w_picpathViewer->Render();

? 29:?????p_w_picpathViewer->GetRenderer()->ResetCamera();

? 30:?????p_w_picpathViewer->Render();

? 31:??

? 32:?????renderWindowInteractor->Start();

?

下面分析一下上面的代碼。如果對于ITK圖像區(qū)域迭代器熟悉的話,可能會對上面代碼存在疑問。上面代碼中首先讀取了一副bmp圖像,然后定義了一個子區(qū)域。注意在定義子區(qū)域的時候,不要超過圖像的大小范圍。subRegion的六個值分別表示區(qū)域中x的最小最大值,y的最小最大值,z的最小最大值。由于處理的圖像為二維圖像,因此z的取值范圍為[0,0]。然后根據(jù)圖像類型unsigned char定義實(shí)例化一個圖像迭代器it,定義it時有兩個參數(shù):一個是要訪問的圖像,另外一個是訪問的圖像區(qū)域。設(shè)置完畢后,迭代器開始工作。注意,上面代碼中有兩個while循環(huán)。

首先看第一個while循環(huán),這里判斷迭代器是否結(jié)束。進(jìn)入循環(huán)后,對于每個迭代器it,又存在第二個循環(huán)。這個循環(huán)判斷的是當(dāng)前像素的組分是否迭代完畢。由于vtk中所有類型的圖像格式都是vtkImageData,因此每個像素可能是標(biāo)量,也可能是向量。因此,每當(dāng)訪問到一個像素時,需要迭代當(dāng)前像素的組分。組分迭代時,inSI = it.BeginSpan()獲取第一個組分,inSIEnd = it.EndSpan()表示組分迭代完畢,通過++inSI不斷迭代組分,并對像素的組分值進(jìn)行處理,當(dāng)inSI與inSIEnd相等時組分迭代完畢。然后繼續(xù)迭代像素it,直至迭代完畢所有像素。上面代碼中將指定區(qū)域的像素值取反,得到如圖5.13所示結(jié)果。

?

圖5.13 利用VTK迭代器修改圖像像素值

?

?

==========歡迎轉(zhuǎn)載,轉(zhuǎn)載時請保留該聲明信息==========

版權(quán)歸@東靈工作室所有,更多信息請訪問東靈工作室


教程系列導(dǎo)航:http://blog.csdn.net/www_doling_net/article/details/8763686

================================================

?

本文來源:http://blog.csdn.net/www_doling_net/article/details/8547317

轉(zhuǎn)載于:https://blog.51cto.com/2845385/1175731

總結(jié)

以上是生活随笔為你收集整理的05-VTK在图像处理中的应用(2)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。