加入实验室后,经过张老师的介绍,有幸与某公司合共共同完成某个项目,在此项目中我主要负责的是三维 pdf 报告生成、Dicom图像上亮度、对比度调整以及 Dicom图像三维重建。今天主要介绍一下完成Dicom图像三维重建的过程以及自己的心得体会。实现Dicom三维图像重建最主要用的VTK(Visualization Toolkit,也就是可视化工具包),由于今天的主题不是有关VTK,所以有关VTK的学习(包括VTK介绍、使用、实列),可以参考此链接:https://blog.csdn.net/wishchin/article/details/12996693,个人建议:先把此教程中的前3个章节看完之后,在看此教程,这样能够更好的理解程序。接下来就让我们进入正题。

VTK将在可视化过程中经常遇到的细节屏蔽起来,并封装了一些常用的可视化算法,如将面绘制中常用的MC(MarchingCubes)算法和体绘制中常用的光线投射(Ray-Casting)算法封装成类的形式提供给使用者。这样在进行医学体数据的可视化时就可以直接使用VTK中已提供的相关类

整个项目的代码以及挂在GitHub上:https://github.com/tgpcai/Dicom_3D_Reconstruction,觉得哈不错的可以给楼主点一个start~


0.三维可视化的两种方式

(1)简单点说,三维可视化的目的就是让人们从屏幕上看到三维图像中有什么东西。众所周知,二维图像的显示是容易的,但是三维图像却不一样。过去由于技术的限制,得到了三维图像的数据,只能把它以二维图像的切片的形式展示给人看,这样显然不够直观。随着计算机科学的发展,使用计算机图形学技术为三维物体建模并实时渲染,实现场景漫游变成显示三维物体的主流方法,而过去切片显示的方式则逐渐被边缘化。

(2)由计算机图形学的知识我们可以知道,想显示三维图像中的内容,可以对这个“内容”的表面建立一个三角形网格模型。一旦得到了这个三角网格,那么渲染它就能够在屏幕上看到想要的内容,同时可以调节视角进行全方位的观察。所以第一类三维可视化方法就是基于这种思想:首先建立网格模型,之后渲染网格。这种方式被称为面绘制。

(3)还有一种叫做体绘制的方式,是直接将三维图像的体素点通过一定的透明度叠加计算后直接对屏幕上的像素点着色。这种方式的特点是能更加清楚的表现体数据内部细节,但是这种算法一般对计算机的压力也会比较大。

1.基于面绘制的MC算法

(0)首先基于MC的一系列算法需要明确一个“体元(Cell)”的概念。体元是在三维图像中由相邻的八个体素点组成的正方体方格,MarchingCubes算法的Cube的语义也可以指这个体元。注意区别体元和体素,体元是8个体素构成的方格,而每个体素(除了边界上的之外)都为8个体元所共享。

(1)面绘制:面绘制是采用分割技术对一系列的二维图像进行轮廓识别、提取等操作,最终还原出被检测物体的三维模型,并以表面的方式显示出来。

(2)面绘制实现三维重建。使用的是经典的 Marching Cubes 算法,也叫移动立方体法。

(3)采用面绘制,VTK中的数据流如下:source->filter(MC算法或者vtkContourFilter)->mapper->actor->render->renderwindow->interactor。

(4)MC算法简介:

  • 首先,假定原始数据是离散的三维空间规则数据场,(断层扫描仪CT及核磁共振仪MRI产生的图像均属于这一类型),读取这些数据,可得出这些数据的三个维度。
  • 其次,以体元为单位来寻找三维图像中内容部分与背景部分的边界,在体元抽取三角片来拟合这个边界。
  • 再者,遍历所有的体元,找出其中的三角片最后集合起来组成图像中实点表面的三角网格(Mesh)。
  • 最后,建立好了三角形网格模型,对该模型进行渲染。

(5)VTK提供了两种提取等值面的类:vtkContourFilter滤波器和封装了MC(Marching Cubes)算法类vtkMarchingCubes。提取等值面之后的数据处理:通过vtkPolyDataNormals在等值面上产生法向量;通过vtkStripper在等值面上产生纹理或三角面片。

(6)利用MC算法提取等值面的代码实现:

 import vtk
