当前位置: 首页 > news >正文

VTK编程指南<十二>:VTK图像数据结构及图像创建与显示

  数字图像是一种重要的多媒体数据,广泛应用于工业生产、生物医学、地质、气象等重要领域。数字图像处理技术具有重要的应用价值。图像是VTK里非常重要的一种数据结构。本章重点讲解VTK在数字图像处理应用方面的相关技术。

1、VTK图像数据结构

  数字图像文件内容由两个部分组成:图像头信息和数据。图像头信息定义了图像的基本
信息,主要包括起点位置(Origin)、像素间隔(Space)和维数(Dimension)。通过这三个参数即可确定图像空间位置和大小。图像可以看作空间中的一个规则的网格,网格中的每个最小单元称为像素(二维)或者体素(三维),网格在每个方向上的像素或者体素个数即为图像在该方向的维数。像素索引表示每个像素在图像网格中的位置,是图像内部的网格坐标。

  在医学图像中,每个图像除了内部坐标外,还存在一个世界坐标,这个世界坐标依赖于成像设备。在医学图像中,起点位置、像素间隔和图像维数决定了世界坐标系。这样通过起点位置、像素间隔和像素索引即可计算每个像素的世界坐标。

  图5-1表示一个4x2x3体素的图像,即图像的维数,每一个小球表示一个像素;而图像的原点为(5.1,10.0,6.5),两个像素之间的间隔表示像素间隔,每个方向的像素间隔分别为1.5、1.5 和1.8。
在这里插入图片描述

  图像数据即为图像像素的像素值,一般采用一维数组来表示和存储。已知像素索引和图像维数的情况下,即可计算每个像素对应的像素值。通常图像的像素值为一个标量,例如灰度图像;图像像素值也可以是一个矢量,例如梯度图像;另外,图像像素值还可以是张量,如弥散张量成像(Diffusion Tensor Imaging,DTI)。医学图像处理中经常使用的是灰度图像。

  这里需要注意:灰度图像像素或者体素的数据类型在一般的灰度图像处理中不需要考虑因为其范围默认为0~255,可以采用一个unsigned char类型来表示。但是在医学图像处理中,256灰度级远远不能满足要求,因此灰度范围往往大于256级。

  常见医学图像的像素数据类型为 unsigned short,灰度范围为 0~65536。另外,有时为了精度的考虑,也会使用 int、float或者 double 类型,因此需要格外注意。由前面章节内容可知,VTK 中图像数据结构由 vtkImageData 类表示。利用 vtkImageData可以方便地创建、读写和访问图像数据。下面以VTK图像创建为起点,一步步走进VTK图像处理的世界。

2、VTK图像创建

2.1 VTK图像源 Source

  VTK中内置了多个创建图像的 Source 类,利用这些 Source 类可以快速创建图像。这里以vtkImageCanvasSource2D为代表进行说明。该Source类的功能是创建一个画布(空白图像),并提供了多种几何图形(点、线段、圆、矩形以及图像等)的绘制填充功能。
在这里插入图片描述

