python中for循环通过手动更新:跳过i(拆分子序列)

Python 的 for 循环是基于迭代器的,enumerate 会依次提供下一个索引和对应的元素。通过手动操作更新状态(如加入第 7 和第 8 张)并跳过循环中的部分逻辑后,索引会自动递增到未处理的项

例子:拆分子序列

1 [-218.400, -202.000, -54.000]

2 [-218.400, -202.000, -54.625]

3 [-218.400, -202.000, -55.250]

4 [-218.400, -202.000, -55.875]

5 [-218.400, -202.000, -56.500]

6 [-218.400, -202.000, -54.000]

7 [-218.400, -202.000, -59.000]

8 [-218.400, -202.000, -64.000]

9 [-218.400, -202.000, -69.000]
 

import os
import pydicom
import shutil
from collections import defaultdict
import numpy as npdef load_dicom_images(dicom_directory):"""从指定目录加载 DICOM 图像,并提取必要的属性。"""dicom_files = []  # 空列表,用来存储从 DICOM 文件中提取的信息,每个元素是一个字典for root, dirs, files in os.walk(dicom_directory):  # 遍历目录中的所有文件for file in files:try:dicom_path = os.path.join(root, file)  # 构建完整文件路径dicom = pydicom.dcmread(dicom_path)  # 读取 DICOM 文件dicom_files.append({"path": dicom_path,  # 文件路径"instance_number": dicom.get("InstanceNumber", 0),  # 实例编号"image_type": dicom.get("ImageType", []),  # 图像类型"position": np.array(dicom.ImagePositionPatient,dtype=float) if "ImagePositionPatient" in dicom else None,  # 图像位置"orientation": np.array(dicom.ImageOrientationPatient,dtype=float) if "ImageOrientationPatient" in dicom else None,  # 图像方向})except Exception as e:# 如果读取失败,打印错误信息print(f"读取 {file} 失败: {e}")return dicom_filesdef classify_images(dicom_files):"""根据 ImageType 将图像分类为 Localizer 和 Axial。"""localizer_images = []  # 用于存储 Localizer 图像axial_images = []  # 用于存储 Axial 图像for dicom in dicom_files:image_type = dicom["image_type"]  # 获取图像类型if "LOCALIZER" in image_type:  # 如果类型中包含 LOCALIZERlocalizer_images.append(dicom)elif "AXIAL" in image_type or len(dicom_files) > 3:  # 如果类型中包含 AXIAL 或文件总数超过 3axial_images.append(dicom)print(f"Localizer 图像数量: {len(localizer_images)}")print(f"Axial 图像数量: {len(axial_images)}")return localizer_images, axial_imagesdef split_into_subseries(dicom_files, output_directory):"""根据位置差异和方向,将图像划分为子序列,避免不必要的拆分。"""dicom_files.sort(key=lambda x: x["instance_number"])  # 按实例编号排序,确保图像顺序一致subseries = defaultdict(list)  # 用于存储每个子序列current_subseries_index = 0  # 当前子序列的索引previous_position = None  # 上一张图像的位置no_step = None  # 记录正常步长for i, dicom in enumerate(dicom_files):current_position = dicom["position"]  # 当前图像的位置if previous_position is None:  # 如果是第一张图像previous_position = current_position  # 初始化上一张图像的位置subseries[current_subseries_index].append(dicom)  # 添加到当前子序列continue# 计算当前图像与上一张图像之间的步长step = np.linalg.norm(current_position - previous_position)if no_step is None:  # 如果尚未初始化步长no_step = step  # 初始化步长elif abs(step - no_step) > 0.01:  # 判断是否为新子序列的条件# 创建一个新的子序列current_subseries_index += 1subseries[current_subseries_index].append(dicom)# 判断是否需要将接下来的两张图像归入当前子序列if i + 2 < len(dicom_files):  # 确保至少有两张图像可以检查next_position = dicom_files[i + 1]["position"]  # 下一张图像的位置next_next_position = dicom_files[i + 2]["position"]  # 再下一张图像的位置# 计算步长step_1 = np.linalg.norm(next_position - current_position)  # 当前到下一张的步长step_2 = np.linalg.norm(next_next_position - next_position)  # 下一张到再下一张的步长# 比较步长差异if abs(step_1 - step_2) < 0.01:  # 如果步长差异较小# 将两张图像都归入当前子序列subseries[current_subseries_index].append(dicom_files[i + 1])subseries[current_subseries_index].append(dicom_files[i + 2])# 更新位置变量以跳过这些图像current_position = next_next_position  # 更新为再下一张的位置previous_position = current_position  # 同步上一张位置no_step = step_2  # 更新步长为新的步长continue  # 跳过本次循环,直接处理后续图像# 如果步长变化大,更新步长no_step = stepelse:# 如果步长在阈值范围内,将图像添加到当前子序列subseries[current_subseries_index].append(dicom)# 更新上一张图像的位置previous_position = current_positionprint(f"拆分成的子序列总数: {len(subseries)}")# 将每个子序列保存到对应的输出目录for index, images in subseries.items():subseries_path = os.path.join(output_directory, f"subseries_{index + 1}")os.makedirs(subseries_path, exist_ok=True)  # 确保目录存在for dicom in images:dicom_basename = os.path.basename(dicom["path"])  # 获取文件名output_path = os.path.join(subseries_path, dicom_basename)  # 构建输出路径shutil.copy(dicom["path"], output_path)  # 复制文件到目标目录def main(dicom_directory, output_directory):# 加载 DICOM 图像dicom_files = load_dicom_images(dicom_directory)# 将图像分类为 Localizer 和 Axiallocalizer_images, axial_images = classify_images(dicom_files)# 分别处理 Localizer 和 Axial 图像的子序列创建print("正在处理 Localizer 图像...")if localizer_images:localizer_output = os.path.join(output_directory, "Localizer")os.makedirs(localizer_output, exist_ok=True)  # 确保输出目录存在split_into_subseries(localizer_images, localizer_output)print("正在处理 Axial 图像...")if axial_images:axial_output = os.path.join(output_directory, "Axial")os.makedirs(axial_output, exist_ok=True)  # 确保输出目录存在split_into_subseries(axial_images, axial_output)print(f"子序列已保存至 {output_directory}")# 示例用法
dicom_directory = 'D:/Users/LX9999/Desktop/CT-jiao-553/CT-JIAO SHAN XUE-20241118'
output_directory = 'D:/Users/LX9999/Desktop/CT-jiao-553/553-1-output'
main(dicom_directory, output_directory)