# source->filter(MC算法)->mapper->actor->render->renderwindow->interactor # 读取Dicom数据,对应source
v16 = vtk.vtkDICOMImageReader()
# v16.SetDirectoryName('D:/dicom_image/V')
v16.SetDirectoryName('D:/dicom_image/vtkDicomRender-master/sample') # 利用封装好的MC算法抽取等值面,对应filter
marchingCubes = vtk.vtkMarchingCubes()
marchingCubes.SetInputConnection(v16.GetOutputPort())
marchingCubes.SetValue(0, 100) # 剔除旧的或废除的数据单元,提高绘制速度,对应filter
Stripper = vtk.vtkStripper()
Stripper.SetInputConnection(marchingCubes.GetOutputPort()) # 建立映射,对应mapper
mapper = vtk.vtkPolyDataMapper()
# mapper.SetInputConnection(marchingCubes.GetOutputPort())
mapper.SetInputConnection(Stripper.GetOutputPort()) # 建立角色以及属性的设置,对应actor
actor = vtk.vtkActor()
actor.SetMapper(mapper)
# 角色的颜色设置
actor.GetProperty().SetDiffuseColor(1, .94, .25)
# 设置高光照明系数
actor.GetProperty().SetSpecular(.1)
# 设置高光能量
actor.GetProperty().SetSpecularPower(100) # 定义舞台,也就是渲染器,对应render
renderer = vtk.vtkRenderer() # 定义舞台上的相机,对应render
aCamera = vtk.vtkCamera()
aCamera.SetViewUp(0, 0, -1)
aCamera.SetPosition(0, 1, 0)
aCamera.SetFocalPoint(0, 0, 0)
aCamera.ComputeViewPlaneNormal() # 定义整个剧院(应用窗口),对应renderwindow
rewin = vtk.vtkRenderWindow() # 定义与actor之间的交互,对应interactor
interactor = vtk.vtkRenderWindowInteractor() # 将相机添加到舞台renderer
renderer.SetActiveCamera(aCamera)
aCamera.Dolly(1.5) # 设置交互方式
style = vtk.vtkInteractorStyleTrackballCamera()
interactor.SetInteractorStyle(style) # 将舞台添加到剧院中
rewin.AddRenderer(renderer)
interactor.SetRenderWindow(rewin) # 将角色添加到舞台中
renderer.AddActor(actor) # 将相机的焦点移动至中央,The camera will reposition itself to view the center point of the actors,
# and move along its initial view plane normal
renderer.ResetCamera() interactor.Initialize()
interactor.Start()

结果如下:

(7)利用vtkContourFilter滤波器提取等值面的代码实现:

  1 # 抽取轮廓(等值面)的操作对象是标量数据。