#include <iostream>#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);// VTK was built with vtkRenderingOpenGL2
VTK_MODULE_INIT(vtkInteractionStyle);#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkImageCanvasSource2D.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkRenderer.h>
#include <vtkImageActor.h>int main()
{vtkSmartPointer<vtkImageCanvasSource2D> canvas =vtkSmartPointer<vtkImageCanvasSource2D>::New();canvas->SetScalarTypeToUnsignedChar();canvas->SetNumberOfScalarComponents(3);canvas->SetExtent(0, 400, 0, 400, 0, 0);canvas->SetDrawColor(255, 0, 0.0);canvas->FillBox(0, 100, 0, 100);canvas->Update();canvas->SetDrawColor(0, 255, 0.0);canvas->FillBox(100, 200, 100, 200);canvas->Update();// Create actorsvtkSmartPointer<vtkImageActor> redActor =vtkSmartPointer<vtkImageActor>::New();redActor->SetInputData(canvas->GetOutput());// Define viewport ranges// (xmin, ymin, xmax, ymax)double redViewport[4] = { 0.0, 0.0, 1.0, 1.0 };// Setup renderersvtkSmartPointer<vtkRenderer> redRenderer =vtkSmartPointer<vtkRenderer>::New();redRenderer->SetViewport(redViewport);redRenderer->AddActor(redActor);redRenderer->ResetCamera();redRenderer->SetBackground(0.2, 0.2, 0.2);// Setup render windowvtkSmartPointer<vtkRenderWindow> renderWindow =vtkSmartPointer<vtkRenderWindow>::New();renderWindow->AddRenderer(redRenderer);renderWindow->SetSize(480, 480);renderWindow->Render();renderWindow->SetWindowName("ImageCanvasSource2D");// Setup render window interactorvtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =vtkSmartPointer<vtkRenderWindowInteractor>::New();vtkSmartPointer<vtkInteractorStyleImage> style =vtkSmartPointer<vtkInteractorStyleImage>::New();renderWindowInteractor->SetInteractorStyle(style);// Render and start interactionrenderWindowInteractor->SetRenderWindow(renderWindow);renderWindowInteractor->Initialize();renderWindowInteractor->Start();return EXIT_SUCCESS;
}

  上面的代码片段中,先定义了一个vtkImageCanvasSource2D对象,然后设置画布的像素数据类型、像素组分数目和画布的大小;然后,利用画布的FiIlIBox()方法在画布中绘制两个矩形,并通过画布的 SetDrawColor()方法来设置两个矩形的颜色。

  除了vtkImageCanvasSource2D 外,VTK还提供了其他类似的Source 类来快速生成特定的图像,例如vtkImageEllipsoidSource,该类根据指定的中心以及各个轴的半径来生成一个前景为椭圆(球)的二值像;vtkImageGaussianSource 类生成一幅像素值服从高斯分布的图像vtkImageGridSource 用于生成网格线图像;vtkImageNoiseSource 生成一个像素值为随机数的噪声像。vtkImageSinusoidSource 生成的图像像素值由正弦函数决定。

2.2 直接创建图像

  利用上述图像Source可以快速地生成特定的图像,但是实际应用中它们用到得较少。VTK中可以手动生成图像,然后根据需要进行像素赋值。
在这里插入图片描述

#include <iostream>#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);// VTK was built with vtkRenderingOpenGL2
VTK_MODULE_INIT(vtkInteractionStyle);#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkImageActor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkRenderWindow.h>
#include <vtkType.h>int main()
{vtkSmartPointer<vtkImageData> img = vtkSmartPointer<vtkImageData>::New();img->SetDimensions(16, 16, 1);// 分配标量数据,并设置数据类型为VTK_UNSIGNED_CHARimg->AllocateScalars(VTK_UNSIGNED_CHAR, 1);unsigned char* ptr = (unsigned char*)img->GetScalarPointer();for (int i = 0; i < 16 * 16 * 1; i++){*ptr++ = i % 256;}vtkSmartPointer<vtkImageActor> redActor =vtkSmartPointer<vtkImageActor>::New();redActor->SetInputData(img);double redViewport[4] = { 0.0, 0.0, 1.0, 1.0 };vtkSmartPointer<vtkRenderer> redRenderer =vtkSmartPointer<vtkRenderer>::New();redRenderer->SetViewport(redViewport);redRenderer->AddActor(redActor);redRenderer->ResetCamera();redRenderer->SetBackground(1.0, 1.0, 1.0);vtkSmartPointer<vtkRenderWindow> renderWindow =vtkSmartPointer<vtkRenderWindow>::New();renderWindow->AddRenderer(redRenderer);renderWindow->SetSize(640, 480);renderWindow->Render();renderWindow->SetWindowName("CreateVTKImageData");vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =vtkSmartPointer<vtkRenderWindowInteractor>::New();vtkSmartPointer<vtkInteractorStyleImage> style =vtkSmartPointer<vtkInteractorStyleImage>::New();renderWindowInteractor->SetInteractorStyle(style);renderWindowInteractor->SetRenderWindow(renderWindow);renderWindowInteractor->Initialize();renderWindowInteractor->Start();return EXIT_SUCCESS;
}

  先定义 vtkImageData 对象,然后指定图像的维数,而图像的原点和像素间隔则都是采用默认值,因此不需要设置。SetScalarTypeToUnsignedChar()指定图像的像素数据类型为 unsigned
char,SetNumberOfScalarComponents()则指定每个像素值的组分数为 1,即每个像素值为1个标量值。参数设置完毕,调用 AllocateScalars()分配内存,生成图像数据。图像生成后,默认所有像素值为 0。可以通过访问图像数据数组来设置每个像素值,vtkImageData:: GetScalarPointer()即返回图像的数据数组(图像数据数组采用一维数组,参考本书3.6节的内容),然后根据图像的大小,访问每个像素并为其赋值。

