在此感谢Manjunath KN的回答,参考链接如下:https://www.researchgate.net/post/How_to_create_a_simple_project_to_convert_DICOM_images_to_3d_images

2D to 3D

1.需要的信息
将2D坐标转换为3D坐标需要以下DICOM信息2D:

  • input point (x,y):原始的2D坐标
  • Image position patient (0020, 0032):ImageOrientation
  • Pixel spacing (0028, 0030):PixelSpacing
  • Row vector and column vectors (0020,0037):ImageOrientation

DICOM 提取示例代码如下:

def getinfo(img_file):RefDs = dicomio.read_file(img_file)# print(dir(RefDs))  #查看dicom文件的属性img_array = RefDs.pixel_array# indexes are z,y,x ImagePosition =np.array(RefDs.ImagePositionPatient)ImageOrientation=np.array(RefDs.ImageOrientationPatient)PixelSpacing =RefDs.PixelSpacingSliceThickness=RefDs.SliceThicknessImageOrientationX=ImageOrientation[0:3]ImageOrientationY=ImageOrientation[3:6]#z轴(X与Y的叉积)normalvector=np.cross(ImageOrientationX,ImageOrientationY)return img_array,normalvector,ImagePosition,PixelSpacing,ImageOrientationX,ImageOrientationY

2.转换过程

Voxel (x, y, z) = Image Plane Position + Row change in X + column change in Y
Where Row change in X = Row vector * Pixel size in X direction * 2D Point location in X direction
Column change in Y = Column vector * Pixel size in Y direction * 2D Point location in Y direction

示例:
Image position patient = (100,100,50) #ImagePositionPatient
row vector=(1,0,0) #ImageOrientationX
column vector=(0,1,0) #ImageOrientationY
pixel size=(0.5,0.5) #PixelSpacing
2D point=(5,6)

Voxel (x,y,z) = (100,100, 50) + (1,0,0) * 0.5 *5 + (0,1,0)0.5 6 = (100,100,50) + (2.5,0,0)+ (0,3,0) = (102.5, 103, 50)

3.将2d平面转换到3d空间原理
这里主要是解释下文代码中 “建立方程组:dx(x-a)+dy(y-b)+dz(z-c)=0”的原理:

(1)dx(x-a)+dy(y-b)+dz(z-c)=0
我们在高中学过空间平面的几种表达方式,比如有点法式、一般式等等。其中点法式最常用的就是A(x-x0)+B(y-y0)+C(z-z0)=0。这里的含义很好理解,假设向量vN=(A,B,C)是平面的法向量,然后取平面任一点p0=(x0,y0,z0)【带入上面式子等于零,说明该点在平面上】。所谓的空间平面,就是任一点pX与点p0链接的直线(pX,p0)与法向量vN内积和等于零。也就是A(x-x0)+B(y-y0)+C(z-z0)=0。这里做了简化,即写成dx(x-a)+dy(y-a)+dz(z-a)=0的意思是直接取(dx,dy,dz)就是法向量的x,y,z三个方向的分量。相当于是吧法向量(A,B,C)进行了归一化处理。
(2)ImageOrientationX即X轴的方向,ImageOrientationY即Y轴方向
图像平面的长,宽方向的方向余弦向量其实就是归一化后的方向向量,叉乘获得的就是平面的法向量,每个分量就是dx,dy,dz。
(3)关于dicon中的左边系可参考博客
https://blog.csdn.net/zssureqh/article/details/61636150

4.两个2d平面投影到3d空间并求得交线