2 # 其思想是:将数据集中标量值等于某一指定恒量值的部分提取出来。对于3D的数据集而言,产生的是一个等值面;对于2D的数据集而言,产生的是一个等值线。
3 # 其典型的应用有气象图中的等温线、地形图中的等高线。对于医学数据而言,不同的标量值代表的是人体的不同部分,因而可以分别提取出人的皮肤或骨头。
4 # 抽取轮廓的功能是由一个过滤器实现的,如vtkContourFilter、vtkMarchingCubes。vtkContourFilter可以接受任意数据集类型作为输入,因而具有 一般性。
5 # 使用vtkContourFilter 时,除了需要设置输入数据集外,还需要指定一个或多个用于抽取的标量值。可用如下两种方法进行设置。
6 #
7 # 使用方法SetValue()逐个设置抽取值。该方法有个两个参数:第一个参数是抽取值的索引号,表示第几个 抽取值。索引号从0开始计数;第二个参数就是指定的抽取值。
8 # 使用方法GenerateValues()自动产生一系列抽取值。该方法有三个参数:第一个参数是抽取值的个数,后面两个参数是抽取值的取值范围。
# coding=utf-8
import vtk # source—filter——mapper——actor——render——renderwindow——interactor
aRenderer = vtk.vtkRenderer() # 渲染器
renWin = vtk.vtkRenderWindow() # 渲染窗口,创建窗口
renWin.AddRenderer(aRenderer) # 渲染窗口
# renWin.Render()
iren = vtk.vtkRenderWindowInteractor() # 窗口交互
iren.SetRenderWindow(renWin) # The following reader is used to read a series of 2D slices(images)
# that compose the volume.Theslicedimensions are set, and the
# pixel spacing.The data Endianness must also be specified.The reader
# uses the FilePrefix in combination with the slice number to construct
# filenames using the format FilePrefix. % d.(In this case the FilePrefix
# is the root name of the file. v16 = vtk.vtkDICOMImageReader()
# v16.SetDirectoryName('D:/dicom_image/V')
v16.SetDirectoryName('D:/dicom_image/vtkDicomRender-master/sample') # An isosurface, or contour value of 500 is known to correspond to the
# skin of the patient.Once generated, a vtkPolyDataNormals filter is
# used to create normals for smooth surface shading during rendering.
skinExtractor = vtk.vtkContourFilter()
skinExtractor.SetInputConnection(v16.GetOutputPort())
skinExtractor.SetValue(0, -10)
# skinExtractor.GenerateValues(2, 100, 110)
skinNormals = vtk.vtkPolyDataNormals()
skinNormals.SetInputConnection(skinExtractor.GetOutputPort())
skinNormals.SetFeatureAngle(60.0)
skinMapper = vtk.vtkPolyDataMapper() # 映射器
skinMapper.SetInputConnection(skinNormals.GetOutputPort())
skinMapper.ScalarVisibilityOff() skin = vtk.vtkActor()
# 设置颜色RGB颜色系统就是由三个颜色分量:红色(R)、绿色(G)和蓝色(B)的组合表示,
# 在VTK里这三个分量的取值都是从0到1,(0, 0, 0)表示黑色,(1, 1, 1)表示白色。
# vtkProperty::SetColor(r,g, b)采用的就是RGB颜色系统设置颜色属性值。
#skin.GetProperty().SetColor(0, 0, 1)
skin.SetMapper(skinMapper) skin.GetProperty().SetDiffuseColor(1, .49, .25) skin.GetProperty().SetSpecular(.5) skin.GetProperty().SetSpecularPower(20) # skin.GetProperty().SetRepresentationToSurface()
# 构建图形的方框
outlineData = vtk.vtkOutlineFilter()
outlineData.SetInputConnection(v16.GetOutputPort())
mapOutline = vtk.vtkPolyDataMapper()
mapOutline.SetInputConnection(outlineData.GetOutputPort())
outline = vtk.vtkActor()
outline.SetMapper(mapOutline)
outline.GetProperty().SetColor(0, 0, 0) # 构建舞台的相机
aCamera = vtk.vtkCamera()
aCamera.SetViewUp(0, 0, -1)
aCamera.SetPosition(0, 1, 0)
aCamera.SetFocalPoint(0, 0, 0)
aCamera.ComputeViewPlaneNormal() # Actors are added to the renderer.An initial camera view is created.
# The Dolly() method moves the camera towards the Focal Point,
# thereby enlarging the image.
aRenderer.AddActor(outline)
aRenderer.AddActor(skin)
aRenderer.SetActiveCamera(aCamera)
# 将相机的焦点移动至中央,The camera will reposition itself to view the center point of the actors,
# and move along its initial view plane normal
aRenderer.ResetCamera()
# aCamera.Dolly(1.5)
# aCamera.Roll(180)
# aCamera.Yaw(60) aRenderer.SetBackground(250, 250, 250)
# renWin.SetSize(640, 480)
# 该方法是从vtkRenderWindow的父类vtkWindow继承过来的,用于设置窗口的大小,以像素为单位。
renWin.SetSize(500, 500)
aRenderer.ResetCameraClippingRange() style = vtk.vtkInteractorStyleTrackballCamera()
iren.SetInteractorStyle(style) iren.Initialize()
iren.Start()

结果如下:

(8)与可视化窗口的交互方式:可以使用鼠标与三维图形交互,比如用鼠标滚轮可以对三维图形放大、缩小;按下鼠标左键不放,然后移动鼠标,可以转动三维图形;按下鼠标左键,同时按下Shift键,移动鼠标,可以移动整个三维图形,等等。其他的功能你也可以试着摸索一下,比如按下Ctrl键时再按鼠标左键;鼠标停留在柱体上,然后按下P键;按一下字母E将关闭窗口。