3、VTK图像显示

3.1 vtkImageViewer2

  VTK早期的版本提供了vtkImageViewer 类来显示图像,随着版本的发展,目前使用vtkImageViewer2来代替vtkImageViewer 实现图像的显示。vtkImageViewer2 中封装了VTK图像显示的可视化渲染引擎,包括vtkActor、vtkRender、vtkRenderWindow、vtkInteractorStypeImage等对象,可以方便地完成图像显示和交互。该类提供的主要交互操作有图像放缩、窗宽窗位调节,并提供切片选择及切片方向设置接口,尤其适合三维图像的切片显示。下述代码说明了使vtkImageViewer2显示图像的方法。

在这里插入图片描述

#include <iostream>#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);// VTK was built with vtkRenderingOpenGL2
VTK_MODULE_INIT(vtkInteractionStyle);#include <vtkSmartPointer.h>
#include <vtkImageViewer2.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkMetaImageReader.h>//测试图像:../data/brain.mhd
int main(int argc, char* argv[])
{std::string sFile = "../data/brain.mhd";vtkSmartPointer<vtkMetaImageReader> reader =vtkSmartPointer<vtkMetaImageReader>::New();reader->SetFileName(sFile.c_str());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 EXIT_SUCCESS;
}

  这里为了更好地演示vtkImageViewer2的功能,以一幅三维医学图像为例进行说明。首先使用 vtkMetalmageReader 读入一个*.mhd 格式的图像,然后定义vtkImageViewer2 对象显示图像。为了实现鼠标、键盘消息响应,定义vtkRenderWindowInteractor 对象,并通过vtkImageViewer2::SetInteractor()设置交互对象。最后设置了窗位(ColorLevel)、窗宽(ColorWindow)、切片索引(Slice)和切片方向(Orientation)等参数。

  在渲染窗口中,按下鼠标左键拖动鼠标,可以调节图像的窗宽窗位,从而显示不同灰度范围内容;按下鼠标右键拖动鼠标可以缩放图像。当然,这些交互操作可以由用户根据需要自己定义vtkInteractorStyle子类,并响应相应的操作。

1.窗宽/窗位的概念
  窗宽是图像显示的灰度范围。一般显示器的灰度范围为256级,而医学图像的灰度范围则远远大于该范围,因此通过显示器显示时不能显示所有灰度级,需要使用窗宽来定义欲显示的灰度范围。当灰度值高于该范围的最大值时,均以白影显示;当低于该范围时,均以黑色显示。若增大窗宽,则显示具有不同灰度值的组织结构增多,但是会降低组织之间的对比度,若减小窗宽,则可视的不同灰度组织结构会减少,同时增大组织结构的对比度。

  窗位是窗宽的中心位置(见图5-5)。窗宽只是确定了CT图像灰度范围上的可视部分范围,还需要窗位来确定可视灰度范围的具体位置。同样的窗宽,会根据窗位的位置变化来显示不同的组织结构。比如,窗宽为200,当窗位为100时,可视灰度范围为0-200:当窗位为500时,可视灰度范围为400~600。当窗宽窗位确定以后,显示时底层会将可视灰度范围转换到256灰度级进行显示。
在这里插入图片描述

2.医学图像二维视图
  切片(Slice)或切面是三维图像比较常用的概念,尤其在医学图像中,不同方向的切面
都有特定的名字(见图5-6),分别是:矢状面(Sagital Plane),沿着身体前后径所做的与地面垂直的切面;冠状面(Coronal Plane),沿着身体左右径所做的与地面垂直的切面:横断面(Transverse/AxialPlane),是指横断身体与地面平行的切面。设置切片的方向即是通过不同的方向来观察人体内部组织结构。
在这里插入图片描述
  常见的医学图像可视化软件通常会提供四个视图用来显示图像:横断面视图、矢状面视图、冠状面视图和三维视图,例如图5-7所示的视图是来自德国癌症研究中心的MITK3M3医学图像处理软件。