核心点:for 循环的机制

在 Python 中,for i, dicom in enumerate(dicom_files) 是基于一个迭代器工作的:

  • 每次循环都会从 dicom_files 中获取下一个元素,同时更新索引 i
  • continue 只跳过当前循环的剩余部分,并不会直接修改循环索引 i

真正影响跳过逻辑的代码:

关键在 手动修改状态和 continue 结合迭代器的自动递增,具体看这一段代码:

if abs(step_1 - step_2) < 0.01:# 如果差异较小,将两张图像都加入当前序列subseries[current_subseries_index].append(dicom_files[i + 1])subseries[current_subseries_index].append(dicom_files[i + 2])# 更新位置变量current_position = dicom_files[i + 2]["position"]previous_position = current_positionno_step = step_2# 跳过后续两张图像的逻辑部分continue

拆解逻辑:跳过的关键点

  1. 手动操作的核心:dicom_files[i + 1] 和 dicom_files[i + 2]

    • 在处理第 6 张图像时,代码手动读取了 第 7 张和第 8 张 的数据:
      subseries[current_subseries_index].append(dicom_files[i + 1])
      subseries[current_subseries_index].append(dicom_files[i + 2])
      
    • 这意味着程序已经 主动处理 了第 7 张和第 8 张,因此在逻辑上跳过了它们。
  2. continue 的作用:

    • continue 不会跳过两次迭代
    • 它只是结束当前循环,直接进入下一次迭代。
    • 当循环进入下一次迭代时,enumerate 会根据其内部逻辑自动更新索引 i
  3. enumerate 的索引自增:

    • 在处理第 6 张图像时,i = 5
    • 下一次迭代时,enumerate 的索引会自动更新为 6,即对应 第 7 张图像
  4. 为什么跳过了第 7 和第 8 张?

    • 虽然 i = 6 时,程序会进入第 7 张图像,但此时程序已经提前 手动处理过第 7 张和第 8 张
    • 由于第 7 和第 8 张已经包含在当前序列,接下来的逻辑无需重复处理它们。
    • 于是,循环继续处理 第 9 张图像i = 8)。

跳过的效果是如何实现的?