(9)整个过程的简要总结:

  (a)读取数据以及数据处理:首先,读取切片数据,并将其转换为我们的开发工具VTK所支持的一种数据表达形式(vtkImageData)。我们给CT数据建立的是比较抽象的等值面模型,最后将物理组件与抽象的模型结合在一起来建立对CT 数据的可视化,以帮助用户正确理解数据。利用VTK中的vtkDICOMImageReader 我们可以很方便的读取切片数据。

  (b)提取等值面:接着我们就可以用算法对所读取的数据进行处理了。比如采用的经典MC的面绘制方法,首先利用vtkMarchingCubes 类来提取出某一CT值的等值面(利用vtksetValue()来设置需要提取的值),但这时的等值面其实仍只是一些三角面片,还必须由vtkStripper类将其拼接起来形成连续的等值面。这样就把读取的原始数据经过处理转换为应用数据,也即由原始的点阵数据转换为多边形数据然后由vtkPolyDataMapper将其映射为几何数据,并将其属性赋给窗口中代表它的演员,将结果显示出来。在实际应用中Visualization Toolkit支持多表面重建。我们可以设置多个参数值,提取出多个等值面并同时显示出来,如何设置多个参数值呢?可以通过VTK自带的GenerateValues()函数。常见的比如人体皮肤所对应的value值为500,人体骨骼所对应的value值为1150。

  (c)显示结果:通过前面这些工作,我们基本上已经完成了对数据的读取处理映射等步骤,下面我们就要对数据进行显示了。通常这些步骤也叫做渲染引擎。可以通过调整value值和actor的相应属性达到重建三维图形的不同效果。

最主要就是设置相机,设置actor的相关属性(颜色,亮度,透明度等等)。

2.基于体绘制的 Ray-casting算法

(1)体绘制:体绘制是将三维空间的离散数据直接转换为最后的立体,图像而不必生成中间几何图元(面绘制需要), 其中心思想是为每一个体素指定一个不透明度,并考虑每一个体素对光线的透射、发射和反射作用。

(2)体绘制达到的效果:体绘制的目标是在一副图片上展示空间体细节。举例而言,你面前有一间房子,房子中有家具、家电,站在房子外面只能看到外部形状(类似于面绘制的效果),无法观察到房子的布局或者房子中的物体;假设房子和房子中的物体都是半透明的,这样你就可以同时查看到所有的细节。这就是体绘制所要达到的效果。

(3)体绘制常用的算法:光线投射算法( Ray-casting )、错切 - 变形算法( Shear-warp )、频域体绘制算法( Frequency Domain )和抛雪球算法( Splatting )。其中又以光线投射算法最为重要和通用。

(4)光线投射算法( Ray-casting )原理:从图像平面的每个像素都沿着视线方向发出一条射线,此射线穿过体数据集,按一定步长进行采样,由内插计算每个采样点的颜色值和不透明度,然后由前向后或由后向前逐点计算累计的颜色值和不透明度值,直至光线完全被吸收或穿过物体。该方法能很好地反映物质边界的变化,使用Phong模型,引入镜面反射、漫反射和环境反射能得到很好的光照效果,在医学上可将各组织器官的性质属性、形状特征及相互之间的层次关系表现出来,从而丰富了图像的信息。(借鉴百度百科)

(5)体绘制的原理和面绘制完全不相同。面绘制需要生成中间图元,而体绘制则是直接在原图上进行绘制,内容需求较面绘制小。每切换一个视角需要重新对所有的像素点进行颜色和透明度计算,需要时间比面绘制长。

(6)代码实现基于体绘制的 Ray-casting算法

 # This example reads a volume dataset and displays it via volume rendering(体绘制).

 import vtk