在这里插入图片描述

  类vtkImageViewer2提供了SetSlice()函数来设置切片索引,SetSliceOrientationToXY()则将切片的方向设置为垂直XY平面方向。此外还可以设置为垂直YZ或者XZ平面方向,其对应函数分别为SetSliceOrientationToYZ(和 SetSliceOrientationToXZ()。默认情况下切片方向为垂直于XY平面即沿着乙轴方向,根据设置的切片索引获取乙轴方向的具体切片进行显示。

3.2 vtkImageActor

  vtkImageActor 是一个三维图像渲染Actor,通过纹理映射将图像映射到一个多边形上进行显示。使用vtkImageActor 较vtkImageViewer2 要复杂一些,需要建立完整的渲染管线:包括 vtkImageActor、vtkRender、vtkRenderWindow 和 vtkRenderWindowInteractor。另外,作为二
维图像浏览器,不需要在三维空间中进行旋转操作,因此还需要为vtkRenderWindowlInteractor
定义一个vtkInteractorStylelmage 对象。下例中使用vtkImageActor 建立图像渲染管线来显示图
像并实现交互功能。
在这里插入图片描述

#include <iostream>#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);// VTK was built with vtkRenderingOpenGL2
VTK_MODULE_INIT(vtkInteractionStyle);#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(int argc, char* argv[])
{std::string sFile = "../data/lena.bmp";vtkSmartPointer<vtkBMPReader> reader =vtkSmartPointer<vtkBMPReader>::New();reader->SetFileName(sFile.c_str());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 EXIT_SUCCESS;
}

4、VTK图像融合

  前面介绍的两种显示图像的方法都是在窗口中显示一幅图像。在实际应用中经常需要在窗口中同时显示多幅图像,这就会用到图像融合技术。图像融合是利用图像的不透明度来合
成图像。在VTK中,用类vtkImageBlend实现图像的融合。vtkImageBlend 可以接收多个图像输入,其输出为融合图像。输出图像的像素间隔、原点、范围以及像素组分个数与第一个图像一致。该类提供了两种融合模式。

  第一种是标准模式,也是默认的融合方式。第二种是混合模式(Compound)。该模式下输出结果利用不透明度的和做归一化。当像素的不透明度 alpha*opacity 小于或等于阈值 threshold 时,该像素会被忽略。

在这里插入图片描述

#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include <vtkImageCanvasSource2D.h>
#include <vtkImageBlend.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>
#include <vtkRenderer.h>
#include <vtkJPEGReader.h>
#include <vtkImageActor.h>
#include <vtkImageCast.h>#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);// VTK was built with vtkRenderingOpenGL2
VTK_MODULE_INIT(vtkInteractionStyle);//测试图像:../data/lena-gray.jpg
int main(int argc, char* argv[])
{std::string sFile = "../data/lena-gray.jpg";vtkSmartPointer<vtkJPEGReader> reader =vtkSmartPointer<vtkJPEGReader>::New();reader->SetFileName (sFile.c_str());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();vtkSmartPointer<vtkImageBlend> imageBlend = vtkSmartPointer<vtkImageBlend>::New();imageBlend->AddInputData(reader->GetOutput());imageBlend->AddInputData(imageSource->GetOutput());imageBlend->SetOpacity(0, 0.4);imageBlend->SetOpacity(1, 0.6);imageBlend->Update();// Create actorsvtkSmartPointer<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());// Define viewport ranges// (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};// Setup renderersvtkSmartPointer<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);vtkSmartPointer<vtkRenderWindow> renderWindow =vtkSmartPointer<vtkRenderWindow>::New();renderWindow->AddRenderer(originalRenderer1);renderWindow->AddRenderer(originalRenderer2);renderWindow->AddRenderer(blendRenderer);renderWindow->SetSize( 640, 320 );renderWindow->Render();renderWindow->SetWindowName("ImageBlendExample");vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =vtkSmartPointer<vtkRenderWindowInteractor>::New();vtkSmartPointer<vtkInteractorStyleImage> style =vtkSmartPointer<vtkInteractorStyleImage>::New();renderWindowInteractor->SetInteractorStyle(style);renderWindowInteractor->SetRenderWindow(renderWindow);renderWindowInteractor->Initialize();renderWindowInteractor->Start();return EXIT_SUCCESS;
}

该示例中先读入一幅灰度图像,另外生成一个二值图像;然后定义了vtkImageBlend 对象,SetInput()函数设置两个图像作为输入。这里设置输入图像时,由于可以输入多个图像,因此需要给定图像的id号来设置输入。SetOpacity()函数用于设置对应id号的图像不透明度的大小,当不透明度为1.0时,为完全不透明。

相关文章:

VTK编程指南<十二>:VTK图像数据结构及图像创建与显示

数字图像是一种重要的多媒体数据&#xff0c;广泛应用于工业生产、生物医学、地质、气象等重要领域。数字图像处理技术具有重要的应用价值。图像是VTK里非常重要的一种数据结构。本章重点讲解VTK在数字图像处理应用方面的相关技术。 1、VTK图像数据结构 数字图像文件内容由两个…...

EasyGBS国标GB28181平台P2P远程访问故障排查指南:客户端角度的排查思路

在现代视频监控系统中&#xff0c;P2P&#xff08;点对点&#xff09;技术因其便捷性和高效性而被广泛应用。然而&#xff0c;当用户在使用P2P远程访问时遇到设备不在线或无法访问的问题时&#xff0c;有效的排查方法显得尤为重要。本文将从客户端的角度出发&#xff0c;详细探…...

打造智慧医院挂号枢纽:SSM 与 Vue 融合的系统设计与实施

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…...

网络编程 02:IP 地址,IP 地址的作用、分类,通过 Java 实现 IP 地址的信息获取

一、概述 记录时间 [2024-12-18] 前置文章&#xff1a;网络编程 01&#xff1a;计算机网络概述&#xff0c;网络的作用&#xff0c;网络通信的要素&#xff0c;以及网络通信协议与分层模型 本文讲述网络编程相关知识——IP 地址&#xff0c;包括 IP 地址的作用、分类&#xff…...

如何使用Python WebDriver爬取ChatGPT内容(完整教程)

大背景 虽然我们能用网页版chatGPT来聊天、写文章&#xff0c;但是我们采集大量的内容&#xff0c;就得不断地手动输入提问来获取答案&#xff0c;并且将结果复制到数据库来保存。如果整个过程能使用程序来做自然要节省很多的人力&#xff0c;精力和时间。 Python webdirver …...

WSL切换默认发行版

查看适用于wsl的子系统有哪些: wslconfig /list 设置wsl的默认发行版 wslconfig /setdefault Ubuntu-20.04...

全志H618 Android12修改doucmentsui功能菜单项

背景: 由于当前的文件管理器在我们的产品定义当中,某些界面有改动的需求,所以需要在Android12 rom中进行定制以符合当前产品定义。 需求: 在进入File文件管理器后,查看...功能菜单时,有不需要的功能菜单,需要隐藏,如:新建窗口、不显示的文件夹、故代码分析以及客制…...

移动网络(2,3,4,5G)设备TCP通讯调试方法

背景&#xff1a; 当设备是移动网络设备连接云平台的时候&#xff0c;如果服务器没有收到网络数据&#xff0c;移动物联设备发送不知道有没有有丢失数据的时候&#xff0c;需要一个抓取设备出来的数据和服务器下发的数据的方法。 1.服务器系统是很成熟的&#xff0c;一般是linu…...

网络安全概论——入侵检测系统IDS

一、入侵检测的概念 1、入侵检测的概念 检测对计算机系统的非授权访问对系统的运行状态进行监视&#xff0c;发现各种攻击企图、攻击行为或攻击结果&#xff0c;以保证系统资源的保密性、完整性和可用性识别针对计算机系统和网络系统或广义上的信息系统的非法攻击&#xff0c…...

Linux通信System V:消息队列 信号量

Linux通信System V&#xff1a;消息队列 & 信号量 一、信号量概念二、信号量意义三、操作系统如何管理ipc资源&#xff08;2.36版本&#xff09;四、如何对信号量资源进行管理 一、信号量概念 信号量本质上就是计数器&#xff0c;用来保护共享资源。多个进程在进行通信时&a…...

计算机网络基础图解

注&#xff1a;本文为来自 猿小许 的 “计算机网络” 相关系列文章合辑。 一、计算机网络概述 猿小许于 2021-06-03 18:39:47 发布 一、计算机网络的概念 1.1 计算机网络 概念 计算机网络&#xff1a; 是一个将分散的、具有独立功能的计算机系统&#xff0c;通过通信设备与…...

TDesign:NavBar 导航栏

NavBar 导航栏 左图&#xff0c;右标 appBar: TDNavBar(padding: EdgeInsets.only(left: 0,right: 30.w), // 重写左右内边距centerTitle:false, // 不显示标题height: 45, // 高度titleWidget: TDImage( // 左图assetUrl: assets/img/logo.png,width: 147.w,height: 41.w,),ba…...

hive注释comment中文乱码解决

问题描述 当使用以下命令查看表的元数据信息时出现中文乱码&#xff08;使用的是idea连接hive&#xff09; desc formatted test.t_archer; 解决 连接保存hive元数据的MySQL数据库&#xff0c;执行以下命令&#xff1a; use hive3; show tables;alter table hive3.COLUMNS_…...

电脑提示ntdll.d缺失是什么原因?不处理的话会怎么样?ntdll.dll文件缺失快速解决方案来啦!

电脑提示ntdll.dll缺失&#xff1a;原因、影响与解决方案 在日常的电脑使用中&#xff0c;我们偶尔会遇到一些令人困惑的系统错误&#xff0c;其中“ntdll.dll缺失”便是较为常见的一种。作为软件开发从业者&#xff0c;我深知这一错误给用户带来的不便&#xff0c;因此&#…...

MFC/C++学习系列之简单记录——序列化机制

MFC/C学习系列之简单记录——序列化机制 前言简述六大机制序列化机制使用反序列化总结 前言 MFC有六大机制&#xff0c;分别是程序启动机制、窗口创建机制、动态创建机制、运行时类信息机制、消息映射机制、序列化机制。 简述六大机制 程序启动机制&#xff1a;全局的应用程序…...

二十、服务发布Ingress

Ingress Kubernetes使用了一个Ingress策略定义和一个具体提供转发服务的Ingress Controller,两者结合,实现了基于灵活Ingress策略定义的服务路由功能。如果是对Kubernetes集群外部的客户端提供服务,那么IngressController实现的是类似于边缘路由器(Edge Router)的功能。需…...

计算机网络 八股青春版

什么是HTTP&#xff1f;HTTP和HTTPS的区别 HTTP HTTP是超文本运输协议&#xff0c;是一种无状态&#xff08;每次请求都是独立的&#xff09;的应用层协议。用于在客户端和服务器之间传输超文本数据&#xff08;如HTML文件&#xff09;。默认端口是80数据以明文形式传输&#…...

java全栈day18--Web后端实战(java操作数据库2)

前言&#xff1a;在上节入门程序当中我们见到了JDBC所提供的API&#xff0c;本节来详细说明一下。 一、JDBC--API详解 1.1DriverManager&#xff08;驱动管理器&#xff09; 回顾&#xff1a;作用获取连接&#xff0c;调用它里面的getConnection。即如下 作用 1.注册驱动解…...

electron-vite【实战】自定义标题栏【组件封装】(含异形标题栏,指定区域拖拽,窗口置顶,窗口最小化,窗口最大化,取消最大化,隐藏窗口到托盘等)

效果预览 技术要点 透明背景 src/main/index.ts 的 new BrowserWindow 中添加 transparent: true, // 设置窗口背景透明frame: false, // 隐藏窗口边框仅图标和标题部分可拖拽 仅图标和标题部分添加样式 drag .drag {-webkit-app-region: drag; }图标与标题栏的融合 标题栏的…...

vue2 项目webpack 4升5

项目背景 公司项目需要将进行微前端改造.主应用和子应用会需要共享依赖,考虑使用模块联邦进行依赖共享. 由于模块联邦要升级到webpack 5才能用,所以老项目要从webpack 4升级到webpack 5 实现思路 原来的项目用的是vue-cli 3,查了一下可以vue-cli 5用的就是webpack 5,所以可以…...

KubeSphere 容器平台高可用:环境搭建与可视化操作指南

Linux_k8s篇 欢迎来到Linux的世界&#xff0c;看笔记好好学多敲多打&#xff0c;每个人都是大神&#xff01; 题目&#xff1a;KubeSphere 容器平台高可用&#xff1a;环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

基础测试工具使用经验

背景 vtune&#xff0c;perf, nsight system等基础测试工具&#xff0c;都是用过的&#xff0c;但是没有记录&#xff0c;都逐渐忘了。所以写这篇博客总结记录一下&#xff0c;只要以后发现新的用法&#xff0c;就记得来编辑补充一下 perf 比较基础的用法&#xff1a; 先改这…...

解决本地部署 SmolVLM2 大语言模型运行 flash-attn 报错

出现的问题 安装 flash-attn 会一直卡在 build 那一步或者运行报错 解决办法 是因为你安装的 flash-attn 版本没有对应上&#xff0c;所以报错&#xff0c;到 https://github.com/Dao-AILab/flash-attention/releases 下载对应版本&#xff0c;cu、torch、cp 的版本一定要对…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

OPENCV形态学基础之二腐蚀

一.腐蚀的原理 (图1) 数学表达式&#xff1a;dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一&#xff0c;腐蚀跟膨胀属于反向操作&#xff0c;膨胀是把图像图像变大&#xff0c;而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...