基于规则的多色空间和相关系数的高效森林火灾探测在无人机中的应用-文献复现

Abstract
Forest fires inflict great losses of human lives and serious damages to ecological systems.
Hence, numerous fire detection methods have been proposed, one of which is fire detection
based on sensors. However, these methods reveal several limitations when applied in large
spaces like forests such as high cost, high level of false alarm, limited battery capacity, and
other problems. In this research, we propose a novel forest fire detection method based on
image processing and correlation coefficient. Firstly, two fire detection conditions are applied
in RGB color space to distinguish between fire pixels and the background. Secondly, the
image is converted from RGB to YCbCr color space with two fire detection conditions being
applied in this color space. Finally, the correlation coefficient is used to distinguish between
fires and objects with fire-like colors. Our proposed algorithm is tested and evaluated on
eleven fire and non-fire videos collected from the internet and achieves up to 95.87% and
97.89% of F-score and accuracy respectively in performance evaluation.
森林火灾给人类生命造成巨大损失,给生态系统造成严重破坏。因此,人们提出了许多火灾探测方法,其中一种是基于传感器的火灾探测。然而,这些方法在森林等大空间应用时存在一些局限性,如高成本、高虚警、电池容量有限等问题。本文提出了一种基于图像处理和相关系数的森林火灾检测方法。首先,在RGB色彩空间中应用两种火灾检测条件来区分火灾像素和背景;其次,将图像从RGB颜色空间转换为YCbCr颜色空间,并在该颜色空间中应用两种火灾检测条件。最后,使用相关系数来区分火焰和具有类似火焰颜色的物体。本文提出的算法在网上收集的11个火灾和非火灾视频上进行了测试和评价,性能评价的f值和准确率分别达到95.87%和97.89%。
2.1 Forest fire Detection in RGB Images
文章原图
Fig. 4. a) The original RGB images and its channels: b) R channel, c) G channel, and d) B channel.在这里插入图片描述复现代码

import cv2

# 读取图像
lena = cv2.imread("A4.jpg")  

# RGB3个通道的提取
(B, G, R) = cv2.split(lena)  #提取R、G、B分量,opencv读取顺序是BGR,所以提取顺序也是BGR
cv2.imshow("Red",R)
cv2.imshow("Green",G)
cv2.imshow("Blue",B)
cv2.waitKey(0)

复现图片在这里插入图片描述
2.1.2 Forest fire detection algorithm in RGB image
在这里插入图片描述
根据上述规则的检测结果
原图
在这里插入图片描述
复现代码:

from PIL import Image

# 打开图片文件
image = Image.open('filename.jpg')

# 将图片转换为RGB模式
rgb_image = image.convert('RGB')

# 获取图片宽度和高度
width, height = rgb_image.size

# 创建一个新的二值化图像对象
binary_image = Image.new('1', (width, height))

# 遍历每个像素,并判断是否满足条件
for x in range(width):
    for y in range(height):
        r, g, b = rgb_image.getpixel((x, y))
        if r > g > b:
            binary_image.putpixel((x, y), 1)
        else:
            binary_image.putpixel((x, y), 0)

# 展示处理后的图片
binary_image.show()

复现结果:
在这里插入图片描述
The result shows that the condition 1 is vague, which caused those pixels with the same color range to be incorrectly passed as in the white color inside the red line in Fig. 5. Based on the achieved results in Fig. 5 can be seen that the using condition 1 only is not strong enough in forest fire detection. Hence, we proposed to combine conditions 1 and 2 to solve the limitations in condition 1. The details of condition 2 are as follows:
在这里插入图片描述
在这里插入图片描述
论文原图:
在这里插入图片描述
复现代码:

from PIL import Image

# 打开图片并转换为RGB格式
img = Image.open('input.jpg').convert('RGB')

# 获取图片大小
width, height = img.size

# 创建新的二值化图片
binary_img = Image.new('1', (width, height))

# 遍历每个像素并进行二值化处理
for x in range(width):
    for y in range(height):
        r, g, b = img.getpixel((x, y))
        if r > g > b and r > 190 and g > 100 and b < 140:
            binary_img.putpixel((x, y), 1)

# 显示二值化后的图片
binary_img.show()

# 将二值化后的图片保存到文件
binary_img.save('output.bmp')

复现效果:
在这里插入图片描述2.2 Forest fire detection in YCbCr Space
在这里插入图片描述
原文图片:
在这里插入图片描述
复现代码:

import cv2

# 加载要转换的RGB图片
img = cv2.imread("RGB.jpg")

# 将RGB图片转换为YCbCr颜色空间图片
img_ycc = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)

# 分离Y、Cb、Cr三个通道并分别显示
y, cb, cr = cv2.split(img_ycc)
cv2.imshow("Y Channel", y)
cv2.imshow("Cb Channel", cb)
cv2.imshow("Cr Channel", cr)

# 等待按下任意按键后关闭窗口
cv2.waitKey(0)
cv2.destroyAllWindows()

