1. 程式人生 > >5.3.7 影象重取樣

5.3.7 影象重取樣

影象重取樣是指對取樣後形成的由離散資料組成的數字影象按所需的像元位置或像元問距重新取樣,以構成幾何變換後的新影象。重取樣過程本質上是影象恢復過程,它用輸入的離散數字影象重建代表原始影象二維連續函式,再按新的像元間距和像元位置進行取樣。其數學過程是根據重建的連續函式(曲面),用周圍若干像元點的值估計或內插出新取樣點的值。影象重取樣在影象處理中應用非常廣泛,如SIFT特徵提取

影象重取樣後圖像的維數會發生改變。當重取樣影象小於原影象維數時,稱為降取樣;當重取樣影象維數大於原影象時,稱為升取樣。VTK中可以方便的對影象進行重取樣。vtkImageShrink3D類實現影象降取樣。降取樣需要設定每個方向的取樣率,降取樣率越大,影象越模糊。升取樣的原理與降取樣原理一致,只是增加取樣點數來增加影象的維數。

VTK中vtkImageMagnify來實現影象的升取樣

#include <vtkSmartPointer.h>
#include <vtkBMPReader.h>
#include <vtkImageData.h>
#include <vtkImageShrink3D.h> //降取樣標頭檔案
#include <vtkImageMagnify.h>  //升取樣標頭檔案
#include <vtkImageActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h> //互動樣式


