MPR

  MPR(Multi-planar Reformation),多平面重建;多平面重建是将扫描范围内所有的轴位图像叠加起来,再对某些标线标定的重组线所指定的组织进行冠状位、矢状位、任意角度斜位图像重组。

MPR的优点

  1.能任意产生新的断层图像,而无需重复扫描;
  2.原图像的密度值被忠实保持到了结果图像上。
  3.曲面重组能在一副图像里展开显示弯曲物体的全长。

MPR的缺点

  1.难以表达复杂的空间结构;
  2.曲面重组易造成假阳性;

  多平面重建(MPR)是CT三维数据呈现的重要内容,其在三维数据的任一点空间位置,采用XY、XZ和YZ三个平面切空间数据得到三个切面分别为轴状面、冠状面和矢状面,而且X/Y/Z三个轴可以绕三维坐标原点任意旋转。

vtkImageReslice

  vtkImageReslice类可以从体数据内的一点沿着不同的方向切出一个平面图像;
  vtkImageReslice是图像几何过滤器的瑞士军刀:它可以以合理高效的任意组合排列、旋转、翻转、缩放、重采样、变形和填充图像数据。置换、重采样和填充等简单操作的效率与专用vtkImagePermute、vtkImageResample和vtkImagePad过滤器类似。  vtkimanageslice非常适合执行以下任务:
    1) 对图像进行简单的旋转、缩放和平移。通常,最好先使用vtkImageChangeInformation使图像居中,这样缩放和旋转就发生在图像的中心而不是左下角。
    2) 通过SetInformationInput()方法对一个数据集进行重采样,以匹配第二个数据集的体素采样,例如为了比较两个图像或合并两个图像。如果两幅图像不在同一坐标空间中,可以通过SetResliceTransform()方法同时应用线性或非线性变换。
    3) 从图像体中提取切片。使用vtkImageReslice可以从体数据中获取到指定的正交、斜切方向的上的切面图像;最方便的方法是使用SetResliceAxesDirectionCosines()指定切片的方向。方向余弦表示输出体积的x、y和z轴。SetOutputDimensionality(2)方法用于指定要输出切片而不是Volume的对象。SetResliceAxesOrigin()方法用于提供切片将通过的(x,y,z)点。可以同时使用ResliceAxes和ResliceTransform,以便从已应用转换的Volume中提取切片。
  3)内容是比较常用的内容,可以提取平行于XY平面、YZ平面、XZ平面的切片,还可以提取斜切切片;
设置切片的步骤是先计算出一个切片的中心位置,计算出切面的变换矩阵(4*4矩阵),前三列分别表示X、Y和Z方向矢量,第四列为切面坐标系原点。通过修改切面坐标系原点,可以得到不同位置的切面图像切面的原点必须过图像内部一点

vtkImageReslice类接口

设置变换矩阵

  变换矩阵是4*4的四阶矩阵,其中左上角的3*3矩阵是3个方向上的向量余弦值;一般情况下,Z轴方向上的方向向量是XY的叉积,也就是Z轴方向会垂直于XY平面;
  三个方向上的方向余弦值:

virtual void SetResliceAxes(vtkMatrix4x4*);
vtkGetObjectMacro(ResliceAxes, vtkMatrix4x4);
void SetResliceAxesDirectionCosines(double x0, double x1, double x2, double y0, double y1,double y2, double z0, double z1, double z2);
void SetResliceAxesDirectionCosines(const double x[3], const double y[3], const double z[3]){this->SetResliceAxesDirectionCosines(x[0], x[1], x[2], y[0], y[1], y[2], z[0], z[1], z[2]);
}
void SetResliceAxesDirectionCosines(const double xyz[9]){this->SetResliceAxesDirectionCosines(xyz[0], xyz[1], xyz[2], xyz[3], xyz[4], xyz[5], xyz[6], xyz[7], xyz[8]);
}
void GetResliceAxesDirectionCosines(double x[3], double y[3], double z[3]);
void GetResliceAxesDirectionCosines(double xyz[9]){this->GetResliceAxesDirectionCosines(&xyz[0], &xyz[3], &xyz[6]);
}
double* GetResliceAxesDirectionCosines() VTK_SIZEHINT(9){this->GetResliceAxesDirectionCosines(this->ResliceAxesDirectionCosines);return this->ResliceAxesDirectionCosines;
}

  当OutputDimensionality设置为3时,可以通过SetResliceAxes或者SetResliceTransform生成转换矩阵,将体数据进行缩放,扭曲,平移等变换;
  SetResliceAxesOrigin可以指定重新切片轴的原点,是变换矩阵最后一列的前三个元素。如果vtkImageReslice有变换矩阵就修改当前的变换矩阵内的值,如果没有,就创建新的变换矩阵;