def getIntersection(f1=None,f2=None,path=None):#get infoimg_array1,normalvector1, ImagePosition1,PixelSpacing1,ImageOrientationX1,ImageOrientationY1= getinfo(f1)img_array2,normalvector2, ImagePosition2,PixelSpacing2,ImageOrientationX2,ImageOrientationY2 = getinfo(f2)# 设置 并设置符号变量sp.init_printing(use_unicode=True)InteractiveShell.ast_node_interactivity = 'all'x, y, z = symbols('x, y, z')#建立方程组#dx(x-a)+dy(y-b)+dz(z-c)=0z1=[normalvector1[0] * (x - ImagePosition1[0]) + normalvector1[1] * (y - ImagePosition1[1]) ] /normalvector1[2] + ImagePosition1[2]z2 = [normalvector2[0] * (x - ImagePosition2[0]) + normalvector2[1] * (y - ImagePosition2[1])] / normalvector2[2] + \ImagePosition2[2]eq=[normalvector1[0] * (x - ImagePosition1[0]) + normalvector1[1] * (y - ImagePosition1[1]) + normalvector1[2] * (z - ImagePosition1[2]),\normalvector2[0] * (x - ImagePosition2[0]) + normalvector2[1] * (y - ImagePosition2[1]) + normalvector2[2] * (z - ImagePosition2[2])]#解方程s = list(linsolve(eq, [x, y]))# show_3d(normalvector1, ImagePosition1,normalvector2,ImagePosition2,s)

在3d空间展示平面

def show_3d(normalvector1,ImagePosition1,normalvector2,ImagePosition2,s):# 3d空间交线的表达式x1_3d = s[0][0]y1_3d = s[0][1]x, y, z = symbols('x, y, z')fig = plt.figure()ax = Axes3D(fig)# 生成x,y的网格数据X = np.arange(-256, 256, 1)# Y = np.arange(-4, 4, 0.25)Y = np.arange(-256, 256, 1)X, Y = np.meshgrid(X, Y)Z1=(normalvector1[0]* (X - ImagePosition1[0]) + normalvector1[1]* (Y - ImagePosition1[1]))/ normalvector1[2] + ImagePosition1[2]Z2 = (normalvector2[0] * (X - ImagePosition2[0]) + normalvector2[1] * (Y - ImagePosition2[1])) / normalvector2[2] +  ImagePosition2[2]# show linea1,a2=x1_3d.coeff(z),y1_3d.coeff(z)b1,b2=x1_3d.coeff(z,0),y1_3d.coeff(z,0)zi = np.linspace(-250, 256, 100)xi=a1*zi+b1yi=a2*zi+b2ax.plot3D(xi,yi,zi)ax.plot_surface(X, Y, Z1, rstride=1, cstride=1, color='r')#cmap='rainbow'ax.plot_surface(X, Y, Z2, rstride=1, cstride=1, color="g")plt.show()

3D to 2D

1.原理
Conversion from 3D to 2D
Difference = Voxel – Image plane Pos;
Difference_in_X = Difference.Innerproduct(Row vector)
Difference_in_Y = Difference.Innerproduct(Col vector);
2D Point = (Difference_in_X/pixel size in X, Differnce_in_Y/pixel size in Y)

这是所涉及的基本逻辑。上述方程组也可以通过矩阵乘法来实现。请参阅第410页,DICOM,章节PS 3.3,2011年版本,或者在文件http://dicom.nema.org/medical/dicom/current/output/pdf/part03.pdf中搜索标签0020,0037

2.代码
(1)3d 空间的交线投影到对应的2D平面

def TO2D(s,ImagePosition,ImageOrientationX,ImageOrientationY,PixelSpacing):# s为3d空间交线的表达式x, y, z = symbols('x, y, z')x1_3d = s[0][0]y1_3d = s[0][1]pos=[x1_3d,y1_3d,z]differ=pos-ImagePositiondiffer_x=np.dot(differ,ImageOrientationX)differ_y=np.dot(differ,ImageOrientationY)pos_2d=[differ_x/PixelSpacing[0],differ_y/PixelSpacing[1]]return pos_2d

