VTK修炼之道19:图像基本操作_图像像素值的访问与修改
1.直接訪問圖像像素(索引法)
#include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL);#include <vtkSmartPointer.h> #include <vtkImageData.h> #include <vtkBMPReader.h> #include <vtkImageViewer2.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h>int main() {vtkSmartPointer<vtkBMPReader> reader =vtkSmartPointer<vtkBMPReader>::New();reader->SetFileName("lena.bmp");reader->Update();int dims[3];reader->GetOutput()->GetDimensions(dims);int nbofComp;nbofComp = reader->GetOutput()->GetNumberOfScalarComponents();for (int k = 0; k < dims[2]; k++){for (int j = 0; j < dims[1]; j++){for (int i = 0; i < dims[0]; i++){if (i < 384 && i > 128 && j > 128 && j < 384){unsigned char *pixel = (unsigned char *)(reader->GetOutput()->GetScalarPointer(i, j, k)); *pixel = 255 - *pixel;*(pixel + 1) = 255 - *(pixel + 1);*(pixel + 2) = 255 - *(pixel + 2);}}}}vtkSmartPointer<vtkImageViewer2> imgViewer =vtkSmartPointer<vtkImageViewer2>::New();imgViewer->SetInputData(reader->GetOutput());vtkSmartPointer<vtkRenderWindowInteractor> rwi =vtkSmartPointer<vtkRenderWindowInteractor>::New();imgViewer->SetupInteractor(rwi);imgViewer->Render();imgViewer->GetRenderer()->ResetCamera();imgViewer->Render();imgViewer->GetRenderer()->SetBackground(1.0, 1.0, 1.0);imgViewer->SetSize(640, 480);imgViewer->GetRenderWindow()->SetWindowName("VisitImagePixelDirectly");rwi->Start();return 0; }輸出結果:
上述案例實現了將圖像的100*100大小的區域設置為反色。首先定義一個reader讀取一副bmp圖像,通過vtkImageData函數GetDimensions()獲取圖像的大小。建立三次循環,通過GetScalarPointer(i, j,k)函數獲取訪問圖像像素值。需要注意的是,GetScalarPointer()函數返回的是void*類型,因此需要根據圖像的實際類型進行強制轉換。如上面代碼中將像素值數組的頭指針類型轉換為unsigned char *。如果對于數據類型不確定的話,還可以先通過vtkImageCast將圖像數據類型強制轉換為特定的數據類型,再進行遍歷。
在這里,我們需要注意的一點是VTK中彩色圖以及矢量圖的存儲方式,具體如下:
因此在修改RGB圖像以及向量圖像像素時,需要根據像素的元組的組分數目來訪問。上例中,需要修改每個像素的RGB值時,首先獲得第(i, j, k)個像素的地址也就是R值的地址,然后將地址加1來訪問后續G值以及B值。如果對于像素的元組組分不確定時,可以通過函數GetNumberOfScalarComponents()來獲取。如下所示:
int nbOfComp = reader->GetOutput()->GetNumberOfScalarComponents();
2.迭代器方法訪問圖像像素
另外VTK中提供了vtkImageIterator類來利用迭代器方法訪問圖像像素。該類是一個模板類,使用時,需要提供迭代的圖像像素類型以及迭代的區域大小。。
#include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL);#include <vtkSmartPointer.h> #include <vtkBMPReader.h> #include <vtkImageData.h> #include <vtkImageIterator.h> #include <vtkImageViewer2.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h>int main() {vtkSmartPointer<vtkBMPReader> reader =vtkSmartPointer<vtkBMPReader>::New();reader->SetFileName("lena.bmp");reader->Update();int subRegion[6] = { 64, 448, 64, 448, 0, 0 };vtkImageIterator<unsigned char> iter(reader->GetOutput(),subRegion);while (!iter.IsAtEnd()){unsigned char *inSI = iter.BeginSpan();unsigned char *inSIEnd = iter.EndSpan();while ( inSI != inSIEnd ){*inSI = 255 - *inSI;++inSI;}iter.NextSpan();}vtkSmartPointer<vtkImageViewer2> imgViewer =vtkSmartPointer<vtkImageViewer2>::New();imgViewer->SetInputConnection(reader->GetOutputPort());vtkSmartPointer<vtkRenderWindowInteractor> rwi =vtkSmartPointer<vtkRenderWindowInteractor>::New();imgViewer->SetupInteractor(rwi);imgViewer->Render();imgViewer->GetRenderer()->ResetCamera();imgViewer->Render();imgViewer->GetRenderer()->SetBackground(1.0, 1.0, 1.0);imgViewer->SetSize(640, 480);imgViewer->GetRenderWindow()->SetWindowName("VisitImagePixelIteratively");rwi->Start();return 0; }輸出結果: 如果對于ITK圖像區域迭代器熟悉的話,可能會對上面代碼存在疑問。上面代碼中首先讀取了一副bmp圖像,然后定義了一個子區域。注意在定義子區域的時候,不要超過圖像的大小范圍。subRegion的六個值分別表示區域中x的最小最大值,y的最小最大值,z的最小最大值。由于處理的圖像為二維圖像,因此z的取值范圍為[0,0]。然后根據圖像類型unsigned char定義實例化一個圖像迭代器it,定義it時有兩個參數:一個是要訪問的圖像,另外一個是訪問的圖像區域。設置完畢后,迭代器開始工作。注意,上面代碼中有兩個while循環。
首先看第一個while循環,這里判斷迭代器是否結束。進入循環后,對于每個迭代器it,又存在第二個循環。這個循環判斷的是當前像素的組分是否迭代完畢。由于vtk中所有類型的圖像格式都是vtkImageData,因此每個像素可能是標量,也可能是向量。因此,每當訪問到一個像素時,需要迭代當前像素的組分。組分迭代時,inSI = it.BeginSpan()獲取第一個組分,inSIEnd = it.EndSpan()表示組分迭代完畢,通過++inSI不斷迭代組分,并對像素的組分值進行處理,當inSI與inSIEnd相等時組分迭代完畢。然后繼續迭代像素it,直至迭代完畢所有像素。
3.參考資料
1.《C++ primer》
2.《The VTK User’s Guide – 11thEdition》
3.《The Visualization Toolkit – AnObject-Oriented Approach To 3D Graphics (4th Edition)》
4. ?張曉東, 羅火靈. VTK圖形圖像開發進階[M]. 機械工業出版社, 2015.
總結
以上是生活随笔為你收集整理的VTK修炼之道19:图像基本操作_图像像素值的访问与修改的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在OpenEIM中每运行一个程序
- 下一篇: VTK修炼之道20:图像基本操作_图像类