void SetResliceAxesOrigin(double x, double y, double z);
void SetResliceAxesOrigin(const double xyz[3]){this->SetResliceAxesOrigin(xyz[0], xyz[1], xyz[2]);
}
void GetResliceAxesOrigin(double xyz[3]);
double* GetResliceAxesOrigin() VTK_SIZEHINT(3){this->GetResliceAxesOrigin(this->ResliceAxesOrigin);return this->ResliceAxesOrigin;
}

  设定由vtkTransform表示变换矩阵信息:

virtual void SetResliceTransform(vtkAbstractTransform*);
vtkGetObjectMacro(ResliceTransform, vtkAbstractTransform);

设置输出维度

  OutputDimensionality表示输出的维度有四种:1、2、3或0,默认值是3。不过一般切片的话,就是二维图像,设置为2;
  如果维度是2D,则输出的Z范围被强制为(0,0),输出的Z原点被强制为0.0(即输出范围被限制在xy平面)。如果维度是1D,则输出范围限制在x轴上。对于0D,输出范围由位于(0,0,0)的单个体素组成。

vtkSetMacro(OutputDimensionality, int);
vtkGetMacro(OutputDimensionality, int);

设置图像输入

  这里vtkImageReslice类输入的一般就是vtkImageData,vtkImageData为三维体数据,毕竟是从体数据中获取切片图像的嘛。
  使用SetInputConnection和SetInputData方法,SetInformationInput用来设置渲染管线中的信息,之前有讲过;

virtual void SetInformationInput(vtkImageData*);
vtkGetObjectMacro(InformationInput, vtkImageData);

设置标识

  TransformInputSampling用来指定是否根据重切片轴的方向余弦原点变换输入的间距、原点和范围,然后再将其应用为默认输出间距、原点和范围(默认值:true);

vtkSetMacro(TransformInputSampling, vtkTypeBool);
vtkBooleanMacro(TransformInputSampling, vtkTypeBool);
vtkGetMacro(TransformInputSampling, vtkTypeBool);

  AutoCropOutput项可以确保输出的范围足够大时,不会裁剪任何数据;默认值是禁用的。

vtkSetMacro(AutoCropOutput, vtkTypeBool);
vtkBooleanMacro(AutoCropOutput, vtkTypeBool);
vtkGetMacro(AutoCropOutput, vtkTypeBool);

  Wrap包裹标识;

vtkSetMacro(Wrap, vtkTypeBool);
vtkGetMacro(Wrap, vtkTypeBool);
vtkBooleanMacro(Wrap, vtkTypeBool);

  Mirror镜像标识;

vtkSetMacro(Mirror, vtkTypeBool);
vtkGetMacro(Mirror, vtkTypeBool);
vtkBooleanMacro(Mirror, vtkTypeBool);

  用Border设置是否将外观输入边界延伸半个体素(默认值:On)。
  这将更改在输入图像的边界处处理插值的方式:如果输出体素的中心超出输入图像的边缘,但在边缘的半体素宽度范围内(使用输入体素宽度),则计算输出体素的值,如同输入的边缘体素被复制到输入图像的边缘。如果“Mirror”或“Wrap”处于启用状态,则此操作无效。

vtkSetMacro(Border, vtkTypeBool);
vtkGetMacro(Border, vtkTypeBool);
vtkBooleanMacro(Border, vtkTypeBool);

  当Border为On开启状态时,用BorderThickness设置图像的边框厚度(默认值:0.5);

vtkSetMacro(BorderThickness, double);
vtkGetMacro(BorderThickness, double);

  InterpolationMode是vtkImageReslice类使用的插值模式,默认为nearest neighbor插值;
  SetInterpolator设置要使用的插值器vtkAbstractImageInterpolator。默认插值器支持最近(Nearest)、线性(Linear)和三次插值模式(Cubic);

