第5章 VTK画像処理
学習チュートリアル: 「高度な VTK グラフィックスと画像開発」 Zhang Xiaodong、Luo Huoling
特別協力: Dongling Studio
5.2 VTK画像表示
5.2.1 vtkImageViewer2——二次元画像の表示
特に3次元画像のスライス表示に適しています。
例 - 3D 医療画像の特定のスライスを *.mhd 形式で表示する
ソース コード:
#include <vtkSmartPointer.h>
#include <vtkImageViewer2.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkMetaImageReader.h>
//测试图像:../data/brain.mhd
int main()
{
//使用vtkMetaImageReader读入一个*.mhd格式的图像
vtkSmartPointer<vtkMetaImageReader>reader = vtkSmartPointer<vtkMetaImageReader>::New();
reader->SetFileName("../data/brain.mhd");
reader->Update();
vtkSmartPointer<vtkImageViewer2>imageViewer = vtkSmartPointer<vtkImageViewer2>::New();
imageViewer->SetInputConnection(reader->GetOutputPort());
//显示切片
vtkSmartPointer<vtkRenderWindowInteractor>renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
imageViewer->SetupInteractor(renderWindowInteractor);
imageViewer->SetColorLevel(500);//窗位
imageViewer->SetColorWindow(2000);//窗宽
imageViewer->SetSlice(40);//切片索引
imageViewer->SetSliceOrientationToXY();//切片方向
imageViewer->Render();
imageViewer->GetRenderer()->SetBackground(1.0, 1.0, 1.0);
imageViewer->SetSize(640, 480);
imageViewer->GetRenderWindow()->SetWindowName("DisplayImageExample");
renderWindowInteractor->Start();
return 0;
}
操作結果:
5.2.2 vtkImageActor — 3D 画像レンダリング
テクスチャ マッピングは、表示のために画像をポリゴンにマッピングします。
vtkBMPReader を使用して画像を読み込んだ後、vtkImageActor、vtkRender、vtkRenderWindow、vtkRenderWindowInteractor を順に作成します。また、vtkInteractorStyleImage オブジェクトを定義し、それをレンダリング パイプラインにアセンブルする必要があります。
ソースコード:
#include <vtkSmartPointer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkRenderer.h>
#include <vtkBMPReader.h>
#include <vtkImageActor.h>
//测试图像:../data/lena.bmp
int main()
{
//读取图片
vtkSmartPointer<vtkBMPReader>reader = vtkSmartPointer<vtkBMPReader>::New();
reader->SetFileName("../data/lena.bmp");
reader->Update();
//渲染管线
vtkSmartPointer<vtkImageActor>imgActor = vtkSmartPointer<vtkImageActor>::New();
imgActor->SetInputData(reader->GetOutput());
vtkSmartPointer<vtkRenderer>renderer = vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(imgActor);
renderer->SetBackground(1.0, 1.0, 1.0);
vtkSmartPointer<vtkRenderWindow>renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
renderWindow->SetSize(640, 480);
renderWindow->Render();
renderWindow->SetWindowName("DisplayImageExample2");
vtkSmartPointer<vtkRenderWindowInteractor>renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
vtkSmartPointer<vtkInteractorStyleImage> style = vtkSmartPointer<vtkInteractorStyleImage>::New();
renderWindowInteractor->SetInteractorStyle(style);
renderWindowInteractor->SetRenderWindow(renderWindow);
renderWindowInteractor->Initialize();
renderWindowInteractor->Start();
return 0;
}
操作結果:
注: vtkImageActor が受け取る画像データ vtkImageData のピクセル タイプは unsigned char である必要があります。タイプが要件を満たしていない場合は、画像を表示する前に画像データ タイプを unsigned char に変換する必要があります。
コンパイル中にエラーが発生しました“vktSmartPointer”: 未声明的标识符
。解決策はこうなりました!!VS でエラー行を削除し、メモ帳でまったく同じ行を書き直して、上に貼り付けると問題ありません。すばらしい!
5.2.3 vtkImageBlend—画像融合
画像の融合: 画像の不透明度を利用して画像を合成します。画像の融合を実現するには、クラス vtkImageBlend を使用します。vtkImageBlend は複数の画像入力を受け入れることができ、その出力画像は融合された画像です。
2 つの融合モード: 標準モード (デフォルト)、ブレンド モード
(1) 標準モード
(2) ブレンド モード
出力結果は不透明度を使用して正規化されます。
例: グレースケール画像を読み込み、バイナリ画像を生成し、画像を融合します (グレースケール画像とバイナリ画像の融合)。最後に、ウィンドウ内に 3 つの画像が表示されます。
ソースコード:
#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkImageCanvasSource2D.h>
#include <vtkImageBlend.h>
#include <vtkJPEGReader.h>
#include <vtkImageActor.h>
#include <vtkImageCast.h>
//测试图像:../data/lena-gray.jpg
int main()
{
//读入灰度图像
vtkSmartPointer<vtkJPEGReader>reader = vtkSmartPointer<vtkJPEGReader>::New();
reader->SetFileName("../data/lena-gray.jpg");
reader->Update();
//生成二值图像
vtkSmartPointer<vtkImageCanvasSource2D>imageSource = vtkSmartPointer<vtkImageCanvasSource2D>::New();
imageSource->SetNumberOfScalarComponents(1);
imageSource->SetScalarTypeToUnsignedChar();
imageSource->SetExtent(0, 512, 0, 512, 0, 0);
imageSource->SetDrawColor(0.0);
imageSource->FillBox(0, 512, 0, 512);
imageSource->SetDrawColor(255.0);
imageSource->FillBox(100,400,100,400);
imageSource->Update();
//融合图像:两个输入(0:灰度图像;1:二值图像)
vtkSmartPointer<vtkImageBlend>imageBlend = vtkSmartPointer<vtkImageBlend>::New();
//imageBlend->SetInputData(0, (vtkDataObject*)reader->GetOutput());
//imageBlend->SetInputData(1, (vtkDataObject*)imageSource->GetOutput()); // 这样写不能显示融合图像
imageBlend->AddInputData(reader->GetOutput());
imageBlend->AddInputData(imageSource->GetOutput()); //修改为Add,然后取消编号就ok
imageBlend->SetOpacity(0, 0.4);
imageBlend->SetOpacity(1, 0.6); //用于设置对应id号的图像不透明度的大小
imageBlend->Update();
//显示三组图像
//(1)创建actors
vtkSmartPointer<vtkImageActor>originalActor1 = vtkSmartPointer<vtkImageActor>::New();
originalActor1->SetInputData(reader->GetOutput());
vtkSmartPointer<vtkImageActor>originalActor2 = vtkSmartPointer<vtkImageActor>::New();
originalActor2->SetInputData(imageSource->GetOutput());
vtkSmartPointer<vtkImageActor>blendActor = vtkSmartPointer<vtkImageActor>::New();
blendActor->SetInputData(imageBlend->GetOutput());
//(2)定义viewport范围 (xmin,ymin,xmax,ymax)
double leftViewport[4] = {
0.0,0.0,0.33,1.0 };
double midViewport[4] = {
0.33,0.0,0.66,1.0 };
double rightViewport[4] = {
0.66,0.0,1.0,1.0 };
//(3)创建渲染示例renderers
vtkSmartPointer<vtkRenderer>originalRenderer1 = vtkSmartPointer<vtkRenderer>::New();
originalRenderer1->SetViewport(leftViewport);
originalRenderer1->AddActor(originalActor1);
originalRenderer1->ResetCamera();
originalRenderer1->SetBackground(1.0, 1.0, 1.0);
vtkSmartPointer<vtkRenderer>originalRenderer2 = vtkSmartPointer<vtkRenderer>::New();
originalRenderer2->SetViewport(midViewport);
originalRenderer2->AddActor(originalActor2);
originalRenderer2->ResetCamera();
originalRenderer2->SetBackground(1.0, 1.0, 1.0);
vtkSmartPointer<vtkRenderer>blendRenderer = vtkSmartPointer<vtkRenderer>::New();
blendRenderer->SetViewport(rightViewport);
blendRenderer->AddActor(blendActor);
blendRenderer->ResetCamera();
blendRenderer->SetBackground(1.0, 1.0, 1.0);
//(4)创建渲染窗口renderWindow
vtkSmartPointer<vtkRenderWindow>renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(originalRenderer1);
renderWindow->AddRenderer(originalRenderer2);
renderWindow->AddRenderer(blendRenderer);
renderWindow->SetSize(640, 320);
renderWindow->Render();
renderWindow->SetWindowName("ImageBlendExample");
//(5)创建交互RenderWindowInteractor以及交互样式
vtkSmartPointer<vtkRenderWindowInteractor>renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
vtkSmartPointer<vtkInteractorStyleImage> style = vtkSmartPointer<vtkInteractorStyleImage>::New();
renderWindowInteractor->SetInteractorStyle(style);
renderWindowInteractor->SetRenderWindow(renderWindow);
renderWindowInteractor->Initialize();
renderWindowInteractor->Start();
return 0;
}
操作結果:
問題: Fusion 画像が表示されない
エラー メッセージ:vtkCompositeDataPipeline (00000201D3E32960): Input for connection index 0 on input port index 1 for algorithm vtkImageBlend(00000201D3E1F930) is of type vtkImageData, but a vtkImageStencilData is required.
エラー修正の参照: VTK Notes-Image Fusion-02-vtkImageBlend Class
注: VTK のバージョンには互換性がないため、SetInput() が使用できなくなります。
- パイプ接続を確立したい場合は、SetInputConnection()、GetOutputPort()を使用します。
- 独立したデータセットを処理したい場合は、SetInputData() を使用します。