from vtk.util.misc import vtkGetDataRoot # Create the renderer, the render window, and the interactor. The renderer
# draws into the render window, the interactor enables mouse- and
# keyboard-based interaction with the scene.
ren = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin) # The following reader is used to read a series of 2D slices (images)
# that compose the volume. The slice dimensions are set, and the
# pixel spacing. The data Endianness must also be specified. The reader
# usese the FilePrefix in combination with the slice number to construct
# filenames using the format FilePrefix.%d. (In this case the FilePrefix
# is the root name of the file: quarter.) # v16 = vtk.vtkVolume16Reader()
# v16.SetDataDimensions(64, 64)
# v16.SetImageRange(1, 93)
# v16.SetDataByteOrderToLittleEndian()
# v16.SetFilePrefix("D:/dicom_image/headsq/quarter")
# v16.SetDataSpacing(3.2, 3.2, 1.5)
v16 = vtk.vtkDICOMImageReader()
# v16.SetDirectoryName('D:/dicom_image/vtkDicomRender-master/sample')
v16.SetDirectoryName('D:/dicom_image/V') # The volume will be displayed by ray-cast alpha compositing.
# A ray-cast mapper is needed to do the ray-casting, and a
# compositing function is needed to do the compositing along the ray.
volumeMapper = vtk.vtkGPUVolumeRayCastMapper()
volumeMapper.SetInputConnection(v16.GetOutputPort())
volumeMapper.SetBlendModeToComposite() # The color transfer function maps voxel intensities to colors.
# It is modality-specific, and often anatomy-specific as well.
# The goal is to one color for flesh (between 500 and 1000)
# and another color for bone (1150 and over).
volumeColor = vtk.vtkColorTransferFunction()
volumeColor.AddRGBPoint(0, 0.0, 0.0, 0.0)
volumeColor.AddRGBPoint(500, 1.0, 0.5, 0.3)
volumeColor.AddRGBPoint(1000, 1.0, 0.5, 0.3)
volumeColor.AddRGBPoint(1150, 1.0, 1.0, 0.9) # The opacity transfer function is used to control the opacity
# of different tissue types.
volumeScalarOpacity = vtk.vtkPiecewiseFunction()
volumeScalarOpacity.AddPoint(0, 0.00)
volumeScalarOpacity.AddPoint(500, 0.15)
volumeScalarOpacity.AddPoint(1000, 0.15)
volumeScalarOpacity.AddPoint(1150, 0.85) # The gradient opacity function is used to decrease the opacity
# in the "flat" regions of the volume while maintaining the opacity
# at the boundaries between tissue types. The gradient is measured
# as the amount by which the intensity changes over unit distance.
# For most medical data, the unit distance is 1mm.
volumeGradientOpacity = vtk.vtkPiecewiseFunction()
volumeGradientOpacity.AddPoint(0, 0.0)
volumeGradientOpacity.AddPoint(90, 0.5)
volumeGradientOpacity.AddPoint(100, 1.0) # The VolumeProperty attaches the color and opacity functions to the
# volume, and sets other volume properties. The interpolation should
# be set to linear to do a high-quality rendering. The ShadeOn option
# turns on directional lighting, which will usually enhance the
# appearance of the volume and make it look more "3D". However,
# the quality of the shading depends on how accurately the gradient
# of the volume can be calculated, and for noisy data the gradient
# estimation will be very poor. The impact of the shading can be
# decreased by increasing the Ambient coefficient while decreasing
# the Diffuse and Specular coefficient. To increase the impact
# of shading, decrease the Ambient and increase the Diffuse and Specular.
volumeProperty = vtk.vtkVolumeProperty()
volumeProperty.SetColor(volumeColor)
volumeProperty.SetScalarOpacity(volumeScalarOpacity)
# volumeProperty.SetGradientOpacity(volumeGradientOpacity)
volumeProperty.SetInterpolationTypeToLinear()
volumeProperty.ShadeOn()
volumeProperty.SetAmbient(0.9)
volumeProperty.SetDiffuse(0.9)
volumeProperty.SetSpecular(0.9) # The vtkVolume is a vtkProp3D (like a vtkActor) and controls the position
# and orientation of the volume in world coordinates.
volume = vtk.vtkVolume()
volume.SetMapper(volumeMapper)
volume.SetProperty(volumeProperty) # Finally, add the volume to the renderer
ren.AddViewProp(volume) # Set up an initial view of the volume. The focal point will be the
# center of the volume, and the camera position will be 400mm to the
# patient's left (which is our right).
camera = ren.GetActiveCamera()
c = volume.GetCenter()
camera.SetFocalPoint(c[0], c[1], c[2])
camera.SetPosition(c[0] + 400, c[1], c[2])
camera.SetViewUp(0, 0, -1) # Increase the size of the render window
renWin.SetSize(640, 480) # Interact with the data.
iren.Initialize()
renWin.Render()
iren.Start()