vtkSetClampMacro(InterpolationMode, int, VTK_RESLICE_NEAREST, VTK_RESLICE_CUBIC);
vtkGetMacro(InterpolationMode, int);
void SetInterpolationModeToNearestNeighbor() { this->SetInterpolationMode(VTK_RESLICE_NEAREST); }
void SetInterpolationModeToLinear() { this->SetInterpolationMode(VTK_RESLICE_LINEAR); }
void SetInterpolationModeToCubic() { this->SetInterpolationMode(VTK_RESLICE_CUBIC); }
virtual const char* GetInterpolationModeAsString();
virtual void SetInterpolator(vtkAbstractImageInterpolator* sampler);
virtual vtkAbstractImageInterpolator* GetInterpolator();
void SetInterpolate(int t) {if (t && !this->GetInterpolate()) {this->SetInterpolationModeToLinear();}else if (!t && this->GetInterpolate()){this->SetInterpolationModeToNearestNeighbor();}
}
void InterpolateOn() { this->SetInterpolate(1); }
void InterpolateOff() { this->SetInterpolate(0); }
int GetInterpolate() { return (this->GetInterpolationMode() != VTK_RESLICE_NEAREST); }

  SlabMode是板模式,用来生成厚切片(类似MIP功能),默认值是Mean。如果调用SetSlabNumberOfSlices(N)时N大于1,则每个输出片实际上是N个片的组合。使用此方法需要指定要使用的合成模式。合成模式有四种:Min(最小)、Max(最大)、Mean(平均值)和Sum(累加和);

vtkSetClampMacro(SlabMode, int, VTK_IMAGE_SLAB_MIN, VTK_IMAGE_SLAB_SUM);
vtkGetMacro(SlabMode, int);
void SetSlabModeToMin() { this->SetSlabMode(VTK_IMAGE_SLAB_MIN); }
void SetSlabModeToMax() { this->SetSlabMode(VTK_IMAGE_SLAB_MAX); }
void SetSlabModeToMean() { this->SetSlabMode(VTK_IMAGE_SLAB_MEAN); }
void SetSlabModeToSum() { this->SetSlabMode(VTK_IMAGE_SLAB_SUM); }
virtual const char* GetSlabModeAsString();

  SlabNumberOfSlices用来设置Slab模式下,合并时用到的图层个数;

vtkSetMacro(SlabNumberOfSlices, int);
vtkGetMacro(SlabNumberOfSlices, int);

  SlabTrapezoidIntegration设定使用梯形积分进行板计算。Slab模式合并时,做加法和平均数的时候,把第一片和最后一片的权重减半。默认情况下,它处于禁用状态。

vtkSetMacro(SlabTrapezoidIntegration, vtkTypeBool);
vtkBooleanMacro(SlabTrapezoidIntegration, vtkTypeBool);
vtkGetMacro(SlabTrapezoidIntegration, vtkTypeBool);

  SlabSliceSpacingFraction是板间距,是输出片间距的一部分。
  当选择了各种slab模式中的一种时,通过生成几个“临时”输出片,然后根据slab模式组合它们来生成每个输出片。默认情况下,这些临时切片之间的间距是OutputSpacing的Z分量。此方法将这些临时切片之间的间距设置为输出间距的一小部分。

vtkSetMacro(SlabSliceSpacingFraction, double);
vtkGetMacro(SlabSliceSpacingFraction, double);

  优化标识Optimization,打开和关闭优化(默认为打开,仅应出于测试目的关闭它们);

vtkSetMacro(Optimization, vtkTypeBool);
vtkGetMacro(Optimization, vtkTypeBool);
vtkBooleanMacro(Optimization, vtkTypeBool);

  设置输出标量数据类型,有 VTK_CHAR, VTK_SIGNED_CHAR, VTK_UNSIGNED_CHAR, VTK_SHORT, VTK_UNSIGNED_SHORT, VTK_INT, VTK_UNSIGNED_INT, VTK_FLOAT, or VTK_DOUBLE,除此之外的类型均不支持,如果设定了输出类型,那么标量数值就被限定在类型的有效范围内。

