🚗

项目概述
这是一个基于计算机视觉和深度学习的智能加油站停车辅助系统,帮助驾驶员在加油站自动保持安全停车距离,并提供精确的停车引导。
🌍
实际应用场景
场景描述
在繁忙的城市加油站,特别是在高峰时段,车辆排队加油现象普遍。
新手司机常常难以判断与前车的安全距离,导致:
-
影响
视线盲区
核心逻辑讲解
┌─────────────────────────────────────────────────────────────┐
│
系统工作流程
│
├─────────────────────────────────────────────────────────────┤
│
摄像头采集实时视频流
│
└─────────────────────────────────────────────────────────────┘
关键技术点
1.
目标检测:YOLOv8实时识别车辆
2.
距离估算:基于相机标定参数转换像素距离
3.
状态机:管理停车流程的各个阶段
4.
多线程:分离视频采集和处理
📁
项目结构
gas_station_parking_assistant/
│
├──
main.py
(config.py)
"""
加油站自动车距提醒系统
配置文件
包含系统所有可调参数
"""
from
dataclasses
List
@dataclass
class
CameraConfig:
"""摄像头配置"""
device_id:
int
焦距(像素单位)
sensor_width:
float
传感器宽度(mm)
@dataclass
class
DetectionConfig:
"""目标检测配置"""
model_path:
str
目标类别(车辆)
def
self.target_classes
7=卡车
self.target_classes
=
7]
@dataclass
class
DistanceConfig:
"""距离计算配置"""
min_safe_distance:
float
最小安全距离(米)
max_safe_distance:
float
最大安全距离(米)
warning_distance:
float
警告距离(米)
car_length_meters:
float
参考车长(米)
pixels_per_meter:
float
每米对应的像素数(需校准)
@dataclass
class
AlertConfig:
"""提醒系统配置"""
beep_enabled:
bool
是否启用视觉提醒
alert_sound_file:
str
"sounds/beep.wav"
alert_interval:
float
提醒间隔(秒)
@dataclass
class
GuideConfig:
"""引导显示配置"""
arrow_color:
Tuple[int,
3
@dataclass
class
SystemConfig:
"""系统总配置"""
camera:
CameraConfig
CameraConfig()
detection:
DetectionConfig
DetectionConfig()
distance:
DistanceConfig
GuideConfig()
debug_mode:
bool
(modules/camera.py)
"""
摄像头管理模块
负责视频流的采集和管理
"""
import
cv2
import
CameraManager:
"""
摄像头管理器
功能:
-
初始化摄像头设备
-
支持多线程采集
"""
def
__init__(self,
None):
"""
初始化摄像头
Args:
config:
摄像头配置对象
"""
self.config
=
Queue(maxsize=10)
self._lock
=
bool:
"""
初始化摄像头设备
Returns:
bool:
初始化是否成功
"""
try:
self.cap
=
cv2.VideoCapture(self.config.device_id)
if
not
self.cap.isOpened():
print(f"[错误]
无法打开摄像头设备
{self.config.device_id}")
return
False
#
设置分辨率
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH,
self.config.width)
self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT,
self.config.height)
self.cap.set(cv2.CAP_PROP_FPS,
=
int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH))
actual_height
=
int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
actual_fps
=
self.cap.get(cv2.CAP_PROP_FPS)
print(f"[信息]
摄像头初始化成功")
print(f"
分辨率:
{actual_width}x{actual_height}")
print(f"
帧率:
start_capture(self):
"""
启动后台线程进行帧采集
"""
if
self.cap
RuntimeError("摄像头未初始化")
self.is_running
=
threading.Thread(target=self._capture_loop)
self.capture_thread.daemon
=
True
self.capture_thread.start()
print("[信息]
_capture_loop(self):
"""
后台帧采集循环
"""
while
frame
self.frame_queue.full():
self.frame_queue.put(frame)
else:
print("[警告]
帧读取失败")
time.sleep(0.01)
def
read_frame(self,
Optional[cv2.Mat]:
"""
读取一帧图像
Args:
timeout:
等待超时时间(秒)
Returns:
Optional[cv2.Mat]:
帧图像,失败返回None
"""
try:
return
self.frame_queue.get(timeout=timeout)
except:
return
None
def
Optional[cv2.Mat]]:
"""
直接从摄像头读取帧(同步方式)
Returns:
tuple:
(成功标志,
帧图像)
"""
if
self.cap
release(self):
"""
释放摄像头资源
"""
self.is_running
=
self.capture_thread.is_alive():
self.capture_thread.join(timeout=2.0)
if
self.cap
None:
self.cap.release()
print("[信息]
get_properties(self)
dict:
"""
获取摄像头属性
Returns:
dict:
摄像头属性字典
"""
if
self.cap
int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH)),
"height":
int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT)),
"fps":
self.cap.get(cv2.CAP_PROP_FPS),
"frame_count":
int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT))
}
class
VideoFileReader(CameraManager):
"""
视频文件读取器(用于测试和演示)
继承自CameraManager,接口兼容
"""
def
__init__(self,
str):
"""
初始化视频文件读取器
Args:
video_path:
视频文件路径
"""
super().__init__()
self.video_path
=
cv2.VideoCapture(video_path)
if
not
self.cap.isOpened():
raise
FileNotFoundError(f"无法打开视频文件:
=
int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT))
self.fps
=
self.cap.get(cv2.CAP_PROP_FPS)
print(f"[信息]
视频加载成功:
{video_path}")
print(f"
总帧数:
start_capture(self):
"""重写方法,视频不需要后台采集"""
self.is_running
=
_capture_loop(self):
"""视频播放循环"""
current_frame
=
self.frame_queue.full():
self.frame_queue.put((current_frame,
+=
(modules/detector.py)
"""
车辆检测模块
基于YOLOv8实现实时车辆检测
"""
import
cv2
import
VehicleDetector:
"""
车辆检测器
功能:
-
加载YOLOv8模型
-
过滤和分类检测结果
"""
#
=
None):
"""
初始化车辆检测器
Args:
config:
检测配置对象
"""
self.config
=
CONFIG.detection
self.model:
Optional[YOLO]
bool:
"""
加载YOLOv8模型
Returns:
bool:
加载是否成功
"""
try:
print(f"[信息]
正在加载模型:
{self.config.model_path}")
#
=
YOLO(self.config.model_path)
#
预热模型(运行几次推理)
dummy_input
=
range(3):
self.model(dummy_input,
verbose=False)
print(f"[信息]
模型加载成功")
print(f"
目标类别:
self.config.target_classes]}")
return
True
except
List[Dict]:
"""
检测图像中的车辆
Args:
frame:
输入图像(BGR格式)
Returns:
List[Dict]:
检测结果列表,每个元素包含:
-
bbox:
中心点坐标
"""
if
self.model
RuntimeError("模型未加载")
results
=
self.model(
frame,
conf=self.config.conf_threshold,
iou=self.config.iou_threshold,
classes=self.config.target_classes,
verbose=False
)
#
解析结果
for
box.xyxy[0].cpu().numpy()
#
=
float(box.conf[0])
class_id
=
int(box.cls[0])
class_name
=
f'unknown_{class_id}')
#
计算中心点
center_x
int(y2)],
'confidence':
confidence,
'class_id':
class_id,
'class_name':
class_name,
'center':
(float(center_x),
float(center_y)),
'width':
int(x2
y1)
}
results.append(result)
return
results
def
filter_vehicles_by_position(
self,
detections:
Tuple[int,
List[Dict]:
"""
根据位置过滤车辆检测结果
Args:
detections:
图像尺寸
'all')
Returns:
List[Dict]:
过滤后的检测结果
"""
height,
width
前方区域:图像下半部分,中间偏右(假设自车在左侧)
if
>
0.9:
filtered.append(det)
elif
region
0.5:
filtered.append(det)
else:
#
全部区域
filtered.append(det)
return
filtered
def
find_closest_vehicle(
self,
detections:
List[Dict],
reference_point:
Tuple[float,
Optional[Dict]:
"""
找到最近的车辆
Args:
detections:
参考点坐标,默认为图像底部中心
Returns:
Optional[Dict]:
最近的车辆信息,无车辆返回None
"""
if
not
reference_point
closest_vehicle
=
min_distance:
min_distance
=
draw_detections(
self,
frame:
bool
np.ndarray:
"""
在图像上绘制检测结果
Args:
frame:
是否显示标签
Returns:
np.ndarray:
绘制后的图像
"""
output
=
det['confidence']
cls_name
=
det['class_name']
#
根据类别选择颜色
color
self._get_class_color(det['class_id'])
#
绘制边界框
cv2.rectangle(output,
(x1,
{conf:.2f}"
label_size,
baseline
标签背景
cv2.rectangle(
output,
(x1,
label_size[1]
y1),
color,
-1
)
#
标签文字
cv2.putText(
output,
label,
5),
cv2.FONT_HERSHEY_SIMPLEX,
0.5,
int]:
"""
根据类别ID获取颜色
Args:
class_id:
类别ID
Returns:
Tuple[int,
int,
BGR颜色值
"""
colors
=
Dict:
"""
获取检测统计信息
Args:
detections:
检测结果
Returns:
Dict:
统计信息
"""
if
not
len(detections),
'by_class':
{},
'avg_confidence':
=
det['class_name']
stats['by_class'][cls_name]
=
stats['by_class'].get(cls_name,
+
det['confidence']
total_area
+=
det['height']
stats['avg_confidence']
=
len(detections)
stats['avg_area']
=
(modules/distance_calculator.py)
"""
距离计算模块
将像素距离转换为实际距离
"""
import
numpy
CONFIG
@dataclass
class
DistanceResult:
"""
距离计算结果
"""
pixel_distance:
float
实际距离(米)
confidence:
float
'danger')
recommended_action:
str
DistanceCalculator:
"""
距离计算器
功能:
-
考虑车辆尺寸估计距离
-
提供安全状态评估
"""
def
__init__(self,
None):
"""
初始化距离计算器
Args:
config:
距离配置对象
"""
self.config
=
CONFIG.distance
self.calibration_params
=
set_calibration(
self,
focal_length:
Tuple[float,
None
):
"""
设置相机标定参数
Args:
focal_length:
焦距(像素单位)
pixels_per_meter:
参考距离下的像素/米比例
principal_point:
主点坐标
cy)
"""
self.calibration_params
=
{
'focal_length':
focal_length,
'pixels_per_meter':
pixels_per_meter,
'principal_point':
principal_point
360)
}
print(f"[信息]
相机标定参数已设置")
print(f"
焦距:
{pixels_per_meter:.1f}")
def
calculate_pixel_distance(
self,
point1:
Tuple[float,
float:
"""
计算两点间的像素距离
Args:
point1:
第一点坐标
像素距离
"""
return
np.sqrt((point2[0]
point1[1])**2)
利用AI解决实际问题,如果你觉得这个工具好用,欢迎关注长安牧笛!