复现效果:
在这里插入图片描述
From our analysis with various images like Fig. 8 above, it can be seen in the example of a fire image pixel at the coordinate of pixel (805,547), the value of pixels in Y, Cb, Cr channels are 189, 88 and 162 respectively. It means that Y(805,547) > Cr(805,547) > Cb(805,547). Based on the analysis results on other fire image pixels, we also achieve the trend that Y(x,y) ≥ Cr(x,y) > Cb(x,y). Hence, we propose that an image pixel is confirmed as fire image pixel when it satisfies the suggested condition 3 as below:
在这里插入图片描述
When separated from the original image from RGB color space to YCbCr color space, the fire pixels are “white” color in Y and Cb channels and “black” in Cr channel (See Fig. 8 for more details). The images in Y, Cb, and Cr channels are grayscale images with the values in the range of [0, 255]. The values will create the different shades of gray, and the zero and 255 values are related to black and white, respectively. Therefore, the fire pixel values in Y and Cr channels are more significant than the mean value pixel of Y and Cr components. Furthermore, the fire pixel values in Cb channel are smaller than the mean value pixel of Cb component. The mean values are calculated by the following formula:
在这里插入图片描述在这里插入图片描述
结合上述4个公式约束:
论文原图
在这里插入图片描述
复现代码:

import cv2
import numpy as np

# 读入彩色图片
img = cv2.imread("input_image.jpg")

# 将图片转换为YCrCb颜色空间
ycc = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)

# 计算YCrCb通道均值
mean_y = np.mean(ycc[:, :, 0])
mean_cr = np.mean(ycc[:, :, 1])
mean_cb = np.mean(ycc[:, :, 2])

# 提取各个通道,由于 Python 中的OpenCV默认颜色顺序为BGR,因此需要使用索引2、1和0
B, G, R = cv2.split(img)
Y, Cr, Cb = cv2.split(ycc)

# 初始化一个全零掩码数组,大小与图片相同,数据类型为np.uint8
mask = np.zeros(img.shape[:2], dtype=np.uint8)

# 将满足条件的像素设为1
mask[((R > G) & (G > B) & (R > 190) & (G > 100) & (B < 140) & (Y >= Cr) & (Cr >= Cb) & (Y > mean_y) & (Cr > mean_cr) & (Cb < mean_cb))] = 1

# 通过cv2.imshow()方法展示处理后的结果
cv2.imshow("Output Image", mask * 255)
cv2.waitKey(0)
cv2.destroyAllWindows()

该程序流程如下:
1.	使用 cv2.imread()读入输入的彩色图片。
2.	使用 cv2.cvtColor()将彩色图片转换为 YCrCb 颜色空间,以便可以方便地对通道进行操作。
3.	使用 np.mean()计算YCrCb通道的均值。
4.	使用 cv2.split() 将 YCrCb 图像分解为各个通道,以便逐通道进行处理。
5.	使用条件生成式生成掩码数组,满足条件的部分设为1,不满足条件的部分设为06.	使用 cv2.imshow() 显示结果。
最后,根据需要,使用其他操作来将生成的掩码数组应用于原始图像,例如将不满足条件的像素设为白色,满足条件的像素设为黑色。

复现效果:在这里插入图片描述
和原文存在一定的差!!
论文原图:
在这里插入图片描述
代码如上述
复现效果:
在这里插入图片描述
2.3 The correlation coefficient
As mentioned above, this method is based on the change of fire. Without this, fire-colored subjects can be incorrectly detected, such as a picture of fire and sunlight. It immensely increases the accuracy of fire recognition.
这里根据火焰的抖动特征,加入了动态因素,主要是根据相关系数判断是否是火焰:
在这里插入图片描述
整个视频图像的检测流程:
在这里插入图片描述
接下来文字相关的视频文件都来自youtube,无法下载得到,选择网上可找到的视频文件!!
根据帧差法,如何计算一段视频中的帧相关系数?

给出一段视频,根据帧差法,计算视频连续帧之间的相关系数
import cv2
import numpy as np

# 读入视频文件
cap = cv2.VideoCapture('your_video_file.mp4')

# 获取视频帧数和帧率
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
fps = int(cap.get(cv2.CAP_PROP_FPS))

# 初始化correlation数组用于存储每一帧与前一帧的相关系数
correlation = np.zeros(frame_count-1)

# 读入第一帧
_, last_frame = cap.read()

# 遍历视频帧
for i in range(frame_count-1):
    # 读入下一帧
    _, cur_frame = cap.read()

    # 转换成灰度图像
    last_gray = cv2.cvtColor(last_frame, cv2.COLOR_BGR2GRAY)
    cur_gray = cv2.cvtColor(cur_frame, cv2.COLOR_BGR2GRAY)

    # 计算两帧图像的差值,并对结果进行二值化处理
    diff = cv2.absdiff(last_gray, cur_gray)
    _, binary = cv2.threshold(diff, 30, 255, cv2.THRESH_BINARY)

    # 计算相关系数
    corr = np.corrcoef(last_gray.flatten(), cur_gray.flatten())[0,1]
    correlation[i] = corr

    # 显示当前帧和相关系数
    cv2.imshow('Current Frame', cur_frame)
    print('Correlation between frames', i+1, 'and', i+2, ':', corr)

    # 更新last_frame变量
    last_frame = cur_frame

    # 等待按下按键
    cv2.waitKey(0)