int main()
{
	vtkSmartPointer<vtkBMPReader> reader = vtkSmartPointer<vtkBMPReader>::New();
	reader->SetFileName("data\\lena.bmp");
	reader->Update();

	vtkSmartPointer<vtkImageShrink3D> shrinkFilter = vtkSmartPointer<vtkImageShrink3D>::New();
	shrinkFilter->SetInputConnection(reader->GetOutputPort());//建立管道
	shrinkFilter->SetShrinkFactors(16, 16, 1);//設定降取樣率
	shrinkFilter->Update();

	vtkSmartPointer<vtkImageMagnify> magnifyFilter = vtkSmartPointer<vtkImageMagnify>::New();
	magnifyFilter->SetInputConnection(reader->GetOutputPort());
	magnifyFilter->SetMagnificationFactors(10, 10, 1);
	magnifyFilter->Update();

	int originalDims[3];
	reader->GetOutput()->GetDimensions(originalDims);
	double originalSpacing[3];
	reader->GetOutput()->GetSpacing(originalSpacing);
	int shrinkDims[3];
	shrinkFilter->GetOutput()->GetDimensions(shrinkDims);
	double shrinkSpacing[3];
	shrinkFilter->GetOutput()->GetSpacing(shrinkSpacing);
	int magnifyDims[3];
	magnifyFilter->GetOutput()->GetDimensions(magnifyDims);
	double magnifuSpacing[3];
	magnifyFilter->GetOutput()->GetSpacing(magnifuSpacing);
	std::cout << "原始維度:      " << originalDims[0] << "*" << originalDims[1] << "*" << originalDims[2] << std::endl;
	std::cout << "原始畫素間距:  " << originalSpacing[0] << " " << originalSpacing[1] << " " << originalSpacing[2] << std::endl;
	std::cout << "降取樣維度:    " << shrinkDims[0] << "*" << shrinkDims[1] << "*" << shrinkDims[2] << std::endl;
	std::cout << "降取樣畫素間距:" << shrinkSpacing[0] << " " << shrinkSpacing[1] << " " << shrinkSpacing[2] << std::endl;
	std::cout << "升取樣維度:    " << magnifyDims[0] << "*" << magnifyDims[1] << "*" << magnifyDims[2] << std::endl;
	std::cout << "升取樣畫素間距:" << magnifuSpacing[0] << " " << magnifuSpacing[1] << " " << magnifuSpacing[2] << std::endl;

	vtkSmartPointer<vtkImageActor> origActor = vtkSmartPointer<vtkImageActor>::New();
	origActor->SetInputData(reader->GetOutput());
	vtkSmartPointer<vtkImageActor> shrinkActor = vtkSmartPointer<vtkImageActor>::New();
	shrinkActor->SetInputData(shrinkFilter->GetOutput());
	vtkSmartPointer<vtkImageActor> magnifyActor = vtkSmartPointer<vtkImageActor>::New();
	magnifyActor->SetInputData(magnifyFilter->GetOutput());
	///////////////////////////////////////////////////////
	double origView[4] = { 0, 0, 0.3, 1.0 };
	double shrinkView[4] = { 0.3, 0, 0.6, 1.0 };
	double magnifyView[4] = { 0.6, 0, 1, 1 };
	vtkSmartPointer<vtkRenderer> origRender = vtkSmartPointer<vtkRenderer>::New();
	origRender->SetViewport(origView);//檢視
	origRender->AddActor(origActor);//物件
	origRender->ResetCamera();//相機
	origRender->SetBackground(0, 0, 0);//背景
	vtkSmartPointer<vtkRenderer> shrinkRender =	vtkSmartPointer<vtkRenderer>::New();
	shrinkRender->SetViewport(shrinkView);
	shrinkRender->AddActor(shrinkActor);
	shrinkRender->ResetCamera();
	shrinkRender->SetBackground(0, 0, 0);
	vtkSmartPointer<vtkRenderer> magnifyRender = vtkSmartPointer<vtkRenderer>::New();
	magnifyRender->SetViewport(magnifyView);
	magnifyRender->AddActor(magnifyActor);
	magnifyRender->ResetCamera();
	magnifyRender->SetBackground(0, 0, 0);
	/////////////////////////////////////////////////
	vtkSmartPointer<vtkRenderWindow> rw = vtkSmartPointer<vtkRenderWindow>::New();
	rw->AddRenderer(origRender);
	rw->AddRenderer(shrinkRender);
	rw->AddRenderer(magnifyRender);
	rw->SetSize(720, 240);
	rw->SetWindowName("Image-Shrink-Magnify");
	rw->Render();
	////////////////////////////////////////////////
	vtkSmartPointer<vtkRenderWindowInteractor> rwi = vtkSmartPointer<vtkRenderWindowInteractor>::New();
	vtkSmartPointer<vtkInteractorStyleImage> style = vtkSmartPointer<vtkInteractorStyleImage>::New();
	rwi->SetInteractorStyle(style);
	rwi->SetRenderWindow(rw);
	rwi->Initialize();
	rwi->Start();

	return 0;
}

執行結果:



vtkImageShrink3D通過SetShrinkFactors()設定X、Y和Z方向的取樣率,引數為三個int型別資料。vtkImageMagnify通過SetMagnificationFactors設定相應的放大采樣率。從圖中可以看成,重取樣影象已經變得十分模糊了。而升取樣影象則變化不大。程式中輸出了原圖和重取樣影象的維數和畫素間隔,從輸出來看,原影象的維數為512x512,縮小16倍後,影象維數變為32x32。需要注意的是,原圖的畫素間隔為(1,1,1),而重取樣後像素間隔變為(16, 16, 1),這是因為取樣是在世界座標系下進行的,當取樣影象的維數減小時,取樣的畫素間隔也相應的變大,這樣保持影象的區域不會發生改變。同樣的道理,當升取樣後圖像的維數變為原來的10倍,而畫素間隔變為原來的十分之一。


注:此文知識學習筆記,僅記錄完整程式和實現結果,具體原理參見:

https://blog.csdn.net/www_doling_net/article/details/8541534

https://blog.csdn.net/shenziheng1/article/category/6114053/4

參考資料:

1.《The Visualization Toolkit – AnObject-Oriented Approach To 3D Graphics (4th Edition)》
2. 張曉東, 羅火靈. VTK圖形影象開發進階[M]. 機械工業出版社, 2015.

所用軟體:vtk7.0+visual studio 2013