跳过的 效果 并不是直接修改索引 i,而是通过以下逻辑 间接跳过

  1. 手动处理了第 7 和第 8 张
    • 在 if abs(step_1 - step_2) < 0.01 条件下,将第 7 张和第 8 张加入序列,已经明确它们的归属。
  2. 循环索引自然递增
    • 即便 enumerate 会尝试递增索引,程序的主逻辑中已经不需要处理第 7 和第 8 张。
  3. 更新位置变量并 continue
    • 更新了 current_position 和 previous_position 为第 8 张的位置:
      current_position = dicom_files[i + 2]["position"]
      previous_position = current_position
      
    • 这些变量控制了后续逻辑,使得程序能够顺利进入第 9 张的处理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/19349.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

基于SpringBoot的“致远汽车租赁系统”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“致远汽车租赁系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 致远汽车租赁系统总体功能模块图 系统首页界面…

DSP28335 DMA 官方例程解析以及拓展(一)

文章目录 概述官方例程1 内部RAM to RAM Example_2833xDMA_ram_to_ram源码解析 要点方法拓展 外部固定地址 TO RAM完整程序: 对DMA 和 DMA有关的API请看这篇文章 DSP28335 DMA API介绍 概述 本篇主要分析官方提供的28335 DMA 有关的例程 在此基础上有一定的拓展 官方例程1 内…

【Java SE】JDBC

JDBC&#xff08;Java DataBase Connectivity&#xff09;是一套用于在 Java 中操作关系型数据库的 API。它允许开发者使用统一的 Java 代码来访问不同的关系型数据库。 JDBC 的本质&#xff1a;JDBC 是由官方&#xff08;Sun 公司&#xff09;定义的一套接口规范&#xff0c;…

西电数据库课设|设计学籍管理系统

前言&#xff1a;ER图和逻辑结构图不准确&#xff0c;因为在后期实际建表的过程中有改动&#xff0c;去除了一些列和外键关系&#xff0c;但是我懒得返回去改图了&#xff0c;所以还是需要自己情况画图&#xff0c;还有学生信息我忘记加性别什么的&#xff0c;这个比较简单&…

优维HAO案例:500强旗下全牌照综合性券商CMDB平台项目

撰文&#xff1a;鹿小U / 制图&#xff1a;脾气超好 某中国500强集团旗下的HS公司&#xff0c;是一家具有一定行业影响力的综合性证券公司。在近年来的发展进程中&#xff0c;该公司坚定不移地持续推进财富管理转型工作&#xff0c;将 ETF 的财富管理以及机构经纪业务作为公司…

github进不去解决办法-误打误撞进去了

我的要求不高&#xff0c;就算麻烦&#xff0c;只要能进去就行&#xff0c;但是我找了很多的办法&#xff0c;xbox下载助手、watt Toolkit、更改host文件、fastgithub…最终还是没有用 绝望之际随便进了一个当时找的fastgithub连接 结果显示不是专用链接 然后看了该博主的文章…

RHCE——WEB服务器的部署及优化

URL组成 <scheme>://<user>:<password><host>:<port>/<path>:<params>?<query>#<frag> scheme 方案 访问服务器以获取资源时要使用哪种协议 user 用户 某些方案访问资源时需要的用户名 pass…

day03(单片机高级)RTOS

目录 RTOS(实时操作系统) 裸机开发模式 轮询方式 前后台&#xff08;中断方式&#xff09; 改进&#xff08;前后台&#xff08;中断&#xff09;&#xff09;定时器 裸机进一步优化 裸机的其他问题 RTOS的概念 什么是RTOS 为什么要使用 RTOS RTOS的应用场景 RTOS的…

基于SSM的毕业论文管理系统【附源码】

基于SSM的毕业论文管理系统&#xff08;源码L文说明文档&#xff09; 目录 4 系统设计 4.1 系统结构设计 4.2 系统顺序图设计 4.3 系统数据库设计 5 系统的实现 5.1 登录模块的实现 5.2 学生管理模块的实现 5.3 导师管理模块的实现 5.4 课题管理模块的实现 …

擎耀数字车灯CAN/LIN总线网络定向数据采集控制解决方案实施流程

2024年是数字车灯崛起的元年&#xff0c;随着车辆的智能化和网络化程度不断提高&#xff0c;车载网络系统&#xff08;如CAN总线&#xff09;成为连接各个电子控制单元&#xff08;ECU&#xff09;的重要纽带。车灯作为车辆重要的安全组件之一&#xff0c;其工作状态直接影响到…