vtkSetMacro(OutputScalarType, int);
vtkGetMacro(OutputScalarType, int);

  SetBackgroundColor对多分量图像设置背景颜色,这里背景颜色是不是数值的意思,暂时还没弄明白;
  SetBackgroundLevel对单通道的灰度图像设置设置背景灰度值;
  SetStencilData使用模具将计算限制到输出的特定区域。输出模具的“outside”的部分将被清除为背景色(莫非是刚才的背景色)。
  SetGenerateStencilOutput设置是否生成一个输出模具,该模具定义哪些像素被插值,哪些像素超出输入范围。

vtkSetVector4Macro(BackgroundColor, double);
vtkGetVector4Macro(BackgroundColor, double);
void SetBackgroundLevel(double v) { this->SetBackgroundColor(v, v, v, v); }
double GetBackgroundLevel() { return this->GetBackgroundColor()[0]; }
void SetStencilData(vtkImageStencilData* stencil);
vtkImageStencilData* GetStencil();
vtkSetMacro(GenerateStencilOutput, vtkTypeBool);
vtkGetMacro(GenerateStencilOutput, vtkTypeBool);
vtkBooleanMacro(GenerateStencilOutput, vtkTypeBool);
vtkAlgorithmOutput* GetStencilOutputPort() { return this->GetOutputPort(1); }
vtkImageStencilData* GetStencilOutput();
void SetStencilOutput(vtkImageStencilData* stencil);

实例

代码

  1.使用vtkMetaImageReader类读取一个.mha文件;
  mha文件一定要和.raw文件放在同一个文件夹,要不然会报错;

ERROR: In I:\v-vtk\VTK-8.2.0\IO\Image\vtkMetaImageReader.cxx, line 237
vtkMetaImageReader (013DEC00): MetaImage cannot read data from file.

  2.计算获取切面的变换矩阵vtkMatrix4x4信息;
  3.使用vtkImageReslice类获取切面数据;
  4.进行渲染显示;

#include "vtkSmartPointer.h"
#include "vtkMetaImageReader.h"
#include "vtkImageData.h"
#include "vtkMatrix4x4.h"
#include "vtkImageReslice.h"
#include "vtkLookupTable.h"
#include "vtkImageMapToColors.h"
#include "vtkImageActor.h"
#include "vtkImageMapper3D.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkInteractorStyleImage.h"
#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);using namespace std;
int main(){vtkNew<vtkMetaImageReader> reader;reader->SetFileName("D:\\data\\brain.mhd");reader->Update();int extent[6];double spacing[3];double origin[3];reader->GetOutput()->GetExtent(extent);reader->GetOutput()->GetSpacing(spacing);reader->GetOutput()->GetOrigin(origin);double center[3];center[0] = origin[0] + spacing[0] * 0.5 * (extent[0] + extent[1]);center[1] = origin[1] + spacing[1] * 0.5 * (extent[2] + extent[3]);center[2] = origin[2] + spacing[2] * 0.5 * (extent[4] + extent[5]);static double axialElements[16] = {1, 0, 0, 0,0, 1, 0, 0,0, 0, 1, 0,0, 0, 0, 1};vtkNew<vtkMatrix4x4> resliceAxes;resliceAxes->DeepCopy(axialElements);resliceAxes->SetElement(0, 3, center[0]);resliceAxes->SetElement(1, 3, center[1]);resliceAxes->SetElement(2, 3, center[2]);vtkNew<vtkImageReslice> reslice;reslice->SetInputConnection(reader->GetOutputPort());reslice->SetOutputDimensionality(2);reslice->SetResliceAxes(resliceAxes);reslice->SetInterpolationModeToLinear();vtkNew<vtkLookupTable> colorTable;colorTable->SetRange(0, 1000);colorTable->SetValueRange(0.0, 1.0);colorTable->SetSaturationRange(0.0, 0.0);colorTable->SetRampToLinear();colorTable->Build();vtkNew<vtkImageMapToColors> colorMap;colorMap->SetLookupTable(colorTable);colorMap->SetInputConnection(reslice->GetOutputPort());vtkNew<vtkImageActor> imgActor;imgActor->GetMapper()->SetInputConnection(colorMap->GetOutputPort());vtkNew<vtkRenderer> renderer;renderer->AddActor(imgActor);renderer->SetBackground(1.0, 1.0, 1.0);vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();renderWindow->AddRenderer(renderer);renderWindow->Render();renderWindow->SetSize(640, 480);renderWindow->SetWindowName("ImageResliceExample");vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;vtkNew<vtkInteractorStyleImage> imagestyle;renderWindowInteractor->SetInteractorStyle(imagestyle);renderWindowInteractor->SetRenderWindow(renderWindow);renderWindowInteractor->Initialize();renderWindowInteractor->Start();return 0;
}

