需求1:
1.首先基于静态特征完成火灾视频的检测(ExR+OTSU)
2.针对二值化视频,每间隔20帧计算一次火灾区域的面积,新建一个散点图按照顺序显示火灾面积
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 打开视频文件
cap = cv2.VideoCapture('1-远距离森林火灾1.avi') # 将'your_video.mp4'替换为你的视频文件路径
# 获取视频帧的宽度和高度
width = int(cap.get(3))
height = int(cap.get(4))
# 创建 VideoWriter 对象,输出视频的名称为 'output_video.avi',编解码器为 XVID,帧率为 25
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output_video.avi', fourcc, 25, (width * 2, height))
# 创建一个窗口
cv2.namedWindow('Fire Detection', cv2.WINDOW_NORMAL)
# 初始化用于存储每20帧计算得到的火灾面积的列表
fire_areas = []
# 用于记录当前帧数的计数器
frame_count = 0
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# 转换为灰度图像
gray_frame = 1.6 * frame[:, :, 2] - frame[:, :, 1] - 0.8 * frame[:, :, 0]
gray_frame = np.clip(gray_frame, 0, 255).astype(np.uint8)
# 使用Otsu算法进行二值化
_, binary_frame = cv2.threshold(gray_frame, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# 对二值化图像进行腐蚀和膨胀操作去除噪声
kernel = np.ones((5, 5), np.uint8)
binary_frame = cv2.erode(binary_frame, kernel, iterations=1)
binary_frame = cv2.dilate(binary_frame, kernel, iterations=1)
# 在同一个窗口中展示原视频和二值化后的视频
side_by_side = np.hstack((frame, cv2.cvtColor(binary_frame, cv2.COLOR_GRAY2BGR)))
cv2.imshow('Fire Detection', side_by_side)
# 将二值化后的帧写入输出视频
out.write(side_by_side)
# 计算每20帧的火灾面积
if frame_count % 20 == 0:
# 计算二值化后的图像中白色区域的面积
fire_area = np.sum(binary_frame == 255)
fire_areas.append(fire_area)
frame_count += 1
if cv2.waitKey(25) & 0xFF == 27:
break
# 释放资源
cap.release()
out.release()
cv2.destroyAllWindows()
# 绘制散点图显示火灾面积的变化
frame_indices = np.arange(0, len(fire_areas) * 20, 20)
plt.scatter(frame_indices, fire_areas, marker='o')
plt.xlabel('Frame Index')
plt.ylabel('Fire Area')
plt.title('Fire Area Over Time')
# 设置纵坐标轴范围
plt.ylim(0, max(fire_areas) + 100) # 调整刻度范围,可以根据需要适当调整上限
plt.show()
需求2:
1.首先基于静态特征完成火灾视频的检测(ExR+OTSU)
2.针对二值化视频,每间隔20帧计算一次火灾区域的面积,新建一个散点图按照顺序显示火灾面积
3.计算间隔20帧间火灾面积的变化率
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 打开视频文件
cap = cv2.VideoCapture('1-远距离森林火灾1.avi') # 将'your_video.mp4'替换为你的视频文件路径
# 获取视频帧的宽度和高度
width = int(cap.get(3))
height = int(cap.get(4))
# 创建 VideoWriter 对象,输出视频的名称为 'output_video.avi',编解码器为 XVID,帧率为 25
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output_video.avi', fourcc, 25, (width * 2, height))
# 创建一个窗口
cv2.namedWindow('Fire Detection', cv2.WINDOW_NORMAL)
# 初始化用于存储每20帧计算得到的火灾面积的列表
fire_areas = []
# 用于记录当前帧数的计数器
frame_count = 0
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# 转换为灰度图像
gray_frame = 1.6 * frame[:, :, 2] - frame[:, :, 1] - 0.8 * frame[:, :, 0]
gray_frame = np.clip(gray_frame, 0, 255).astype(np.uint8)
# 使用Otsu算法进行二值化
_, binary_frame = cv2.threshold(gray_frame, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# 对二值化图像进行腐蚀和膨胀操作去除噪声
kernel = np.ones((5, 5), np.uint8)
binary_frame = cv2.erode(binary_frame, kernel, iterations=1)
binary_frame = cv2.dilate(binary_frame, kernel, iterations=1)
# 在同一个窗口中展示原视频和二值化后的视频
side_by_side = np.hstack((frame, cv2.cvtColor(binary_frame, cv2.COLOR_GRAY2BGR)))
cv2.imshow('Fire Detection', side_by_side)
# 将二值化后的帧写入输出视频
out.write(side_by_side)
# 计算每20帧的火灾面积
if frame_count % 20 == 0:
# 计算二值化后的图像中白色区域的面积
fire_area = np.sum(binary_frame == 255)
fire_areas.append(fire_area)
frame_count += 1
if cv2.waitKey(25) & 0xFF == 27:
break
# 释放资源
cap.release()
out.release()
cv2.destroyAllWindows()
# 绘制散点图显示火灾面积的变化
frame_indices = np.arange(0, len(fire_areas) * 20, 20)
plt.scatter(frame_indices, fire_areas, marker='o')
plt.xlabel('Frame Index')
plt.ylabel('Fire Area')
plt.title('Fire Area Over Time')
# 设置纵坐标轴范围
plt.ylim(0, max(fire_areas) + 100) # 调整刻度范围,可以根据需要适当调整上限
# 计算火灾面积变化率
fire_area_rates = [0] # 初始帧的变化率为0
for i in range(1, len(fire_areas)):
# 计算变化率
rate = (fire_areas[i] - fire_areas[i - 1]) / fire_areas[i - 1]
fire_area_rates.append(rate)
# 绘制火灾面积变化率图
plt.figure() # 新建一个图形窗口
plt.plot(frame_indices, fire_area_rates, marker='o', linestyle='-')
plt.xlabel('Frame Index')
plt.ylabel('Fire Area Rate')
plt.title('Fire Area Rate Over Time')
# 设置纵坐标轴范围,从0开始,间隔一定距离向上递增或者向下递减
plt.ylim(min(fire_area_rates) - 0.1, max(fire_area_rates) + 0.1)
plt.show()