结果如下:

(7)体绘制的整个过程包括VTK数据量都与面绘制类似。同样可以通过调整actor的相应属性达到重建三维图形的不同效果,比如通过设置不透明度值来显示体数据内部的不同成分和细节,例如显示人体CT图像的不同器官和组织。

 3.心得体会与总结

(1)其实无论是面绘制还是体绘制都需要一定的VTK知识,所以先了解VTK的一些基础知识才能帮助你更好的掌握这些方法。

(2)有关VTK整个数据流的过程可以用一下的例子进行类比,方便理解(虽然这个类比不是非常形象):

  • 当我们去看舞台剧的时候,我们坐在台下,展现在我们面前的是一个舞台,舞台上有各式的灯光,各样的演员。演员出场的时候肯定是会先化妆,有些演员可能会打扮成高富帅,有些演员可能会化妆成白富美。观众有时还会与台上的演员有一定的互动。
  • 整个剧院就好比VTK程序的渲染窗口(vtkRenderWindow);舞台就相当于渲染场景(vtkRenderer);而那些高富帅、白富美就是我们程序中的Actor(有些文献翻译成“演员”,有些翻译成“角色”,这里我们不作翻译);台上的演员与台下观众的互动可以看成是程序的交互(vtkRenderWindowInteractor);演员与观众的互动方式有很多种,现场的观众可以直接上台跟演员们握手拥抱,电视机前的可以发短信,电脑、移动终端用户等可以微博关注、加粉等等,这就好比我们程序里的交互器样式(vtkInteractorStyle);
  • 舞台上的演员我们都能一一分辨出来,不会把高富帅弄混淆,是因为他们化的妆、穿的服饰都不一样,这就相当于我们程序里vtkActor的不同属性(vtkProperty);台下观众的眼睛可以看作是vtkCamera,前排的观众因为离得近,看台上演员会显得比较高大,而后排的观众看到的会显得小点,每个观众看到的东西在他的世界里都是唯一的,所以渲染场景Renderer里的vtkCamera对象也是只有一个;舞台上的灯光可以有多个,所以渲染场景里的vtkLight也存在多个
  • 如下图所示,可以加深理解

(3)体绘制与面绘制管线上的区别

  • 在面绘制中,用到vtkActor或其子类的例子采用的渲染技术都是几何渲染,即通过绘制几何图元(顶点、线段、面片等)来渲染数据。
  • 首先我们看下几何渲染管线和体绘制渲染管线对比,如下图所示。可以看出,体绘制渲染线和几何渲染线的组成是比较一致的,不同在于:在几何渲染中,通常使用vtkActor来渲染几何图形数据,在体绘制中则使用vtkVolume渲染数据;在几何渲染中,通常采用vtkPolyDataMapper实现输入数据向图元的转换,在体绘制中,则采用vtkVolumeRayCastMapper,这是与体绘制算法有关的,不同的体绘制算法会有不同的Mapper类。

参考文献:https://vtk.org/doc/nightly/html/annotated.html

      http://blog.sina.com.cn/s/blog_5ff6097b0100zz2y.html


以上就是本次学习的内容,欢迎交流与讨论

 

 
 