鼠标点击进行图层切换

#include "pch.h"
#include "TestDicomImage.h"
#include "vtk_include.h"
#include "dcmtk\config\osconfig.h"
#include "dcmtk\dcmdata\dctk.h"
#include <dcmtk/dcmjpeg/djdecode.h>  /* for dcmjpeg decoders */
#include <dcmtk/dcmjpeg/djencode.h>
#include <dcmtk/dcmjpls/djdecode.h>       //for JPEG-LS decode
#include <dcmtk/dcmjpls/djencode.h>       //for JPEG-LS encode#include <set>
#include <string>using namespace std;
class vtkImageInteractionCallback : public vtkCommand{public:static vtkImageInteractionCallback *New(){return new vtkImageInteractionCallback;}vtkImageInteractionCallback(){this->Slicing = 0;this->ImageReslice = 0;this->Interactor = 0;}void SetImageReslice(vtkImageReslice *reslice){this->ImageReslice = reslice;}void SetImageMapToColors(vtkImageMapToColors *mapToColors){this->mapToColors = mapToColors;}vtkImageReslice *GetImageReslice(){return this->ImageReslice;}void SetInteractor(vtkRenderWindowInteractor *interactor){this->Interactor = interactor;}vtkRenderWindowInteractor *GetInteractor(){return this->Interactor;}virtual void Execute(vtkObject *, unsigned long event, void *){vtkRenderWindowInteractor *interactor = this->GetInteractor();int lastPos[2];interactor->GetLastEventPosition(lastPos);int currPos[2];interactor->GetEventPosition(currPos);if (event == vtkCommand::LeftButtonPressEvent){this->Slicing = 1;}else if (event == vtkCommand::LeftButtonReleaseEvent){this->Slicing = 0;}else if (event == vtkCommand::MouseMoveEvent){if (this->Slicing){vtkImageReslice *reslice = this->ImageReslice;// Increment slice position by deltaY of mouseint deltaY = lastPos[1] - currPos[1];reslice->Update();double sliceSpacing = reslice->GetOutput()->GetSpacing()[2];vtkMatrix4x4 *matrix = reslice->GetResliceAxes();// move the center point that we are slicing throughdouble point[4] = {0.0};double center[4];             point[2] = sliceSpacing * deltaY;              matrix->MultiplyPoint(point, center);matrix->SetElement(0, 3, center[0]);matrix->SetElement(1, 3, center[1]);matrix->SetElement(2, 3, center[2]);mapToColors->Update();interactor->Render();}else{vtkInteractorStyle *style = vtkInteractorStyle::SafeDownCast(interactor->GetInteractorStyle());if (style){style->OnMouseMove();}}}}private:int Slicing;vtkImageReslice *ImageReslice;vtkRenderWindowInteractor *Interactor;vtkImageMapToColors *mapToColors;
};void TestDicomImage::Test(){DJDecoderRegistration::registerCodecs();DJLSEncoderRegistration::registerCodecs();        //JPEG-LS encoder registerCodecsDJLSDecoderRegistration::registerCodecs();      //JPEG-LS decoder registerCodecsint count = 273;int single_img = 512 * 512;int size_all = count * single_img;short* pBuf = new short[size_all] {0};for (int i = 1; i < 274; i++)  {string fileName = "G:\\data\\" + to_string(i) + ".DCM";DcmFileFormat *myFileFormat = new DcmFileFormat;OFCondition cond = myFileFormat->loadFile(fileName.c_str());DcmElement* pElement = nullptr;myFileFormat->getDataset()->chooseRepresentation(EXS_DeflatedLittleEndianExplicit, NULL);myFileFormat->getDataset()->findAndGetElement(DCM_PixelData, pElement);if (pElement != NULL) {int size = pElement->getLength() / 2;OFCondition cond = pElement->loadAllDataIntoMemory();if (cond.good()) {Uint16 * ptr;cond = pElement->getUint16Array(ptr);if (cond.good()) {memcpy(pBuf + (i - 1)*single_img, ptr, size * sizeof(short));}}}delete myFileFormat;}int extent[6] = { 0,511,0,511,0,272 };double spacing[3] = { 0.3, 0.3, 0.75 };double origin[3] = { 0 };double center[3] = { 0 };center[0] = origin[0] + spacing[0] * 0.5 * (extent[0] + extent[1]);center[1] = origin[1] + spacing[1] * 0.5 * (extent[2] + extent[3]);center[2] = origin[2] + spacing[2] * 0.5 * (extent[4] + extent[5]);vtkNew<vtkShortArray> dataArray;dataArray->SetArray(pBuf, size_all, 1);vtkNew<vtkImageData> pALLImageData;pALLImageData->AllocateScalars(VTK_SHORT, 1);pALLImageData->SetDimensions(512, 512, 273);pALLImageData->GetPointData()->SetScalars(dataArray);pALLImageData->SetSpacing(spacing);pALLImageData->SetOrigin(origin);static double axialElements[16] = {1, 0, 0, 0,0, 1, 0, 0,0, 0, 1, 0,0, 0, 0, 1};vtkNew<vtkMatrix4x4> resliceAxes;resliceAxes->DeepCopy(axialElements);resliceAxes->SetElement(0, 3, center[0]);resliceAxes->SetElement(1, 3, center[1]);resliceAxes->SetElement(2, 3, center[2]);vtkNew<vtkImageReslice> reslice;reslice->SetInputData(pALLImageData);reslice->SetOutputDimensionality(2);reslice->SetResliceAxes(resliceAxes);reslice->SetInterpolationModeToLinear();vtkNew<vtkLookupTable> colorTable;colorTable->SetRange(0, 1000);colorTable->SetValueRange(0.0, 1.0);colorTable->SetSaturationRange(0.0, 0.0);colorTable->SetRampToLinear();colorTable->Build();vtkNew<vtkImageMapToColors> colorMap;colorMap->SetLookupTable(colorTable);colorMap->SetInputConnection(reslice->GetOutputPort());colorMap->Update();vtkNew<vtkImageActor> imgActor;imgActor->SetInputData(colorMap->GetOutput());vtkNew<vtkRenderer> renderer;renderer->AddActor(imgActor);renderer->SetBackground(0.3, 0.4, 0.3);vtkNew<vtkRenderWindow> renderWindow;renderWindow->SetSize(500, 500);renderWindow->AddRenderer(renderer);vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;vtkNew<vtkInteractorStyleImage> imagestyle;renderWindowInteractor->SetInteractorStyle(imagestyle);renderWindowInteractor->SetRenderWindow(renderWindow);renderWindowInteractor->Initialize();vtkNew<vtkImageInteractionCallback> callback;callback->SetImageReslice(reslice);callback->SetInteractor(renderWindowInteractor);callback->SetImageMapToColors(colorMap);imagestyle->AddObserver(vtkCommand::MouseMoveEvent, callback);imagestyle->AddObserver(vtkCommand::LeftButtonPressEvent, callback);imagestyle->AddObserver(vtkCommand::LeftButtonReleaseEvent, callback);renderWindowInteractor->Start();
}

参考资料

1.vtkImageReslice Class Reference

VTK笔记-计算MPR切面-vtkImageReslice类相关推荐

