import cv2
import numpy as np
import math
import json
class FireSuppressionSystem:
def __init__(self):
self.sensitive_devices = []
self.fire_location = None
self.sprinkler_height = 3.0 # 灭火喷头安装高度,单位:米
def S110_capture_image(self, image_path):
"""S110: 采集配电站内的图像信息"""
try:
image = cv2.imread(image_path)
if image is None:
raise FileNotFoundError(f"无法加载图像文件: {image_path}")
return image
except Exception as e:
print(f"图像采集错误: {e}")
return None
def S120_locate_fire(self, image):
"""S120: 根据图像信息,定位配电站内的起火点"""
try:
# 转换为HSV色彩空间
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
# 定义火焰颜色范围(红色和黄色)
lower_red = np.array([0, 120, 70])
upper_red = np.array([10, 255, 255])
lower_yellow = np.array([20, 100, 100])
upper_yellow = np.array([30, 255, 255])
# 创建火焰颜色掩膜
mask_red = cv2.inRange(hsv, lower_red, upper_red)
mask_yellow = cv2.inRange(hsv, lower_yellow, upper_yellow)
mask = cv2.bitwise_or(mask_red, mask_yellow)
# 寻找轮廓
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if not contours:
print("未检测到火焰")
return None
# 找到最大轮廓(假设为火焰)
largest_contour = max(contours, key=cv2.contourArea)
M = cv2.moments(largest_contour)
if M["m00"] == 0:
return None
# 计算火焰中心点
cx = int(M["m10"] / M["m00"])
cy = int(M["m01"] / M["m00"])
# 转换为实际坐标(假设图像坐标系与配电站坐标系一致)
self.fire_location = (cx, cy)
# 发送报警信息
print(f"警报:检测到起火点,位置坐标: {self.fire_location}")
return self.fire_location
except Exception as e:
print(f"起火点定位错误: {e}")
return None
def S130_get_sensitive_devices(self, devices_info):
"""S130: 获取对灭火剂敏感的敏感设备"""
try:
self.sensitive_devices = devices_info
print(f"获取到敏感设备信息: {len(self.sensitive_devices)}个设备")
return self.sensitive_devices
except Exception as e:
print(f"获取敏感设备错误: {e}")
return None
def S140_calculate_sensitive_distances(self):
"""S140: 获取各个敏感设备距离起火点对应的敏感间距"""
if not self.fire_location or not self.sensitive_devices:
print("错误:缺少起火点位置或敏感设备信息")
return None
try:
fx, fy = self.fire_location
sensitive_distances = []
for device in self.sensitive_devices:
dx, dy = device['position']
distance = math.sqrt((dx - fx)**2 + (dy - fy)**2)
sensitive_distances.append({
'device_id': device['id'],
'distance': distance
})
print("敏感设备距离计算完成")
return sensitive_distances
except Exception as e:
print(f"计算敏感间距错误: {e}")
return None
def S150_determine_safety_angles(self):
"""S150: 确定敏感设备对应的安全角"""
if not self.sensitive_devices:
print("错误:缺少敏感设备信息")
return None
try:
safety_angles = []
for device in self.sensitive_devices:
# 这里假设安全角是根据设备类型预先定义的
angle = device.get('safety_angle', 30) # 默认30度
safety_angles.append({
'device_id': device['id'],
'safety_angle': angle
})
print("安全角确定完成")
return safety_angles
except Exception as e:
print(f"确定安全角错误: {e}")
return None
def S160_check_sprinkler_angle(self, current_angle, sensitive_distances, safety_angles):
"""S160: 判断灭火喷头的喷射角度是否需要进行迭代"""
if not sensitive_distances or not safety_angles:
print("错误:缺少敏感间距或安全角信息")
return None
try:
min_sensitive_distance = min([d['distance'] for d in sensitive_distances])
safety_angle_dict = {d['device_id']: d['safety_angle'] for d in safety_angles}
# 计算空间避让约束模型
for device in self.sensitive_devices:
device_id = device['id']
distance = next(d['distance'] for d in sensitive_distances if d['device_id'] == device_id)
safety_angle = safety_angle_dict[device_id]
# 计算临界角度
critical_angle = math.degrees(math.atan(distance / self.sprinkler_height))
# 检查是否违反约束
if abs(current_angle - critical_angle) < safety_angle:
print(f"需要迭代喷射角度,设备 {device_id} 违反约束")
return True
print("当前喷射角度满足所有约束")
return False
except Exception as e:
print(f"喷射角度检查错误: {e}")
return None
def S180_iterate_sprinkler_angle(self, current_angle, sensitive_distances, safety_angles):
"""S180: 迭代喷射角度"""
if not sensitive_distances or not safety_angles:
print("错误:缺少敏感间距或安全角信息")
return None
try:
safety_angle_dict = {d['device_id']: d['safety_angle'] for d in safety_angles}
# 计算所有设备的临界角度
critical_angles = []
for device in self.sensitive_devices:
device_id = device['id']
distance = next(d['distance'] for d in sensitive_distances if d['device_id'] == device_id)
safety_angle = safety_angle_dict[device_id]
critical_angle = math.degrees(math.atan(distance / self.sprinkler_height))
critical_angles.append({
'device_id': device_id,
'critical_angle': critical_angle,
'safety_angle': safety_angle
})
# 找出最严格的约束
max_constraint = max(critical_angles, key=lambda x: abs(current_angle - x['critical_angle']))
# 计算新的喷射角度
if current_angle > max_constraint['critical_angle']:
new_angle = max_constraint['critical_angle'] + max_constraint['safety_angle']
else:
new_angle = max_constraint['critical_angle'] - max_constraint['safety_angle']
print(f"喷射角度从 {current_angle}° 迭代为 {new_angle}°")
return new_angle
except Exception as e:
print(f"喷射角度迭代错误: {e}")
return None
def run_full_process(self, image_path, devices_info, initial_angle=45):
"""运行完整的灭火喷头控制流程"""
# S110: 采集图像
image = self.S110_capture_image(image_path)
if image is None:
return None
# S120: 定位起火点
fire_location = self.S120_locate_fire(image)
if fire_location is None:
return None
# S130: 获取敏感设备
sensitive_devices = self.S130_get_sensitive_devices(devices_info)
if sensitive_devices is None:
return None
# S140: 计算敏感间距
sensitive_distances = self.S140_calculate_sensitive_distances()
if sensitive_distances is None:
return None
# S150: 确定安全角
safety_angles = self.S150_determine_safety_angles()
if safety_angles is None:
return None
# S160: 检查喷射角度
need_iteration = self.S160_check_sprinkler_angle(initial_angle, sensitive_distances, safety_angles)
if need_iteration is None:
return None
final_angle = initial_angle
# S180: 如果需要则迭代角度
if need_iteration:
final_angle = self.S180_iterate_sprinkler_angle(initial_angle, sensitive_distances, safety_angles)
if final_angle is None:
return None
# S170/S180: 确定最终喷射角度
print(f"最终确定的灭火剂喷射角度为: {final_angle}°")
# 保存结果
result = {
'fire_location': fire_location,
'sensitive_devices': sensitive_devices,
'sensitive_distances': sensitive_distances,
'safety_angles': safety_angles,
'final_sprinkler_angle': final_angle
}
with open('灭火喷头控制结果.json', 'w', encoding='utf-8') as f:
json.dump(result, f, ensure_ascii=False, indent=4)
print("灭火喷头控制结果已保存到'灭火喷头控制结果.json'")
return result
# 示例使用
if __name__ == "__main__":
# 创建灭火系统实例
fire_system = FireSuppressionSystem()
# 示例敏感设备信息
example_devices = [
{'id': 'device1', 'position': (100, 150), 'safety_angle': 30},
{'id': 'device2', 'position': (200, 100), 'safety_angle': 25},
{'id': 'device3', 'position': (150, 200), 'safety_angle': 35}
]
# 运行完整流程
result = fire_system.run_full_process(
image_path='配电站图像.jpg', # 需要替换为实际图像路径
devices_info=example_devices,
initial_angle=45
)
if result:
print("灭火喷头控制流程执行成功")
else:
print("灭火喷头控制流程执行失败")