VTK修炼之道28:图像统计_灰度直方图计算
生活随笔
收集整理的這篇文章主要介紹了
VTK修炼之道28:图像统计_灰度直方图计算
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1.灰度圖像直方圖
直方圖統計是圖像處理中的一個非常重要的操作。VTK中實現直方圖統計功能的filter是vtkImageAccumulate。其將每個組分的數值范圍劃分為離散的間隔,然后統計每個灰度間隔上的像素數目。vtkImageAccumulate輸入和輸出都是vtkImageData類型,因此直方圖也可以看做是一幅圖像;對于輸入圖像的像素數據類型可以是任意的,但是最大支持3個組分像素類型,而輸出圖像的像素數據類型為int型。一個灰度圖像的直方圖為一個一維圖像。 下面代碼提供了如何計算灰度圖像直方圖的方法: #include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL);#include <vtkSmartPointer.h> #include <vtkJPEGReader.h> #include <vtkImageAccumulate.h> #include <vtkImageData.h> #include <vtkIntArray.h> #include <vtkDataObject.h> // #include <vtkFieldData.h> //一起用 #include <vtkBarChartActor.h> #include <vtkProperty2D.h> #include <vtkTextProperty.h> #include <vtkLegendBoxActor.h> #include <vtkImageActor.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h>int main() {vtkSmartPointer<vtkJPEGReader> reader =vtkSmartPointer<vtkJPEGReader>::New();reader->SetFileName("lena-gray.jpg");reader->Update();int bins = 16;int comps = 1;vtkSmartPointer<vtkImageAccumulate> histogram =vtkSmartPointer<vtkImageAccumulate>::New();histogram->SetInputData(reader->GetOutput());histogram->SetComponentExtent(0, bins - 1, 0, 0, 0, 0);histogram->SetComponentOrigin(0, 0, 0);histogram->SetComponentSpacing(256.0 / bins, 0, 0);histogram->Update();int* output = static_cast<int*>(histogram->GetOutput()->GetScalarPointer());vtkSmartPointer<vtkIntArray> frequencies =vtkSmartPointer<vtkIntArray>::New();frequencies->SetNumberOfComponents(1);for (int j = 0; j < bins; ++j){for (int i = 0; i<comps; i++){frequencies->InsertNextTuple1(*output++);}}vtkSmartPointer<vtkDataObject> dataObject =vtkSmartPointer<vtkDataObject>::New();dataObject->GetFieldData()->AddArray(frequencies);vtkSmartPointer<vtkBarChartActor> barChart =vtkSmartPointer<vtkBarChartActor>::New();barChart->SetInput(dataObject);barChart->SetTitle("Histogram");barChart->GetPositionCoordinate()->SetValue(0.05, 0.05, 0.0);barChart->GetPosition2Coordinate()->SetValue(0.95, 0.95, 0.0);barChart->GetProperty()->SetColor(0, 0, 0);barChart->GetTitleTextProperty()->SetColor(0, 0, 0);barChart->GetLabelTextProperty()->SetColor(0, 0, 0);barChart->GetLegendActor()->SetNumberOfEntries(dataObject->GetFieldData()->GetArray(0)->GetNumberOfTuples());barChart->LegendVisibilityOff();barChart->LabelVisibilityOff();double colors[3][3] = {{ 1, 0, 0 },{ 0, 1, 0 },{ 0, 0, 1 } };int count = 0;for (int i = 0; i < bins; ++i){for (int j = 0; j < comps; ++j){barChart->SetBarColor(count++, colors[j]); //單通道 紅色}}vtkSmartPointer<vtkImageActor> imgActor =vtkSmartPointer<vtkImageActor>::New();imgActor->SetInputData(reader->GetOutput());double imgView[4] = { 0.0, 0.0, 0.5, 1.0 };double barView[4] = { 0.5, 0.0, 1.0, 1.0 };vtkSmartPointer<vtkRenderer> barRender =vtkSmartPointer<vtkRenderer>::New();barRender->SetViewport(barView);barRender->AddActor(barChart);barRender->SetBackground(1.0, 1.0, 1.0);vtkSmartPointer<vtkRenderer> imgRender =vtkSmartPointer<vtkRenderer>::New();imgRender->SetViewport(imgView);imgRender->AddActor(imgActor);imgRender->SetBackground(1.0, 1.0, 1.0);vtkSmartPointer<vtkRenderWindow> renderWindow =vtkSmartPointer<vtkRenderWindow>::New();renderWindow->AddRenderer(barRender);renderWindow->AddRenderer(imgRender);renderWindow->SetSize(640, 320);renderWindow->Render();renderWindow->SetWindowName("Gray-Image Histogram");vtkSmartPointer<vtkRenderWindowInteractor> interactor =vtkSmartPointer<vtkRenderWindowInteractor>::New();interactor->SetRenderWindow(renderWindow);interactor->Initialize();interactor->Start();return 0; }下面來分析一下代碼。 首先是讀入一副灰度圖像,一般的灰度圖像的灰度范圍為0-255。定義了一個變量bins = 16,表示要圖像灰度范圍上的間隔數目,也可以理解為直方圖一維數組的維數。然后定義vtkImageAccumulate對象,并設置輸入數據為我們讀入的圖像數據,接著調用了三個函數:
SetComponentExtent(0,bins-1, 0, 0, 0, 0),該函數設置要計算每個組分的直方圖的最小和最大值。vtkImageAccumulate最大支持像素值為三個組分(如RGB圖像)的直方圖,支持共有六個參數。分別表示每個組分的直方圖最小和最大值。該例中由于計算的是灰度圖像直方圖,只有一個組分,因此第二個和第三個組分都設置為0;而第一組分直方圖維數為bins = 16,那么其最小和最大范圍為0和bins-1。
SetComponentOrigin(0,0,0),該函數設置的是統計每個組分直方圖時的起始灰度值,這里設置為0,表示灰度從0開始統計直方圖。同樣,vtkImageAccumulate最大支持像素值為三個組分,這里也要設置三個參數。如果圖像的灰度范圍為[1000, 2000],那么計算直方圖時,其起始灰度應該設置為1000。
SetComponentSpacing(16,0, 0),設置直方圖每個間隔代表的灰度范圍,例如當一個圖像灰度范圍為[1000, 2000],統計直方圖的間隔數bins為100時,那么對應的space應該設置為SetComponentSpacing(100, 0, 0)。
參數設置完畢后執行Update()即可計算直方圖。前面已經提到過,vtkImageAccumulate的輸出結果也是一個vtkImageData類型,這樣就可以方便的訪問圖像的每個數據。圖像像素訪問前面已經介紹過,這里就不在重述。需要注意的是輸出直方圖圖像的數據類型為int。
這里再順便簡單的介紹一下直方圖的顯示。 雖然vtkImageAccumulate的輸出類型為vtkImageData但是并不能直接按照圖像的方式進行顯示。VTK中定義了vtkBarChartActor用來顯示條形圖,因此可以利用其來顯示直方圖。但是該類接收的數據類型為vtkDataObject類型,因此需要先將直方圖數據進行轉換。首先將直方圖數組存儲到vtkIntArray數組frequencies中,通過函數vtkDataObject函數GetFieldData()->AddArray(frequencies)將其添加到vtkDataObject對象中。vtkBarChartActor對象接收vtkDataObject對象作為輸入,另外還需要設置圖表的名字,顏色等,需要注意兩個函數:
barChart->GetPositionCoordinate()->SetValue(0.05,0.05,0.0);
barChart->GetPosition2Coordinate()->SetValue(0.95,0.95,0.0);
這里設置的是窗口中顯示圖表的所在矩形的左下角點和右上角點坐標,VTK的坐標系原點位于左下角點,設置時需要格外注意。設置完畢后,即可定義相應的vtkRenderer,vtkRenderWindow和vtkRenderWindowInteractor對象顯示圖像直方圖。 本例的顯示效果如下:
2.參看資料
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修炼之道28:图像统计_灰度直方图计算的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 和大家探讨一下“虚拟光驱”原理
- 下一篇: VTK修炼之道29:图像统计_彩色直方图