基于面绘制的MC算法以及基于体绘制的 Ray-casting 实现Dicom图像的三维重建(python实现)的更多相关文章

  1. Mahout实现基于用户的协同过滤算法

    Mahout中对协同过滤算法进行了封装,看一个简单的基于用户的协同过滤算法. 基于用户:通过用户对物品的偏好程度来计算出用户的在喜好上的近邻,从而根据近邻的喜好推测出用户的喜好并推荐. 图片来源 程序 ...

  2. mahout demo——本质上是基于Hadoop的分步式算法实现,比如多节点的数据合并,数据排序,网路通信的效率,节点宕机重算,数据分步式存储

    摘自:http://blog.fens.me/mahout-recommendation-api/ 测试程序:RecommenderTest.java 测试数据集:item.csv 1,101,5.0 ...

  3. 2维FFT算法实现——基于GPU的基2快速二维傅里叶变换

    上篇讲述了一维FFT的GPU实现(FFT算法实现——基于GPU的基2快速傅里叶变换),后来我又由于需要做了一下二维FFT,大概思路如下. 首先看的肯定是公式: 如上面公式所描述的,2维FFT只需要拆分 ...

  4. 最小生成树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind

    最小支撑树树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind 最小支撑树树 前几节中介绍的算法都是针对无权图的,本节将介绍带权图的最小 ...

  5. 基于视觉信息的网页分块算法(VIPS) - yysdsyl的专栏 - 博客频道 - CSDN.NET

    基于视觉信息的网页分块算法(VIPS) - yysdsyl的专栏 - 博客频道 - CSDN.NET 于视觉信息的网页分块算法(VIPS) 2012-07-29 15:22 1233人阅读 评论(1) ...

  6. VIPS:基于视觉的页面分割算法[微软下一代搜索引擎核心分页算法]

    VIPS:基于视觉的页面分割算法[微软下一代搜索引擎核心分页算法] - tingya的专栏 - 博客频道 - CSDN.NET VIPS:基于视觉的页面分割算法[微软下一代搜索引擎核心分页算法] 分类 ...

  7. 基于FPGA的腐蚀膨胀算法实现

    本篇文章我要写的是基于的腐蚀膨胀算法实现,腐蚀膨胀是形态学图像处理的基础,,腐蚀在二值图像的基础上做"收缩"或"细化"操作,膨胀在二值图像的基础上做" ...

  8. 基于FPGA的肤色识别算法实现

    大家好,给大家介绍一下,这是基于FPGA的肤色识别算法实现. 我们今天这篇文章有两个内容一是实现基于FPGA的彩色图片转灰度实现,然后在这个基础上实现基于FPGA的肤色检测算法实现. 将彩色图像转化为 ...

  9. 基于MATLAB的人脸识别算法的研究

    基于MATLAB的人脸识别算法的研究 作者:lee神 现如今机器视觉越来越盛行,从智能交通系统的车辆识别,车牌识别到交通标牌的识别:从智能手机的人脸识别的性别识别:如今无人驾驶汽车更是应用了大量的机器 ...

随机推荐

  1. js spread object

    What’s is the benefit / drawback of these two alternatives? Using object spread options = {...option ...

  2. CRLF

    提示信息: Inject false data in the journalisation log. -------------日志中注入错误数据 开始挑战后,进入如下界面-------------- ...

  3. [Algorithm] 21. Merge Two Sorted Lists

    Merge two sorted linked lists and return it as a new list. The new list should be made by splicing t ...

  4. pipelinewise 学习二 创建一个简单的pipeline

    pipelinewise 提供了方便的创建简单pipeline的命令,可以简化pipeline 的创建,同时也可以帮我们学习 生成demo pipeline pipelinewise init --n ...

  5. 16-网页,网站,微信公众号基础入门(网页版MQTT,页面控件位置调整入门)

    https://www.cnblogs.com/yangfengwu/p/11200767.html 说一下,只要你java学的很好,那么几乎所有的语言都不在话下了 来看一下样式设置 运行 在左上角感 ...

  6. 【题解】洛谷 P1080 国王游戏

    目录 题目 思路 \(Code\) 题目 P1080 国王游戏 思路 贪心+高精度.按\(a \times b\)从小到大排序就可以了. \(Code\) #include<bits/stdc+ ...

  7. 第08组 Alpha事后诸葛亮

    组长博客 点这里! 总结思考 设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 弥补Powerpoint中模板转换存在的缺陷,完善PPT模板一键转换的功能 ...

  8. java8 instant localDateTime

  9. [技术博客]Android 开发 Bug Log

    [技术博客] Android 开发 Bug Log 大大小小的bug,聪明的愚蠢的都有, 持续记录中...... java.lang.IllegalArgumentException: The sty ...

  10. android studio 创建项目的一些配置

    build.gradle文件 apply plugin: 'com.android.application' apply plugin: 'org.greenrobot.greendao' // 使用 ...