数据读取基础:用Python打开ADAS数据的大门
做ADAS数据分析,第一步永远是把数据读进来。这听起来简单,但我在实际项目中踩过不少坑。今天咱们就聊聊三种最常见的ADAS数据格式:CSV、Parquet、图像,以及二进制数据。每种格式都有它的脾气,摸透了才能事半功倍。
1. CSV文件:最通用的数据交换格式
CSV文件在ADAS领域太常见了。传感器标定参数、日志文件、标注数据,到处都能看到它的身影。我个人习惯用pandas来读取,因为它太方便了。
import pandas as pd
# 读取CSV文件
df = pd.read_csv('adas_sensor_data.csv')
print(df.head())
print(df.info())
嗯,这里要注意几个关键参数。我在项目中遇到过一个问题:某个CSV文件里时间戳列被读成了字符串,导致后续分析全乱套。后来发现是文件里混入了空行。
dtype 参数指定列类型,尤其是时间戳和数值列。比如 dtype={'timestamp': 'int64', 'speed': 'float32'},能避免很多隐式类型转换的坑。
# 更稳健的读取方式
df = pd.read_csv(
'adas_sensor_data.csv',
dtype={'timestamp': 'int64', 'speed': 'float32'},
parse_dates=['time_column'], # 自动解析时间
na_values=['NA', 'null', ''] # 统一缺失值标记
)
你想想看,如果数据量不大,CSV完全够用。但一旦上了百万行级别,CSV的读取速度就让人抓狂了。这时候就该Parquet上场了。
2. Parquet文件:大数据场景下的首选
Parquet是列式存储格式,压缩率高,读取速度快。我在处理激光雷达点云数据时,经常用Parquet来存储中间结果。pandas直接支持读取,非常方便。
# 读取Parquet文件
df = pd.read_parquet('lidar_pointcloud.parquet')
print(df.shape)
print(df.columns.tolist())
为什么Parquet比CSV快?说白了,它只读取你需要的列。比如你只需要速度和加速度两列数据,Parquet可以跳过其他列,而CSV必须全部读进来。
| 文件格式 | 100万行读取时间 | 文件大小 | 内存占用 |
|---|---|---|---|
| CSV | 约3.2秒 | 85 MB | 约500 MB |
| Parquet | 约0.8秒 | 22 MB | 约120 MB |
我曾经在项目里用CSV存了10GB的驾驶数据,每次加载都要等好几分钟。后来换成Parquet,加载时间缩短到30秒以内。这个优化太值了。
3. 图像数据:OpenCV读取ADAS视觉数据
ADAS离不开摄像头。不管是车道线检测、行人识别还是交通标志识别,第一步都是把图像读进来。OpenCV是业界标准,我用它处理过几十万张道路图像。
import cv2
# 读取图像
img = cv2.imread('road_scene.jpg')
print(f"图像尺寸: {img.shape}") # (高度, 宽度, 通道数)
# 显示图像(调试用)
cv2.imshow('ADAS Image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
这里有个坑:OpenCV默认读取的是BGR格式,不是RGB。我第一次做颜色分析时,发现红色和蓝色通道搞反了,折腾了半天才找到原因。
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)。另外,图像路径不要包含中文字符,否则OpenCV会静默失败,返回None。
# 批量读取图像(ADAS视频帧处理)
import glob
image_files = glob.glob('frames/*.jpg')
frames = []
for f in image_files[:10]: # 先读10帧测试
img = cv2.imread(f)
if img is not None:
frames.append(img)
else:
print(f"警告:无法读取 {f}")
4. 二进制数据:用pyarrow处理原始传感器数据
ADAS系统里,很多传感器数据是二进制的。比如激光雷达的点云数据、毫米波雷达的原始信号。pyarrow是处理这类数据的利器,它底层用C++实现,速度飞快。
import pyarrow as pa
import pyarrow.parquet as pq
# 读取二进制文件(假设是自定义格式)
with open('radar_raw.bin', 'rb') as f:
raw_data = f.read()
# 解析二进制数据(示例:假设每4字节是一个float32)
import numpy as np
data_array = np.frombuffer(raw_data, dtype=np.float32)
print(f"读取了 {len(data_array)} 个浮点数")
pyarrow的真正威力在于处理大规模列式数据。比如你要读取一个10GB的Parquet文件,pyarrow可以只加载需要的列,内存占用极低。
# 使用pyarrow读取Parquet(只读特定列)
import pyarrow.parquet as pq
table = pq.read_table(
'large_lidar_data.parquet',
columns=['x', 'y', 'z', 'intensity'] # 只读这4列
)
print(f"行数: {table.num_rows}, 列数: {table.num_columns}")
# 转换为pandas DataFrame
df = table.to_pandas()
我记得有一次处理一个20GB的点云数据集,用pandas直接读内存直接爆了。换成pyarrow的列式读取,内存占用降到2GB以下,顺利搞定。
- 小数据量(<100MB):用pandas读CSV,简单直接
- 中等数据量(100MB-5GB):用pandas读Parquet,平衡速度和内存
- 大数据量(>5GB):用pyarrow读Parquet,精细控制内存
- 图像数据:永远用OpenCV,没有替代品
5. 实战:组合读取ADAS多模态数据
真实场景下,ADAS数据往往是多模态的。比如一个驾驶场景,同时包含CSV格式的车辆状态、Parquet格式的激光雷达点云、以及JPG格式的摄像头图像。我写过一个脚本,一次性加载所有数据。
import pandas as pd
import cv2
import pyarrow.parquet as pq
import os
def load_adas_scene(scene_path):
"""加载一个ADAS场景的所有数据"""
data = {}
# 读取车辆状态(CSV)
csv_file = os.path.join(scene_path, 'vehicle_state.csv')
data['state'] = pd.read_csv(csv_file)
# 读取激光雷达数据(Parquet)
lidar_file = os.path.join(scene_path, 'lidar.parquet')
table = pq.read_table(lidar_file, columns=['x', 'y', 'z', 'reflectivity'])
data['lidar'] = table.to_pandas()
# 读取摄像头图像(JPG)
img_file = os.path.join(scene_path, 'camera.jpg')
data['image'] = cv2.imread(img_file)
return data
# 使用示例
scene_data = load_adas_scene('scene_001')
print(f"车辆状态: {scene_data['state'].shape}")
print(f"点云数据: {scene_data['lidar'].shape}")
print(f"图像尺寸: {scene_data['image'].shape}")
这个函数我用了好几年,不断迭代优化。最开始没有加列过滤,后来发现点云数据太大,就加上了 columns 参数。你想想看,如果每次都要加载全部列,内存根本扛不住。
- CSV适合小数据量,注意指定数据类型和缺失值处理
- Parquet是大数据场景的首选,列式存储节省时间和内存
- OpenCV读取图像时注意BGR和RGB的差异
- pyarrow适合处理超大二进制数据集,可以精细控制内存
- 多模态数据建议封装成统一的加载函数,便于复用
好了,数据读取这块就聊到这儿。下一章咱们会深入聊聊数据清洗和预处理,那才是真正考验耐心的地方。记住,数据读不对,后面全白费。先把这一步练扎实了。