  1. VTK笔记-计算MPR切面-vtkImageReslice输出视口设置

      设定的坐标点,vtkImageReslice生成的切面是一个无限大的二维图像,图像的中心点是设定的坐标点,在二维图像中是坐标原点(0,0),根据需要可以设定二维图像左下角的坐标位置,也可以设定像素 ...

  2. VTK笔记-纹理贴图-vtkTexture类

    纹理贴图   计算机图形学中的纹理既包括通常意义上物体表面的纹理即使物体表面呈现凹凸不平的沟纹,同时也包括在物体的光滑表面上的彩色图案,通常我们更多地称之为花纹.对于花纹而言,就是在物体表面绘出彩色花 ...

  3. VTK笔记-图形相关-圆锥体-vtkConeSoure类

    圆锥体 文章目录 圆锥体 前言 一.代码 1.1流程 二.遇到的问题 1.运行时异常 2.在ThinkPad E530C笔记本上出现的异常 3.运行结果 三.相机旋转 四.vtkConeSource ...

  4. VTK笔记——医学图像的切片提取(vtkImageReslice)

    医学图像的浏览和内部分析是很常见也很重要的功能,我们不仅可以从矢状面.冠状面和轴状面这样的切面去看,还可以从任意切面去看.在VTK术语中,切面(切片)就是图像数据. vtkImageReslice v ...

