做网站是那个语言写的,公司建设网站费用属于什么费用吗,网站如何做反爬,免费网站建设图书下载Python数据处理入门
常用库学习
numpy
NumPy#xff08;Numerical Python#xff09; 是 Python 中用于高效数值计算的库#xff0c;核心是提供一个强大的 ndarray#xff08;多维数组#xff09;对象#xff0c;类似于 C/C 中的数组#xff0c;但支持更丰富的操作Numerical Python 是 Python 中用于高效数值计算的库核心是提供一个强大的 ndarray多维数组对象类似于 C/C 中的数组但支持更丰富的操作比如切片、广播、线性代数等。
基本用法
import numpy as np创建数组
a np.array([1, 2, 3]) # 一维数组
b np.array([[1, 2], [3, 4]]) # 二维数组print(a) # [1 2 3]
print(b) # [[1 2]# [3 4]]说明使用 np.array() 可以把列表或嵌套列表转换为 NumPy 数组。查看数组形状和属性
print(a.shape) # (3,) → 一维数组3个元素
print(b.shape) # (2, 2) → 2行2列print(b.ndim) # 2 → 二维数组
print(b.dtype) # int64 → 元素类型常用数组创建方法
print(np.zeros((2, 3))) # 全0数组
# [[0. 0. 0.]
# [0. 0. 0.]]print(np.ones((2, 2))) # 全1数组
# [[1. 1.]
# [1. 1.]]print(np.eye(3)) # 单位矩阵
# [[1. 0. 0.]
# [0. 1. 0.]
# [0. 0. 1.]]print(np.arange(0, 5, 1)) # 等差数组[0 1 2 3 4]
print(np.linspace(0, 1, 5)) # 等间距[0. 0.25 0.5 0.75 1.]数组运算
a np.array([1, 2, 3])
b np.array([4, 5, 6])print(a b) # [5 7 9]
print(a - b) # [-3 -3 -3]
print(a * 2) # [2 4 6]
print(a ** 2) # [1 4 9]说明NumPy 支持逐元素运算不需要写循环。数组统计函数
a np.array([1, 2, 3, 4])print(np.sum(a)) # 总和10
print(np.mean(a)) # 平均数2.5
print(np.max(a)) # 最大值4
print(np.min(a)) # 最小值1
print(np.std(a)) # 标准差数组索引和切片
a np.array([[10, 20, 30],[40, 50, 60]])print(a[0, 1]) # 第1行第2列 → 20
print(a[1]) # 第2行 → [40 50 60]
print(a[:, 0]) # 第1列 → [10 40]说明二维数组使用 a[行, 列] 方式访问。形状变换
a np.arange(6) # [0 1 2 3 4 5]
b a.reshape((2, 3)) # 改成2行3列print(b)
# [[0 1 2]
# [3 4 5]]广播机制自动对齐维度
a np.array([[1, 2], [3, 4]])
b np.array([10, 20])print(a b)
# [[11 22]
# [13 24]]说明b 自动扩展为二维数组 [10, 20]重复到每一行。矩阵乘法 vs 元素乘法
a np.array([[1, 2],[3, 4]])
b np.array([[5, 6],[7, 8]])print(a * b) # 元素乘法
# [[ 5 12]
# [21 32]]print(np.dot(a, b)) # 矩阵乘法
# [[19 22]
# [43 50]]数组条件筛选
a np.array([1, 2, 3, 4, 5])
print(a[a 3]) # [4 5]复制与原地修改
a np.array([1, 2, 3])
b a.copy() # 深拷贝不影响原数组
b[0] 99print(a) # [1 2 3]
print(b) # [99 2 3]pandas
PandasPython Data Analysis Library 是 Python 中用于 数据分析与处理 的核心库提供了强大的 DataFrame 和 Series 两种数据结构适用于结构化数据表格、Excel、数据库的读取、清洗、分析、可视化等。
基本用法
import pandas as pd创建 Series一维数据
s pd.Series([10, 20, 30, 40])
print(s)
# 0 10
# 1 20
# 2 30
# 3 40
# dtype: int64说明Series 是带标签的一维数组默认索引为 0 开始的整数。创建 DataFrame二维表格
data {name: [Alice, Bob, Charlie],age: [25, 30, 35],city: [NY, LA, Chicago]}df pd.DataFrame(data)
print(df)
# name age city
# 0 Alice 25 NY
# 1 Bob 30 LA
# 2 Charlie 35 Chicago说明DataFrame 是 Pandas 的核心表格型结构类似于 Excel 表。查看数据基本信息
print(df.shape) # (3, 3) → 3行3列
print(df.columns) # 列名Index([name, age, city], dtypeobject)
print(df.index) # 行索引RangeIndex(start0, stop3, step1)
print(df.dtypes) # 每列的数据类型读取常见文件
# 读取 CSV 文件
df pd.read_csv(data.csv)# 读取 Excel 文件
df pd.read_excel(data.xlsx)# 保存为 CSV 文件
df.to_csv(output.csv, indexFalse)访问列与行
print(df[name]) # 访问单列Series
print(df[[name, age]]) # 多列DataFrameprint(df.loc[0]) # 按标签访问第1行
print(df.iloc[1]) # 按位置访问第2行说明loc 用标签iloc 用索引位置。条件筛选
print(df[df[age] 28])
# 筛选出 age 28 的行添加、修改与删除列
df[salary] [5000, 6000, 7000] # 添加新列print(df[age] * 2) # 修改方式表达式df.drop(city, axis1, inplaceTrue) # 删除列缺失值处理
df pd.DataFrame({name: [Alice, Bob, None],age: [25, None, 35]
})print(df.isnull()) # 判断是否为空
print(df.dropna()) # 删除含缺失值的行
print(df.fillna(0)) # 填充缺失值分组与聚合
df pd.DataFrame({dept: [IT, HR, IT, HR],salary: [6000, 5000, 7000, 5500]
})print(df.groupby(dept).mean())
# 按部门求平均工资排序与唯一值
print(df.sort_values(salary, ascendingFalse)) # 按工资降序
print(df[dept].unique()) # 唯一值合并与拼接
df1 pd.DataFrame({id: [1, 2], name: [Alice, Bob]})
df2 pd.DataFrame({id: [1, 2], score: [90, 85]})print(pd.merge(df1, df2, onid)) # 按 id 合并应用函数与映射
df[age_group] df[age].apply(lambda x: adult if x 30 else young)
print(df)说明使用 apply() 可以对每个元素应用函数。导出结果
df.to_csv(result.csv, indexFalse)
df.to_excel(result.xlsx, indexFalse)json
jsonJavaScript Object Notation 是一种轻量级的数据交换格式Python 内置了 json 模块来方便地进行 JSON 数据的解析和生成常用于数据持久化、前后端通信等场景。
基本用法
import jsonPython 与 JSON 的对应关系Python 类型JSON 类型dictobjectlist、tuplearraystrstringint/floatnumberTrue/Falsetrue / falseNonenull
Python 转 JSON 字符串序列化
data {name: Alice, age: 25, is_student: False}
json_str json.dumps(data)print(json_str)
# {name: Alice, age: 25, is_student: false}说明json.dumps() 可以把 Python 对象转换为 JSON 字符串。JSON 字符串转 Python 对象反序列化
json_str {name: Alice, age: 25, is_student: false}
data json.loads(json_str)print(data)
# {name: Alice, age: 25, is_student: False}说明json.loads() 可以把 JSON 字符串解析为 Python 对象。序列化时格式化输出
data {name: Bob, scores: [90, 85, 88]}
print(json.dumps(data, indent2))
# {
# name: Bob,
# scores: [
# 90,
# 85,
# 88
# ]
# }说明通过 indent 参数可控制缩进增加可读性。中文处理
data {name: 小明, age: 18}
print(json.dumps(data, ensure_asciiFalse))
# {name: 小明, age: 18}说明默认中文会转成 Unicode用 ensure_asciiFalse 可以保留中文。写入 JSON 文件
data {title: Python, level: beginner}with open(data.json, w, encodingutf-8) as f:json.dump(data, f, ensure_asciiFalse, indent2)使用 with open(...) 打开一个文件data.json要写入的文件名如果没有会自动创建w写入模式write会覆盖原有内容encodingutf-8指定编码为 UTF-8确保中文不会乱码f 是文件对象代表这个打开的文件
说明json.dump() 将 Python 对象写入文件支持格式化输出。从 JSON 文件读取
with open(data.json, r, encodingutf-8) as f:data json.load(f)print(data)说明json.load() 用于从文件中读取并解析 JSON 数据。复杂嵌套结构解析
json_str
{user: {name: Tom,skills: [Python, C]}
}
data json.loads(json_str)
print(data[user][skills][0]) # Python说明嵌套结构可通过多级键访问。转换时处理非默认类型
import datetimedef custom(obj):if isinstance(obj, datetime.datetime):return obj.isoformat()now datetime.datetime.now()
print(json.dumps({time: now}, defaultcustom))
# {time: 2025-07-28T11:30:00.123456}说明使用 default 参数可以处理自定义类型。字符串与字典互转小技巧
s {x: 1, y: 2}
d json.loads(s)
s2 json.dumps(d)print(type(d)) # class dict
print(type(s2)) # class str防止类型错误
# 错误示例集合不是 JSON 可序列化类型
data {nums: {1, 2, 3}}
# json.dumps(data) 会报错# 解决方式转换为 list
data[nums] list(data[nums])
print(json.dumps(data))说明json 只支持部分 Python 类型需提前转换。与字典深拷贝的配合
import copy
original {a: 1, b: [1, 2]}# 用 json 序列化方式做深拷贝
clone json.loads(json.dumps(original))clone[b][0] 999
print(original) # {a: 1, b: [1, 2]}
print(clone) # {a: 1, b: [999, 2]}说明json 也可以作为一种简易深拷贝手段前提是可序列化。PIL / Pillow
PillowPIL 的分支 是 Python 中用于图像处理的强大库支持打开、编辑、保存多种格式的图片。Pillow 是原始 PIL 库的增强版常用于图像缩放、裁剪、转换、绘图等操作。
基本用法
from PIL import Image打开和显示图片
img Image.open(example.jpg) # 打开图片
img.show() # 使用默认图片查看器显示说明使用 Image.open() 加载本地图片show() 会调用系统图片查看器。查看图片属性
print(img.format) # 图片格式如 JPEG
print(img.size) # 尺寸如 (宽, 高)
print(img.mode) # 模式如 RGB、L、RGBA保存图片
img.save(output.png) # 另存为 PNG 格式说明可以将图片保存为不同格式只需更改文件后缀。图像转换
gray img.convert(L) # 转为灰度图
rgba img.convert(RGBA) # 转为含透明通道说明使用 convert() 可以转换图片颜色模式。图像缩放和缩略图
resized img.resize((100, 100)) # 强制缩放为100x100thumb img.copy()
thumb.thumbnail((100, 100)) # 缩略图保持比例说明resize() 会强行变形thumbnail() 则保持原比例缩小。裁剪图像
box (50, 50, 200, 200) # 左、上、右、下坐标
cropped img.crop(box)
cropped.show()说明裁剪区域的坐标单位为像素左上角为原点 (0, 0)。旋转和翻转
rotated img.rotate(90) # 顺时针旋转90°
flipped img.transpose(Image.FLIP_LEFT_RIGHT) # 水平翻转说明rotate() 默认逆时针实际显示是顺时针transpose() 支持翻转和旋转。叠加文字绘图
from PIL import ImageDraw, ImageFontdraw ImageDraw.Draw(img)
draw.text((10, 10), Hello, fillred)
img.show()说明使用 ImageDraw.Draw() 可对图像进行绘制默认字体简单若需设置字体需加载 ImageFont。拼接图片
img1 Image.open(a.jpg)
img2 Image.open(b.jpg)new_img Image.new(RGB, (img1.width img2.width, img1.height))
new_img.paste(img1, (0, 0))
new_img.paste(img2, (img1.width, 0))
new_img.show()说明通过创建新图像并粘贴已有图像可以实现拼接。获取像素值和修改像素
pixel img.getpixel((0, 0)) # 获取坐标(0,0)处像素
img.putpixel((0, 0), (255, 0, 0)) # 修改为红色像素RGB 模式说明适用于手动像素级操作效率较低。图片转 numpy 数组
import numpy as nparr np.array(img)
print(arr.shape) # 如(高, 宽, 通道数)说明配合 NumPy 可以进行高效的图像计算与分析。numpy 数组转图片
new_img Image.fromarray(arr)
new_img.show()说明Image.fromarray() 可以把 NumPy 数组还原为图像对象。图像格式转换与压缩
img.save(output.jpg, quality85) # 保存为 JPEG 并设置压缩质量说明quality 参数可控制 JPEG 图像压缩程度范围 1~95默认是 75。检查图片是否损坏
try:img.verify()print(图片无损坏)
except:print(图片损坏)说明verify() 方法可以验证图片文件是否完整有效。创建纯色图像
new_img Image.new(RGB, (200, 200), colorblue)
new_img.show()说明Image.new() 可创建指定颜色和尺寸的新图片。opencv
OpenCVOpen Source Computer Vision Library 是一个开源的计算机视觉库广泛用于图像处理、视频分析、人脸识别等任务。Python 中使用时通过 cv2 模块操作支持 NumPy 数组与图像的高效互操作。
基本用法
import cv2读取和显示图片
img cv2.imread(a.jpg) # 读取图像
cv2.imshow(Image, img) # 显示图像窗口
cv2.waitKey(0) # 等待按键
cv2.destroyAllWindows() # 关闭窗口说明OpenCV 使用 BGR 而非 RGB必须调用 waitKey() 才能显示窗口。保存图片
cv2.imwrite(output.jpg, img)说明将图像保存为文件支持 jpg/png 等格式。图像尺寸和属性
print(img.shape) # (高, 宽, 通道数)例如 (400, 600, 3)
print(img.dtype) # 图像数据类型例如 uint8修改图像尺寸
resized cv2.resize(img, (200, 100)) # 宽200高100转换颜色空间
gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转灰度图
rgb cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # BGR转RGB图像裁剪与ROI
roi img[100:200, 150:300] # 裁剪区域高100-200宽150-300说明和 NumPy 一样用切片操作裁剪结果仍是图像。图像绘图在图上画图形
cv2.rectangle(img, (50, 50), (150, 150), (0, 255, 0), 2) # 绿色矩形
cv2.circle(img, (100, 100), 30, (255, 0, 0), -1) # 蓝色实心圆
cv2.line(img, (0, 0), (200, 200), (0, 0, 255), 3) # 红色直线添加文字
cv2.putText(img, Hello, (50, 50), cv2.FONT_HERSHEY_SIMPLEX,1, (255, 255, 255), 2)说明可以自定义字体、大小、颜色和粗细。图像滤波模糊
blur cv2.GaussianBlur(img, (5, 5), 0) # 高斯模糊
median cv2.medianBlur(img, 5) # 中值模糊边缘检测
edges cv2.Canny(img, 100, 200) # 边缘检测说明两个参数为低/高阈值。图像阈值处理二值化
gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, thresh cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)图像按位操作遮罩
mask np.zeros(img.shape[:2], dtypenp.uint8)
mask[100:200, 100:200] 255
masked cv2.bitwise_and(img, img, maskmask)摄像头读取实时视频
cap cv2.VideoCapture(0) # 0代表默认摄像头while True:ret, frame cap.read()if not ret:breakcv2.imshow(Live, frame)if cv2.waitKey(1) ord(q):breakcap.release()
cv2.destroyAllWindows()说明按下 q 键退出循环。图像通道操作
b, g, r cv2.split(img) # 拆分BGR通道
merged cv2.merge([b, g, r]) # 合并通道图像叠加加权合并
blended cv2.addWeighted(img1, 0.6, img2, 0.4, 0)说明将两张图按比例混合适用于图像融合、水印等。轮廓检测基本
gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, thresh cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, _ cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1, (0, 255, 0), 2)保存视频
fourcc cv2.VideoWriter_fourcc(*XVID)
out cv2.VideoWriter(out.avi, fourcc, 20.0, (640, 480))while True:ret, frame cap.read()if not ret:breakout.write(frame)cv2.imshow(Recording, frame)if cv2.waitKey(1) ord(q):breakcap.release()
out.release()
cv2.destroyAllWindows()复制与原地修改
img_copy img.copy()
img_copy[0:100, 0:100] 0 # 修改左上角为黑色不影响原图任务一实践
任务
通过编写脚本处理DDXPlus数据集将数据集release_train_patients中每个病人案例划分为一个json文件
1release_train_patients
2release_evidences.json(里面含有代码(E_91等)的映射关系)
3release_conditions.json里面有每个疾病的具体信息
划分的json文件要包含上述三个文件中的相应信息。
json文件命名格式participant_{i}.json
因为train数据集的病人比较多划分出200个病人的即可
├── data/
│ └── DDXPlus/
│ ├── release_evidences.json
│ ├── release_conditions.json
│ └── release_train_patients.csv
├── result/ ← 希望输出的 json 文件保存到这里result/participants_output
├── split_ddxplus.py ← 要运行的脚本
创建虚拟环境
python -m venv venv激活虚拟环境
.\.venv\Scripts\Activate.ps1安装pandas库
pip install pandassplit_ddxplus.py脚本源码学习
import json # 导入json模块用于JSON数据的读取和写入
import os # 导入os模块用于文件和目录操作
import pandas as pd # 导入pandas模块用于读取和处理CSV文件# 设置基础路径即数据文件所在目录
base_path data/DDXPlus# 构造训练数据CSV文件的完整路径
train_file os.path.join(base_path, release_train_patients.csv)# 构造证据JSON文件的完整路径
evidence_file os.path.join(base_path, release_evidences.json)# 构造病症条件JSON文件的完整路径
condition_file os.path.join(base_path, release_conditions.json)# 设置结果输出目录
output_dir result/participants_output# 创建输出目录如果目录已存在则不会报错
os.makedirs(output_dir, exist_okTrue)# 读取训练数据CSV文件结果是pandas的DataFrame对象
train_df pd.read_csv(train_file)# 以utf-8编码打开证据JSON文件读取内容为Python对象一般是list或dict
with open(evidence_file, r, encodingutf-8) as f:evidence_data json.load(f)# 判断evidence_data的类型确保它是一个字典方便后续按ID查找
if isinstance(evidence_data, list):# 如果是列表转换为字典键为每个证据的id值为该证据的完整信息evidence_map {item[id]: item for item in evidence_data}
elif isinstance(evidence_data, dict):# 如果本来就是字典直接赋值evidence_map evidence_data
else:# 如果既不是list也不是dict抛出异常提示格式不支持raise ValueError(release_evidences.json 格式不支持)# 以utf-8编码打开条件JSON文件读取内容为Python对象
with open(condition_file, r, encodingutf-8) as f:condition_data json.load(f)# 同样判断condition_data类型确保是字典格式
if isinstance(condition_data, list):# 如果是列表转换为字典键为病症id值为病症详细信息condition_map {item[id]: item for item in condition_data}
elif isinstance(condition_data, dict):# 直接赋值condition_map condition_data
else:# 抛异常raise ValueError(release_conditions.json 格式不支持)# 遍历训练数据的前200个病人记录防止数据过多控制处理数量
for i in range(min(200, len(train_df))):# 通过iloc根据索引i选取DataFrame中的一行数据返回Series对象row train_df.iloc[i]# 解析该行中evidence字段的JSON字符串转换成Python对象try:# 先判断evidence字段是否存在且不是空值再用json.loads转换if evidence in row and pd.notna(row[evidence]):patient_evidences_raw json.loads(row[evidence])else:patient_evidences_raw []except:# 如果解析失败则赋空列表避免程序崩溃patient_evidences_raw []# 同理解析conditions字段try:if conditions in row and pd.notna(row[conditions]):patient_conditions_raw json.loads(row[conditions])else:patient_conditions_raw []except:patient_conditions_raw []# 从解析后的evidences列表中提取每条证据的id过滤掉格式不对的数据evidence_ids [e[id] for e in patient_evidences_raw if isinstance(e, dict) and id in e]# 确保patient_conditions_raw是列表类型赋给condition_ids否则赋空列表condition_ids patient_conditions_raw if isinstance(patient_conditions_raw, list) else []# 根据id从证据字典中获取对应证据详细信息忽略id不存在的情况evidence_details [evidence_map[eid] for eid in evidence_ids if eid in evidence_map]# 根据id从条件字典中获取对应条件详细信息忽略id不存在的情况condition_details [condition_map[cid] for cid in condition_ids if cid in condition_map]# 将当前病人整行信息转换为字典形式方便一起存储patient_info row.to_dict()# 构造完整的病人数据结构包括基本信息证据详情条件详情result {patient_info: patient_info,evidence_details: evidence_details,condition_details: condition_details}# 生成输出文件名例如 participant_0.jsonfilename fparticipant_{i}.json# 拼接文件保存完整路径filepath os.path.join(output_dir, filename)# 以写入模式打开文件编码为utf-8with open(filepath, w, encodingutf-8) as f:# 将result字典转换成格式化的JSON字符串写入文件确保中文正常显示json.dump(result, f, ensure_asciiFalse, indent2)# 打印提示表示当前病人数据已成功保存print(f已保存{filename})
详细分步解析
import json
import os
import pandas as pd导入 Python 标准库中的 json 用于 JSON 格式数据处理os 用于操作文件路径和目录pandas 用于处理 CSV 文件和表格数据。
# 设置路径
base_path data/DDXPlus
train_file os.path.join(base_path, release_train_patients.csv)
evidence_file os.path.join(base_path, release_evidences.json)
condition_file os.path.join(base_path, release_conditions.json)base_path 是数据集文件所在的根目录。使用 os.path.join 拼接得到训练数据 CSV 文件的完整路径 train_file。同理拼接得到 evidence_file 和 condition_file 的路径分别对应证据和病症的 JSON 文件。
# 输出目录
output_dir result/participants_output
os.makedirs(output_dir, exist_okTrue)定义输出结果保存目录 output_dir。os.makedirs 递归创建该目录如果目录已存在则不会报错exist_okTrue。
# 读取 CSV 数据
train_df pd.read_csv(train_file)用 pandas.read_csv 读取训练数据 CSV 文件存成一个 DataFrame 对象 train_df方便后续按行操作。
# 读取 evidence JSON 数据
with open(evidence_file, r, encodingutf-8) as f:evidence_data json.load(f)以 UTF-8 编码打开证据 JSON 文件使用 json.load 读取成 Python 对象赋值给 evidence_data。
# 判断 evidence_data 是不是 dict不是就转换为 dict
if isinstance(evidence_data, list):evidence_map {item[id]: item for item in evidence_data}
elif isinstance(evidence_data, dict):evidence_map evidence_data
else:raise ValueError(release_evidences.json 格式不支持)判断 evidence_data 的数据类型
如果是列表则把每个证据的 id 作为 key证据对象作为 value构建成字典 evidence_map 方便快速查找。如果本身是字典直接赋值给 evidence_map。其它类型则抛出异常提示格式不支持。# 读取 condition JSON 数据
with open(condition_file, r, encodingutf-8) as f:condition_data json.load(f)以 UTF-8 编码打开疾病条件 JSON 文件读取为 Python 对象 condition_data。
# 同样处理 condition_data
if isinstance(condition_data, list):condition_map {item[id]: item for item in condition_data}
elif isinstance(condition_data, dict):condition_map condition_data
else:raise ValueError(release_conditions.json 格式不支持)对 condition_data 做同样的判断和转换确保最终 condition_map 是字典方便后续根据 ID 查找详细信息。
# 处理前200个病人
for i in range(min(200, len(train_df))):row train_df.iloc[i]循环遍历训练数据的前 200 条记录如果不足200条就遍历所有。train_df.iloc[i] 按索引 i 获取对应行数据存到 row类型是 pandas Series。try:patient_evidences_raw json.loads(row[evidence]) if evidence in row and pd.notna(row[evidence]) else []except:patient_evidences_raw []尝试解析当前行的 evidence 字段应该是 JSON 字符串
如果字段存在且不是空值使用 json.loads 转成 Python 对象。如果不存在或是空赋空列表。若解析失败格式错误等也赋空列表避免程序崩溃。try:patient_conditions_raw json.loads(row[conditions]) if conditions in row and pd.notna(row[conditions]) else []except:patient_conditions_raw []同理尝试解析当前行的 conditions 字段处理方法和上一段相同得到原始条件列表 patient_conditions_raw。# 提取 IDevidence_ids [e[id] for e in patient_evidences_raw if isinstance(e, dict) and id in e]condition_ids patient_conditions_raw if isinstance(patient_conditions_raw, list) else []从 patient_evidences_raw 中筛选出每个证据的 id 字段生成 evidence_ids 列表。patient_conditions_raw 如果是列表则直接赋值给 condition_ids否则赋空列表保险处理。# 获取详细信息evidence_details [evidence_map[eid] for eid in evidence_ids if eid in evidence_map]condition_details [condition_map[cid] for cid in condition_ids if cid in condition_map]根据 evidence_ids 和 condition_ids从之前构建的映射字典 evidence_map 和 condition_map 中取对应详细信息生成详细信息列表。# 构建结果patient_info row.to_dict()将当前患者行数据 row 转成字典方便和证据、条件信息合并构成完整数据结构。result {patient_info: patient_info,evidence_details: evidence_details,condition_details: condition_details}构造最终输出的字典结构包含患者信息证据详情和条件详情三个部分。# 保存文件filename fparticipant_{i}.jsonfilepath os.path.join(output_dir, filename)with open(filepath, w, encodingutf-8) as f:json.dump(result, f, ensure_asciiFalse, indent2)构造输出文件名格式是 participant_0.json、participant_1.json 等。拼接成完整保存路径。以 UTF-8 编码写入 JSON 文件参数 ensure_asciiFalse 保持中文显示indent2 格式化缩进方便阅读。print(f已保存{filename})控制台打印提示告诉用户当前第 i 个患者信息已保存完成方便调试和跟踪进度。任务二实践
任务
处理vaihingen数据集将每个大图像划分并转换为512**512的jpg格式图像不足512** 512的部分用黑色像素填充图像和其标签要一起进行处理项目根目录/
├── data/
│ └── vaihingen/
│ ├── image/ ← 存放原始图像.tif
│ └── label/ ← 存放对应标签图.tif
├── result/
│ └── new_vaihingen/
│ ├── new_image/ ← 保存裁剪后的图像.jpg
│ └── new_label/ ← 保存裁剪后的标签.png
├── split_vaihingen.py ← 运行脚本pip install opencv-python tqdm numpysplit_vaihingen.py脚本源码学习
import os
import cv2
import numpy as np
from glob import glob
from tqdm import tqdmtile_size 512 # 裁剪窗口大小512x512像素# 设置输入路径分别是彩色原图和灰度标签图目录
image_dir data/vaihingen/image
label_dir data/vaihingen/label# 设置输出路径分别保存裁剪后的图像和标签
out_img_dir result/new_vaihingen/new_image
out_lbl_dir result/new_vaihingen/new_labelos.makedirs(out_img_dir, exist_okTrue) # 自动创建图像输出目录
os.makedirs(out_lbl_dir, exist_okTrue) # 自动创建标签输出目录# 获取所有图像和标签路径并排序保证对应关系
image_paths sorted(glob(os.path.join(image_dir, *.tif)))
label_paths sorted(glob(os.path.join(label_dir, *_noBoundary.tif)))assert len(image_paths) len(label_paths), 图像和标签数量不一致 # 确保一一对应# 遍历所有图像-标签对
for img_path, lbl_path in tqdm(zip(image_paths, label_paths), totallen(image_paths), desc正在处理):image cv2.imread(img_path, cv2.IMREAD_COLOR) # 读取彩色图if image is None:print(f[错误] 无法读取图像文件: {img_path})continuelabel cv2.imread(lbl_path, cv2.IMREAD_GRAYSCALE) # 读取灰度标签if label is None:print(f[错误] 无法读取标签文件: {lbl_path})continueh, w image.shape[:2] # 获取图像高宽# 从文件名中提取“area_数字”作为命名前缀basename os.path.splitext(os.path.basename(img_path))[0] # 例如 top_mosaic_09cm_area1area_name area_ basename.split(area)[-1] # 结果如 area_1# 按512像素步长遍历图像坐标进行裁剪for y in range(0, h, tile_size):for x in range(0, w, tile_size):tile_img image[y:ytile_size, x:xtile_size] # 裁剪图像块tile_lbl label[y:ytile_size, x:xtile_size] # 裁剪对应标签块# 如果标签块为空无内容跳过该块if tile_lbl is None or tile_lbl.size 0:print(f[警告] tile_lbl 是空的跳过该块。坐标: ({x}, {y}) in {area_name})continue# 判断图像块是否足够512*512不够则用黑色填充if tile_img.shape[0] tile_size or tile_img.shape[1] tile_size:pad_img np.zeros((tile_size, tile_size, 3), dtypenp.uint8) # 黑色背景图像pad_lbl np.zeros((tile_size, tile_size), dtypenp.uint8) # 黑色背景标签pad_img[:tile_img.shape[0], :tile_img.shape[1]] tile_img # 复制原图内容到左上角pad_lbl[:tile_lbl.shape[0], :tile_lbl.shape[1]] tile_lbl # 复制标签内容tile_img pad_img # 替换为填充后的图像tile_lbl pad_lbl # 替换为填充后的标签# 生成输出文件名含坐标信息确保唯一性img_name f{area_name}_{y}_{x}.jpglbl_name f{area_name}_{y}_{x}.png# 保存裁剪好的图像和标签cv2.imwrite(os.path.join(out_img_dir, img_name), tile_img)cv2.imwrite(os.path.join(out_lbl_dir, lbl_name), tile_lbl)详细分步解析
import os
import cv2
import numpy as np
from glob import glob
from tqdm import tqdm导入所需库os处理路径cv2处理图像numpy做数组和填充glob匹配文件tqdm显示进度条。
tile_size 512定义裁剪小块的尺寸为512×512像素。
image_dir data/vaihingen/image
label_dir data/vaihingen/label指定输入路径分别是原始彩色大图和对应的标签灰度图文件夹。
out_img_dir result/new_vaihingen/new_image
out_lbl_dir result/new_vaihingen/new_label指定输出路径用于保存裁剪后的小图像和对应标签。
os.makedirs(out_img_dir, exist_okTrue)
os.makedirs(out_lbl_dir, exist_okTrue)自动创建输出文件夹如果已经存在则不会报错。
image_paths sorted(glob(os.path.join(image_dir, *.tif)))
label_paths sorted(glob(os.path.join(label_dir, *_noBoundary.tif)))利用glob获取所有符合后缀的文件路径并排序确保图像和标签顺序对应。
assert len(image_paths) len(label_paths), 图像和标签数量不一致确保图像和标签数量匹配一对一对应。
for img_path, lbl_path in tqdm(zip(image_paths, label_paths), totallen(image_paths), desc正在处理):遍历每对图像和标签路径用tqdm显示进度条。image cv2.imread(img_path, cv2.IMREAD_COLOR)if image is None:print(f[错误] 无法读取图像文件: {img_path})continue读取彩色图像如果读取失败则输出错误并跳过。label cv2.imread(lbl_path, cv2.IMREAD_GRAYSCALE)if label is None:print(f[错误] 无法读取标签文件: {lbl_path})continue读取灰度标签图失败则报错跳过。h, w image.shape[:2]获取当前图像的高行数和宽列数。basename os.path.splitext(os.path.basename(img_path))[0]area_name area_ basename.split(area)[-1]解析图像文件名提取area_数字作为命名前缀方便区分图像来源。for y in range(0, h, tile_size):for x in range(0, w, tile_size):以512步长在图像宽高方向上滑动遍历每个裁剪窗口的左上角坐标。tile_img image[y:ytile_size, x:xtile_size]tile_lbl label[y:ytile_size, x:xtile_size]根据当前坐标裁剪图像块和对应标签块大小通常是512×512但边缘可能小于512。if tile_lbl is None or tile_lbl.size 0:print(f[警告] tile_lbl 是空的跳过该块。坐标: ({x}, {y}) in {area_name})continue如果标签块为空可能是超出边界或没有内容打印警告并跳过避免无效数据。if tile_img.shape[0] tile_size or tile_img.shape[1] tile_size:pad_img np.zeros((tile_size, tile_size, 3), dtypenp.uint8)pad_lbl np.zeros((tile_size, tile_size), dtypenp.uint8)pad_img[:tile_img.shape[0], :tile_img.shape[1]] tile_imgpad_lbl[:tile_lbl.shape[0], :tile_lbl.shape[1]] tile_lbltile_img pad_imgtile_lbl pad_lbl判断裁剪块是否小于512×512通常在图像边缘如果是
创建全黑的512×512空白图像和标签图把原始裁剪块数据复制到黑色背景的左上角这样确保所有输出块尺寸统一为512×512。img_name f{area_name}_{y}_{x}.jpglbl_name f{area_name}_{y}_{x}.png根据area_数字和裁剪左上角坐标生成唯一文件名方便后续对应。cv2.imwrite(os.path.join(out_img_dir, img_name), tile_img)cv2.imwrite(os.path.join(out_lbl_dir, lbl_name), tile_lbl)将裁剪并如需填充后的图像块和标签块保存为文件格式分别是jpg和png。认识数据增强
数据增强Data Augmentation是对原始训练数据进行各种变换操作生成更多的“新”样本从而扩充训练集。通过让模型见到更多样化的训练样本减少过拟合提高模型在真实环境中的表现。常见的数据增强方法
几何变换Geometric Transformations
旋转Rotation 将图像顺时针或逆时针旋转一定角度如90度、180度、任意角度。翻转Flip 水平翻转左右镜像或垂直翻转上下镜像。平移Translation 图像整体上下左右移动若干像素。缩放Scaling 放大或缩小图像尺寸。裁剪Crop 随机裁剪图像的一部分作为新样本。仿射变换Affine Transform 包括旋转、缩放、平移和剪切等组合变换。
颜色变换Color Transformations
调整亮度Brightness 调节图像整体亮度。调整对比度Contrast 增强或减弱图像对比度。调整饱和度Saturation 改变图像颜色的鲜艳度。颜色抖动Color Jitter 随机微调亮度、对比度、饱和度等。
添加噪声Noise Injection
高斯噪声Gaussian Noise 在像素值中加入高斯分布噪声。椒盐噪声Salt-and-Pepper Noise 随机像素被替换为极端黑白值。
模糊和锐化Blurring and Sharpening
高斯模糊Gaussian Blur 图像平滑处理减弱细节。锐化Sharpening 增强边缘和细节。
复杂增强技术Advanced Techniques
Cutout随机遮挡图像的一部分区域模拟遮挡。Mixup将两张图像按一定比例混合同时混合标签。CutMix剪切一块图像并粘贴到另一张图像上同时对应标签也按比例调整。数据增强的作用
增加训练数据多样性降低过拟合风险。提升模型的泛化能力使其在各种变化环境下表现更稳健。弥补样本数量不足尤其在数据采集困难或成本高时尤为重要。Python中常用的数据增强库
Albumentations功能丰富且高效的图像增强库。imgaug支持复杂的序列增强操作。torchvision.transformsPyTorch框架内置的常用增强函数。Keras ImageDataGeneratorKeras内置的实时图像增强工具。