利用DICOM文件实现2D与3D体素坐标之间的转换相关推荐

  1. 动态文件、2d、3d、Html设置电脑桌面背景【超实用】

    LivelyWallpaper是一个非常棒的电脑桌面背景设置软件,可用url.html.图片.2d.3d等文件设置为win10桌面背景,且cpu占用极低. 一.下载: 1.https://www.mi ...

  2. 闪存颗粒-2D和3D闪存之间的区别和联系

    转载:http://ssd.zol.com.cn/625/6254456.html 首先是2D NAND,我们知道在数学和物理领域,2D/3D都是指的方向,都是指的坐标轴,"2D" ...

  3. 自学Python第二十二天- Django框架(三) AJAX、文件上传、POST 请求类型之间的转换、多APP开发、iframe、验证码、分页器、类视图、中间件、信号、日志、缓存、celery异步

    Django官方文档 django 使用 AJAX django 项目中也可以使用 ajax 技术 前端 前端和其他 web 框架一样,需要注意的是,django 接收 POST 请求时,需要 csr ...

  4. react中使用jszip获取压缩包里文件的方法、Blob与Flie之间的转换

    react中jszip获取压缩包里的文件方法: // react里通过npm install jszip安装 import JSZip from 'jszip'const zip = new JSZi ...

  5. CSS3之2D与3D转换

    在CSS3中新增了很多关于2D和3D转换的标准,它允许将页面元素在2D和3D空间内进行移动.缩放.旋转.倾斜等.所谓的2D转换,指的是元素可以在平面内进行位置或形状的转换,而3D转换指的是元素可以在三 ...

  6. 2D转3D技术的优势

    从传统电影出现到目前为止,已经积累了大量的2D的电影,2D转3D可以让2D影片绽放3D的魅力.在3D电影的制作中,由于拍摄上物理的限制,很多特殊的镜头是拍摄不出正确的3D效果,和得不到需要的3D艺术效 ...

  7. 《Android多媒体应用开发实战详解:图像、音频、视频、2D和3D》——2.3节简析Android安装文件...

    本节书摘来自异步社区<Android多媒体应用开发实战详解:图像.音频.视频.2D和3D>一书中的第2章,第2.3节简析Android安装文件,作者 王石磊 , 吴峥,更多章节内容可以访问 ...

  8. 利用Python绘制 3D 体素色温图

    简 介: 测试了Matplotlib中的 体素绘制函数 voxels() ,但是无论是在 AI Studio中执行,还是直接在本地执行,都会出了错误.也就是无法通过 gca(projection='3 ...

  9. 【WPF学习手记】利用fo-dicom读取DICOM文件

    利用开源库 fo-dicom 读取 DICOM 文件基本操作. 读取DICOM信息 原始数据经过窗宽.窗位校正后显示成图. private void Button_Click1(object send ...

最新文章

  1. 2022-2028年中国椎间孔镜行业市场研究及前瞻分析报告
  2. ThreadLocal 简介
  3. SpringBoot集成全局异常处理
  4. 银行柜员网申计算机水平要求高吗,银行网申没通过,是因为你水平差吗?
  5. 11g新特性-自动sql调优(Automatic SQL Tuning)
  6. 文末送书 | 数据分析简单入门
  7. 【job】面试中常见的笔试梳理
  8. 金蝶K3退出远程桌面后,客户端无法登陆
  9. paypalsdk集成php,php核心paypal sdk
  10. linux 文件名加粗,konsole与用粗体绘制强调色
  11. 解决Linux系统下字体没有宋体和黑体问题
  12. h5在线游戏制作开发:h5模板打地鼠小游戏怎么制作?
  13. 英特尔cpu发布时间表_英特尔10代桌面cpu上市时间(英特尔10代发售时间)
  14. 页面中设置IE浏览器的文档模式
  15. 远程工具MobaXterm安装和使用教程
  16. sim卡没坏但苹果手机无服务_工信部为啥要喊你设置SIM卡密码?如何设置(安卓苹果都有了)|工信部|手机|安卓|安卓手机|iphone...
  17. 快速学习一门新技术的工作原理(十步学习法来自软技能)
  18. galera-mariadb集群
  19. “已连接,但无法访问互联网”开机后wifi有感叹号, 时间无法同步解决办法
  20. 【ubuntu】htop命令详解

热门文章

  1. Rose Blumki
  2. (附源码)springboot社区养老医疗服务平台 毕业设计 041148
  3. Allure报告的安装及环境变量的配置和在pytest中调用
  4. 3ds Max发生闪退怎么办?
  5. 电脑ctrl和ALT经常键自动按住--答案是QQ2012的Bug
  6. 解决npm ERR! Unexpected end of JSON input while parsing near的方法汇总
  7. OSPF中双ASBR重发布5类LSA问题
  8. wordpress主题转html,WordPress主题的 HTML静态页面模板制作教程
  9. 每日一面 - java里的wait()和sleep()的区别有哪些?
  10. JDBC实现多条件查询万能解决思路