【C++之STL】摸清 string 的模拟实现(上)

文章目录 1. 为什么要模拟实现&#xff1f;2. 基本框架搭建3. 构造函数3. 1 默认构造/from c_str3. 2 拷贝构造3. 2. 1 深浅拷贝 3. 3 fill3. 4 迭代器区间构造 4. 容量操作4. 1 size()和capacity()和empty()4. 2 clear()4. 3 resize()4. 4 reserve() 1. 为什么要模拟实现&…

视频直播5G CPE解决方案:ZX7981PG/ZX7981PMWIFI6网络覆盖

方案背景 视频直播蓬勃发展的当下&#xff0c;传统直播网络联网方式的局限性越来越明显。目前传统直播的局限性主要集中在以下几个方面&#xff1a; 传统直播间网络架构条件有限&#xff0c;可连接WIFI数量少&#xff0c;多终端同时直播难以维持&#xff1b;目前4G网络带宽有限…

input file结合vue3和vant实现上传图片效果,并显示上传进度百分比%

这里写自定义目录标题 采用的dom结构是input file&#xff0c;label事件绑定&#xff0c;一下为代码传入参数为uploadNum实现效果如图上传中&#xff0c;图片1上传成功&#xff0c;图片2 采用的dom结构是input file&#xff0c;label事件绑定&#xff0c;一下为代码 传入参数为…

SELECT 语句详解

开发准备 注:如果你是从上一节直接进入本节进行学习的,请先删除上一节建立的数据库mysql_shiyan,删除语句为DROP DATABASE mysql_shiyan;。在正式开始本实验内容之前,需要先下载相关数据库表,搭建好一个名为mysql_shiyan 的数据库(有三张表:department,employee,projec…

重力传感器算法概述!

一、核心技术 高精度重力测量技术&#xff1a; 无人机重力传感器的核心技术之一是能够高精度地测量重力加速度数据。这通常依赖于先进的传感器设计和制造工艺&#xff0c;以确保传感器具有高度的灵敏度和稳定性。 例如&#xff0c;中国船舶第七〇七研究所自主研发的低空重力…

炼码LintCode--数据库题库(级别:中等;数量:更新中~)--刷题笔记_03

目录 炼码LintCode--数据库题库&#xff08;级别&#xff1a;中等&#xff1b;数量&#xff1a;更新中~&#xff09;--刷题笔记_033617 更换连续两个人的座位&#xff08;case when&#xff09;题&#xff1a;sql&#xff1a;解释&#xff1a; 3615 数据中位数&#xff08;窗…

【stm入门学习SPI_铁头山羊系列教程】

stm入门学习SPI_铁头山羊教程 1.SPI总线1.电路结构与通信协议2.SPI的特点&#xff1a;3. 极性 相位4. 4中时钟模式5. 比特位的传输模式6.数据宽度 2. SPI引脚IO引脚初始化 1.SPI总线 1.电路结构与通信协议 主机向从机NSS引脚发送低电压&#xff0c;选中该从机。 主机通过向MOS…

RK3568平台开发系列讲解(platform虚拟总线驱动篇)实验:点亮一个LED

🚀返回专栏总目录 文章目录 一、设备树二、平台驱动三、应用沉淀、分享、成长,让自己和他人都能有所收获!😄 📢xxx 程序编写的主要内容为添加 LED 灯的设备树节点、在驱动程序中使用 of 函数获取设备节点中的属性,编写测试应用程序。 • 首先向设备树添加 LED 设备节点…

Spring Boot 与腾讯云 MySQL 监听 Binlog 数据变化,并使用 UI 展示页面效果

引言 在现代的分布式系统和微服务架构中&#xff0c;数据同步和变更监控是保证系统一致性和实时性的核心问题之一。MySQL 数据库的 binlog&#xff08;二进制日志&#xff09;功能能够记录所有对数据库的修改操作&#xff0c;如插入&#xff08;INSERT&#xff09;、更新&…

菜鸟驿站二维码/一维码 取件识别功能

特别注意需要引入 库文 ZXing 可跳转&#xff1a; 记录【WinForm】C#学习使用ZXing.Net生成条码过程_c# zxing-CSDN博客 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using static System.Net.…