记录西安电子科技大学星火杯软件赛道一等奖(大一)
include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
bool detectSmoke(Mat frame) {
// 实现烟雾检测算法
// 使用简单的颜色阈值
// 转换为HSV颜色空间
Mat hsv;
cvtColor(frame, hsv, COLOR_BGR2HSV);
cv::Scalar lowerBound(0, 50, 100); // 请根据实际情况调整下限
cv::Scalar upperBound(10, 255, 255); // 请根据实际情况调整上限
// 通过颜色阈值获取烟雾区域的二值图像
Mat mask;
inRange(hsv, lowerBound, upperBound, mask);
// 使用形态学操作进行噪音过滤
Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(5, 5));
morphologyEx(mask, mask, MORPH_OPEN, kernel);
morphologyEx(mask, mask, MORPH_CLOSE, kernel);
// 计算二值图像中白色像素的数量
int whitePixels = countNonZero(mask);
putText(frame, "White Pixels: " + std::to_string(whitePixels), Point(10, 30), FONT_HERSHEY_SIMPLEX, 1, Scalar(255, 255, 255), 2);
// 根据实际情况调整阈值
return whitePixels > 5000;
}
bool detectMotion(Mat prevFrame, Mat currentFrame) {
// 运动检测算法
// 使用帧差
Mat diff;
absdiff(prevFrame, currentFrame, diff);
Mat grayDiff;
cvtColor(diff, grayDiff, COLOR_BGR2GRAY);
Mat thresholdDiff;
threshold(grayDiff, thresholdDiff, 30, 255, THRESH_BINARY);
putText(currentFrame, "motion level: " + std::to_string(countNonZero(thresholdDiff)), Point(10, 60), FONT_HERSHEY_SIMPLEX, 1, Scalar(255, 255, 255), 2);
return countNonZero(thresholdDiff) > 4000; // 根据实际情况调整阈值
}
bool detectLightChange(Mat prevFrame, Mat currentFrame) {
// 的光照变化检测算法
// 使用平均强度差异
Mat diff;
absdiff(prevFrame, currentFrame, diff);
Mat grayDiff;
cvtColor(diff, grayDiff, COLOR_BGR2GRAY);
putText(currentFrame, "light level " + std::to_string(mean(grayDiff)[0]), Point(10, 90), FONT_HERSHEY_SIMPLEX, 1, Scalar(255, 255, 255), 2);
return mean(grayDiff)[0] > 2; // 根据实际情况调整阈值
}
void drawSmokeRegion(Mat& frame, std::vector<std::vector<Point>>& contours,double minContourAreaThreshold) {
for (const auto& contour : contours) {
double area = contourArea(contour);
if (area > minContourAreaThreshold) {
std::vector<Point> hull;
convexHull(contour, hull);
drawContours(frame, std::vector<std::vector<Point>>{hull}, 0, Scalar(0, 0, 255), 3); // 橙红色
}
}
}
int main()
{
double minContourAreaThreshold = 300.0; // 设置阈值
int smoke,light,motion;
smoke=0;
light =0;
motion =0;
int sos =0;
VideoCapture capture("/home/a/Desktop/123.mp4");
//测试视频路径
///home/a/Desktop/IMG_2960.MP4
///home/a/Desktop/RPReplay_Final1701363220.MP4
///home/a/Desktop/b4412ebf2a608091ca2bbbf005a4e304.mp4
///home/a/Desktop/f142649fca7338a9a5f821069df06993_raw.mp4
///home/a/Desktop/eca471f4a7b82dd6866cdb9162536eca.mp4
///home/a/Desktop/e007a752da82088104d98762b9f86bbf_raw.mp4
///home/a/Desktop/e1dd4b101a51f8248e0ee46ec0990efa_raw.mp4
///home/a/Desktop/bb0bbb3bdbf49cdd6fdf0789e513a1a1_raw.mp4
///home/a/Desktop/b4412ebf2a608091ca2bbbf005a4e304_raw.mp4
///home/a/Desktop/59ef339385022b76dda6bf13223c.mp4
///home/a/Desktop/26c24abe36157021d3628191229c213d_raw.mp4
if (!capture.isOpened()) {
std::cout << "Error: Couldn't open the video file." << std::endl;
return -1;
}
Mat prevFrame;
capture.read(prevFrame);
while (capture.isOpened()) {
Mat currentFrame;
Mat currentFrame1;
capture.read(currentFrame);
if (currentFrame.empty()) {
break;
}
Mat hsv;
Mat image = currentFrame.clone();
resize(image, image, Size(), 0.5, 0.5);//!!!!!!!!
cvtColor(image, hsv, COLOR_BGR2HSV);
cv::Scalar lowerBound(0,50,100); // 请根据实际情况调整下限
cv::Scalar upperBound(10,255, 255); // 请根据实际情况调整上限
// 通过颜色阈值获取烟雾区域的二值图像
Mat mask;
inRange(hsv, lowerBound, upperBound, mask);
// 查找橙红色区域的轮廓
std::vector<std::vector<Point>> contours;
findContours(mask, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
Mat smokeRegion = currentFrame.clone();
resize(smokeRegion,smokeRegion, Size(), 0.5, 0.5);
drawSmokeRegion(smokeRegion, contours,minContourAreaThreshold);
imshow("Smoke Region", smokeRegion);
// 烟雾检测
if (detectSmoke(currentFrame)) {
std::cout << "have smoke" << std::endl;
smoke++;
}
// 运动检测
if (detectMotion(prevFrame, currentFrame)) {
std::cout << "Motion Detection: Anomalous Motion Occurred!" << std::endl;
motion++;
}
// 光照变化检测
if (detectLightChange(prevFrame, currentFrame)) {
std::cout << "Light Change Detection: Possible Fire Occurred!" << std::endl;
light++;
}
if(detectSmoke(currentFrame)&&detectMotion(prevFrame, currentFrame)&&detectLightChange(prevFrame, currentFrame))
{
std::cout<<"SOS-SOS"<<std::endl;
sos++;
}
// 显示当前帧
imshow("Video Frame", currentFrame);
// 更新前一帧
prevFrame = currentFrame.clone();
// 按 'q' 键退出循环
if (waitKey(20) == 'q') {
break;
}
}
std::ofstream outputFile("huozai.txt");
if (outputFile.is_open()) {
// 将文本内容写入文件
outputFile << "<<data数据>>"<<"\n";
outputFile << "smoke烟雾监测等级(次数):"<<smoke<<"\n";
outputFile << "light光感变化程度:"<<light<<"\n";
outputFile <<"motion图面运动变化程度:"<<motion<<"\n";
outputFile<<"SOS-SOS火灾可信程度等级:"<<sos<<"\n";
if(sos>10&&sos<20)
{
outputFile << "%95火灾可信度"<<"\n";
}
else if(sos>=5&&sos<10) outputFile << "%70火灾可信度"<<"\n";
else if(sos>=20) outputFile << "%99火灾可信度"<<"\n";
else if(sos==0) outputFile << "%0火灾可信度"<<"\n";
else outputFile << "%50火灾可信度"<<"\n";
outputFile<<"检测依据:烟雾监测等级,光感变化程度,图面运动变化程度,为火灾的基本监测目标,三者以科学关系并满足一定情况的条件下,>会对应产生SOS-SOS火灾可信程度,以此测算火灾可能度"<<"\n";
// 关闭文件
outputFile.close();
std::cout << "文本写入完成。" << std::endl;
} else {
std::cout << "无法打开文件。" << std::endl;
}
// 释放资源
capture.release();
destroyAllWindows();
return 0;
}