  5. python输入数字翻译成星期几-Python练习笔记——计算输入日期为改年的第几天、星期几...

    # 输入年月日,如:1995年12月10日,计算是该年的第几天? # 同时计算出当天是星期几? print("请依据提示依次输入您想查询的年 月 日") # 第一段代码块(年月日输 ...

  6. VTK笔记-相机vtkCamera-投影方式与裁剪范围

    投影方式中物体在View上的投影位置   在之前对多边形数据进行裁剪时<VTK笔记-裁剪分割-不规则闭合圈选裁剪-vtkImplicitSelectionLoop类>,显示的下图的效果:在 ...

  7. python aop编程_学习笔记: AOP面向切面编程和C#多种实现

    AOP:面向切面编程   编程思想 OOP:一切皆对象,对象交互组成功能,功能叠加组成模块,模块叠加组成系统 类--砖头     系统--房子 类--细胞     系统--人 面向对象是非常适合做大型 ...

  8. PyTorch学习笔记(六)——Sequential类、参数管理与GPU

    系列文章\text{\bf 系列文章}系列文章 PyTorch学习笔记(一)--Tensor的基础语法 PyTorch学习笔记(二)--自动微分 PyTorch学习笔记(三)--Dataset和Dat ...

  9. Kotlin 学习笔记(八)—— Kotlin类与对象之接口

    Kotlin 学习笔记(八)-- Kotlin类与对象之接口 Kotlin学习笔记系列教程 Kotlin 学习笔记(一)-- 概述.学习曲线.开发工具.参考资料 Kotlin 学习笔记(二)-- 基础 ...

最新文章

  1. python实现录音并去燥_Python实现电脑录音(含音频基础知识讲解)
  2. linux网络工程师证书,网络工程师应该考什么证
  3. python function if yield_Python中的yield关键字
  4. Packet Tracer 5.0建构CCNA实验攻略(3)——Cisco VTP
  5. python compileall 打包发布
  6. apache iotdb_Apache-IoTDB
  7. jzoj6801-NOIP2020.9.19模拟patrick【树状数组】
  8. 修改终端服务器的最大连接数
  9. 如何通过 Python 和 OpenCV 实现目标数量监控?
  10. vueweb端响应式布局_响应式网站和PC+手机端网站有什么区别?
  11. css列名不动_利用js+css+html实现固定table的列头不动
  12. 【论文笔记】视频分类系列 Appearance-and-Relation Networks for Video Classification (ARTNet)
  13. 万圣节奇妙夜,不给糖就捣蛋—Python带你点击解锁恐怖新道具(南瓜头、骷髅、蝙蝠、糖......)
  14. 基于深度学习的检测和阶段分级优化糖尿病视网膜病变的诊断
  15. ElasticSearch 从5.6.3升级到7.9.3遇到问题总结
  16. MATLAB机器人机械臂运动学正逆解、动力学建模仿真与轨迹规划
  17. 计算机扫描变文档,原来电脑上的扫描仪功能这么好用!纸质文档轻松转为电子格式...
  18. 已知三点求平面方程、平面法向量和点到平面的距离
  19. 区块链学习笔记4——BTC实现
  20. HTMLCSS简单学习,看这篇就够了!

热门文章

  1. 网络管理与维护期末复习
  2. PHP 编写留言板
  3. php空间搭建tcshare,宝塔面板搭建 TCShare 天翼云盘 API 目录列表程序
  4. 云计算的那些事之存储虚拟化
  5. 图片中的文字打码,公章打码
  6. 如何用python在mysql上创建1亿条数据
  7. 鸿蒙系统有没有hicar,华为智选车载智慧屏将12月上市:有望搭载鸿蒙系统
  8. C#编写Rtf文档,中文与字母区分,C#将汉字转换成GBK编码
  9. 如何使用条件格式突出显示Google表格中的行
  10. 【SLAM入门】概率机器人中的一些重要概念(1)