# 计算相关系数的平均值和标准差
mean_corr = np.mean(correlation)
std_corr = np.std(correlation)

# 输出相关系数的平均值和标准差
print('Average Correlation:', mean_corr)
print('Standard Deviation of Correlation:', std_corr)

# 释放窗口和资源
cv2.destroyAllWindows()
cap.release()
这段代码将计算视频中每一帧与前一帧的相关系数,并输出相关系数的平均值和标准差,您可以根据需要进行修改。

对于一段有火焰的视频,满足上述4个公式(分别是2个颜色空间)和火焰动态(相关系数)的检测流程和代码如下:
要求:

用python写一段程序处理一段视频,把满足以下条件视频帧的相关位置框出来并打上“有火情”的标签,统计满足以下条件视频帧的数量,保存处理后的视频文件

条件1:视频帧满足R(x,y)>𝐺(𝑥,𝑦)>𝐵(𝑥,𝑦)、R(x,y)>190,𝐺(𝑥,𝑦)>100、𝐵(𝑥,𝑦)<140、Y(x,y)≥Cr(x,y)、𝐶𝑟(x,y)≥Cb(x,y)、Y(x,y)>𝑌通道均值、Cr(x,y)>𝐶𝑟通道均值、Cb(x,y)<𝐶𝑏通道均值条件

条件2:基于动态火焰检测中的帧差法,相关系数满足大于0.95

代码如下:

import cv2
import numpy as np

# 定义全局变量
fire_frames = []  # 存储检测到火情的帧编号

# 定义函数,判断当前帧是否存在火情
def detect_fire(frame):
    # 转换成HSV颜色空间
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    # 按照条件1进行颜色过滤
    lower_color = (0, 50, 140)
    upper_color = (30, 240, 255)
    mask = cv2.inRange(hsv, lower_color, upper_color)
    filtered = cv2.bitwise_and(frame, frame, mask=mask)

    # 计算Y、Cr和Cb通道均值
    Y, Cr, Cb = cv2.split(cv2.cvtColor(filtered, cv2.COLOR_BGR2YCrCb))
    (mean_Y, mean_Cr, mean_Cb) = (np.mean(Y), np.mean(Cr), np.mean(Cb))

    # 获取红、绿、蓝三个通道
    (B, G, R) = cv2.split(filtered)

    # 计算相关条件的满足情况
    R_temp = np.array(R).astype(float)
    G_temp = np.array(G).astype(float)
    B_temp = np.array(B).astype(float)
    check1 = np.logical_and(np.logical_and(R_temp > G_temp, G_temp > B_temp), R_temp > 190)
    check2 = G_temp > 100
    check3 = B_temp < 140
    check4 = Y >= Cr
    check5 = Cr >= Cb
    check6 = Y > mean_Y
    check7 = Cr > mean_Cr
    check8 = Cb < mean_Cb

    # 满足所有条件,则标记有火情
    check = np.logical_and(np.logical_and(np.logical_and(np.logical_and(np.logical_and(np.logical_and(np.logical_and(check1, check2), check3), check4), check5), check6), check7), check8)
    if np.sum(check) > 0:
        return True
    else:
        return False

# 读取视频文件
cap = cv2.VideoCapture('d.mp4')

# 获取视频帧数和帧率
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
fps = int(cap.get(cv2.CAP_PROP_FPS))

# 定义输出视频文件
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('output.mp4', fourcc, fps, (int(cap.get(3)), int(cap.get(4))))

# 读入第一帧
_, last_frame = cap.read()

# 遍历视频帧
for i in range(frame_count-1):
    # 读入下一帧
    _, cur_frame = cap.read()

    # 计算帧差法相关系数
    corr = np.corrcoef(cv2.cvtColor(last_frame, cv2.COLOR_BGR2GRAY).flatten(), cv2.cvtColor(cur_frame, cv2.COLOR_BGR2GRAY).flatten())[0,1]

    # 判断当前帧是否存在火情
    if detect_fire(cur_frame) and corr > 0.95:
        # 添加当前帧编号到fire_frames列表中
        fire_frames.append(i+1)

        # 在当前帧中标出有火情的区域,并添加警告信息
        cv2.rectangle(cur_frame, (0,0), (150,60), (255,255,255), -1)
        cv2.putText(cur_frame, 'Warning: Fire Detected!', (10,40), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0,0,255), 2)

    # 将当前帧写入输出视频文件
    out.write(cur_frame)

    # 更新last_frame变量
    last_frame = cur_frame

    # 显示当前帧和相关系数
    cv2.imshow('Current Frame', cur_frame)
    print('Correlation between frames', i+1, 'and', i+2, ':', corr)

    # 等待按下按键
    cv2.waitKey(0)

# 输出检测到火情的帧数量
print('Number of frames with fire:', len(fire_frames))

# 释放窗口和资源
cv2.destroyAllWindows()
cap.release()
out.release()
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值