马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
VTK医学图像处理---vtkImageData类
目录
VTK医学图像处理---vtkImageData类
简介:
1 Mricro软件的安装和利用
(1) Mricro安装
(2) Mricro转换DICOM为裸数据
2 从硬盘读取数据到vtkImageData
3 vtkImageData转RGB或RGBA格式
4 训练
总结
简介:
对于医学图像来说,vtkImageData是利用频率非常高的类,因为医学图像通常为较为规则的矩形或容积范例(三维),而vtkImageData类重要就是用于存储此类数据的,vtk中相干算法(好比阈值、缩放等)的输入和输出也是vtkImageData类,熟练把握vtkImageData类非常重要。
vtkDICOMImageReader类读取文件夹中的DICOM文件后,DICOM数据也存储在vtkImageData类中,本篇博文将跳过vtkDICOMImageReader类,直接从硬盘读取数据到vtkImageData类中,以增强大家对vtkImageData类的熟悉。
由于DICOM格式非常负责,有专门的开源库对DICOM文件进行分析,好比DCMTK(DCMTK - dicom.offis.de),我们不筹划具体介绍DICOM标准,因此我们将借助一个免费的软件Mricro(建议大家学会利用给软件,不管是开辟还是做科研都非常有用)来将DICOM文件转换为原始数据,采用C语言从硬盘读取原始数据到vtkImageData类中。
本博文重要包括为 Mricro的安装和利用,从硬盘读取数据到vtkImageData类,vtkImageData类的具体介绍。
1 Mricro软件的安装和利用
下载地址:MRIcro software guide (sc.edu)
打开网页后,点击下图中红色方框中的链接开始下载。
(1) Mricro安装
下载后,解压会看到下面的图标,双击安装,提出是否安装,选择是,一路默认安装,具体步调如下图:
(2) Mricro转换DICOM为裸数据
在开始栏中搜索Mricro,或从所有应用步伐内里找到Mricro启动,启动后的界面为:
DICOM数据下载地址:【免费】VTK-医学图像处理博文中需要的DICOM测试数据资源-CSDN文库
下载DICOM数据解压,在Mricro软件的菜单项中选择 Import--Convert foreign to Analyze,跳出选择对话框。
在Number of Files中要输入待转换的DICOM文件张数, 例如这里我们转换10张,就在该输入框内填写10,记得勾选 Open sequential files:ignore filename选项,然后点击 Select。
在Conversion Options框中,继续点击 OK
这里有时候会跳出一个或两个提示框,不消管它,点击OK继续
到 Select 对话框后,恣意选中一张待转换的DICOM文件,然后再文件名中输入要保存为裸数据的名称,点击 打开。
单击 打开后,会跳出导出保存框,在保存框中输入要保存的名称,点击 保存按钮进行保存。
打开DicomFiles地点文件夹,会发现内里多了两个文件:test.hdr和 test.img
此中 test.hdr文件中保存的数据的长宽高,空间位置等信息
test.img文件中就是纯粹的裸数据,接下来我们将读取test.img中的数据到vtkImageData中。
双击test.hdr,用Mricro软件打开它,在软件的左侧,可以看到test.img中的数据长为512,宽为512,一共有10张图像,数据范例为short。
2 从硬盘读取数据到vtkImageData
老例子,先看下代码,也可以拷贝到自己的项目中,运行下:
- #define _CRT_SECURE_NO_WARNINGS
- #include "vtkImageMapToWindowLevelColors.h"
- #include "vtkImageActor.h"
- #include "vtkImageMapper3D.h"
- #include "vtkImageData.h"
- #include "vtkNew.h"
- #include "vtkDICOMImageReader.h"
- #include "vtkRenderWindow.h"
- #include "vtkRenderWindowInteractor.h"
- #include "vtkRenderer.h"
- #include "vtkCamera.h"
- int ImageSlice = 0;
- void main()
- {
- vtkNew<vtkImageData> imageData;
- imageData->SetDimensions(512, 512, 10);
- imageData->SetSpacing(.49, .49, .7);
- imageData->SetOrigin(0.0, 0.0, 0.0);
- imageData->AllocateScalars(VTK_SHORT, 1);
- void *ptr = imageData->GetScalarPointer();
- size_t bSize = 512 * 512 * 10;
- FILE* pFile = fopen("D:\\DicomFiles\\test.img","rb+");
- if (NULL == pFile)
- return;
- fread(ptr, sizeof(short), bSize, pFile);
- fclose(pFile);
- int* ext = imageData->GetExtent();
- // map the input image through a lookup table and window / level it
- vtkNew<vtkImageMapToWindowLevelColors> windowLevel;
- windowLevel->SetWindow(1000);
- windowLevel->SetLevel(800);
- windowLevel->SetInputData(imageData);
- //vtkImageActor: draw an image in a rendered 3D scene
- vtkNew<vtkImageActor> imageActor;
- imageActor->SetDisplayExtent(ext[0], ext[1], ext[2], ext[3], ImageSlice, ImageSlice);
- imageActor->GetMapper()->SetInputConnection(windowLevel->GetOutputPort());
- // The renderer generates the image which is then displayed on the render window.
- vtkNew<vtkRenderer> renderer;
- renderer->AddActor(imageActor);
- renderer->SetBackground(.2,.2,.2);
- vtkCamera *cam = renderer->GetActiveCamera();
- if (cam)
- {
- // 获取物体在三维空间中的原点,XYZ范围和中心
- //vtkImageData* idata = reader->GetOutput();
- vtkImageData* idata = imageData;
- double* origins = idata->GetOrigin(); // 三维坐标中的起点
- double* bounds = idata->GetBounds(); // 包围盒的xyz范围
- double* center = idata->GetCenter(); // 中心
- cam->SetFocalPoint(center);
- cam->SetPosition(center[0], center[1], center[2] - bounds[5]); // -1 if medical ?
- cam->SetViewUp(0, 1, 0);
- cam->SetClippingRange(0.1,1000);
- renderer->ResetCamera();
- }
- // The render window is the actual GUI window that appears on the computer screen
- vtkNew<vtkRenderWindow> renderWindow;
- renderWindow->SetSize(512, 512);
- renderWindow->AddRenderer(renderer);
- renderWindow->SetWindowName("Dicom Image");
- // The render window interactor captures mouse events
- // and will perform appropriate camera or actor manipulation
- // depending on the nature of the events.
- vtkNew<vtkRenderWindowInteractor> interactor;
- interactor->SetRenderWindow(renderWindow);
- // This starts the event loop and as a side effect causes an initial render.
- renderWindow->Render();
- interactor->Start();
- }
复制代码 重要修改的代码如下:
- vtkNew<vtkImageData> imageData;
- imageData->SetDimensions(512, 512, 10);
- imageData->SetSpacing(.49, .49, .7);
- imageData->SetOrigin(0.0, 0.0, 0.0);
- imageData->AllocateScalars(VTK_SHORT, 1);
- void *ptr = imageData->GetScalarPointer();
- size_t bSize = 512 * 512 * 10;
- FILE* pFile = fopen("D:\\DicomFiles\\test.img","rb+");
- if (NULL == pFile)
- return;
- fread(ptr, sizeof(short), bSize, pFile);
- fclose(pFile);
复制代码 SetDimensions 函数重要用来设置图像的长宽高信息
SetSpacing 是像素间距,图像的(512 - 1)* 0.49 就是图像宽的实际尺寸;
SetOrigin 是图像活着界坐标中的位置;
AllocateScalars有两个参数,第一个参数指定命据范例(16bit short);第二个参数1是 一个像素是有一个元素组成(对于BMP位图来说,一个像素是有RGB/RGBA组成的);
AllocateScalars 同时还分配内存空间;
GetScalarPointer函数可以获取分配内存空间的地址;有了地址,有了数据的大小,就可以直接从硬盘读取裸数据了。读取的代码用C语言来写的,这里就不解释了。
运行结果如下:
3 vtkImageData转RGB或RGBA格式
接下来我们增加了个一个Convert2RGB函数,用户将vtkImageData中的数据转换为RGB格式的数据,并保存的硬盘,然后用Mricro打开查看。
完整源代码如下:
- #define _CRT_SECURE_NO_WARNINGS
- #include "vtkImageMapToWindowLevelColors.h"
- #include "vtkImageActor.h"
- #include "vtkImageMapper3D.h"
- #include "vtkImageData.h"
- #include "vtkNew.h"
- #include "vtkDICOMImageReader.h"
- #include "vtkRenderWindow.h"
- #include "vtkRenderWindowInteractor.h"
- #include "vtkRenderer.h"
- #include "vtkCamera.h"
- #include "vtkWindowLevelLookupTable.h"
- int ImageSlice = 0;
- void Convert2RGB(vtkImageData* pData);
- void main()
- {
- vtkNew<vtkImageData> imageData;
- imageData->SetDimensions(512, 512, 10);
- imageData->SetSpacing(.49, .49, .7);
- imageData->SetOrigin(0.0, 0.0, 0.0);
- imageData->AllocateScalars(VTK_SHORT, 1);
- void *ptr = imageData->GetScalarPointer();
- size_t bSize = 512 * 512 * 10;
- FILE* pFile = fopen("D:\\DicomFiles\\test.img","rb+");
- if (NULL == pFile)
- return;
- fread(ptr, sizeof(short), bSize, pFile);
- fclose(pFile);
- Convert2RGB(imageData);
- int* ext = imageData->GetExtent();
- // map the input image through a lookup table and window / level it
- vtkNew<vtkImageMapToWindowLevelColors> windowLevel;
- windowLevel->SetWindow(1000);
- windowLevel->SetLevel(800);
- windowLevel->SetInputData(imageData);
- //vtkImageActor: draw an image in a rendered 3D scene
- vtkNew<vtkImageActor> imageActor;
- imageActor->SetDisplayExtent(ext[0], ext[1], ext[2], ext[3], ImageSlice, ImageSlice);
- imageActor->GetMapper()->SetInputConnection(windowLevel->GetOutputPort());
- // The renderer generates the image which is then displayed on the render window.
- vtkNew<vtkRenderer> renderer;
- renderer->AddActor(imageActor);
- renderer->SetBackground(.2,.2,.2);
- vtkCamera *cam = renderer->GetActiveCamera();
- if (cam)
- {
- // 获取物体在三维空间中的原点,XYZ范围和中心
- //vtkImageData* idata = reader->GetOutput();
- vtkImageData* idata = imageData;
- double* origins = idata->GetOrigin(); // 三维坐标中的起点
- double* bounds = idata->GetBounds(); // 包围盒的xyz范围
- double* center = idata->GetCenter(); // 中心
- cam->SetFocalPoint(center);
- cam->SetPosition(center[0], center[1], center[2] - bounds[5]); // -1 if medical ?
- cam->SetViewUp(0, 1, 0);
- cam->SetClippingRange(0.1,1000);
- renderer->ResetCamera();
- }
- // The render window is the actual GUI window that appears on the computer screen
- vtkNew<vtkRenderWindow> renderWindow;
- renderWindow->SetSize(512, 512);
- renderWindow->AddRenderer(renderer);
- renderWindow->SetWindowName("Dicom Image");
- // The render window interactor captures mouse events
- // and will perform appropriate camera or actor manipulation
- // depending on the nature of the events.
- vtkNew<vtkRenderWindowInteractor> interactor;
- interactor->SetRenderWindow(renderWindow);
- // This starts the event loop and as a side effect causes an initial render.
- renderWindow->Render();
- interactor->Start();
- }
- void Convert2RGB(vtkImageData* pData)
- {
- void *ptr = pData->GetScalarPointer();
- vtkNew<vtkWindowLevelLookupTable> table;
- table->SetWindow(1000);
- table->SetLevel(800);
- table->Build();
- table->BuildSpecialColors();
- long iCount = 512 * 512;
- void *rgbPtr = malloc(iCount * 3);
- unsigned char *desPtr = (unsigned char *)rgbPtr;
- table->MapScalarsThroughTable2(ptr, desPtr, VTK_UNSIGNED_SHORT, iCount, VTK_LUMINANCE, VTK_RGB);
- FILE* pFile = fopen("color2.img", "wb+");
- if (!pFile)
- return;
- fwrite(rgbPtr, 1, iCount * 3, pFile);
- fclose(pFile);
- free(rgbPtr);
- }
复制代码 打开源代码地点文件夹,会发现多了一个color2.img,打开Mricro软件,将 color2.img拖到Mricro软件中,发现打开后是乱码,这是由于Mricro软件左侧的参数信息不精确。

将左侧X Y Z分别填入512 512 1
将Data,选中 24-bit rgb,
然后点击菜单中的Header,Save header;


保存完成后,双击 color2.hdr,打开,显示结果如下:

在这里例子中,我们只保存了一张RGB,而图像是有10张的,请自己动手,把10张图像全部保存成为RGB数据,训练一下。
4 训练
(1)用vtkImageData读取一张BMP图像,并显示;
(2)将相机的位置这是在现在位置的反方向,对比下显示结果;
(3)将vtkImageData中的数据重新保存一份,用Mricro软件打开查看是否精确;
总结
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |