概述
基于VS和opencv的烟雾识别
1.1 采用两帧图像差分法进行运动物体的识别
原理:两帧间差分算法是目前运动对象检测中在视频分割中常用的一种方法,即相邻两帧图像差分法,在这里的应用主要是考虑到比较容易获得运动物体(烟雾和非烟雾)的轮廓,对于不运动的物体则不会显示,这样就可以得到需要关注的运动部分,为下一步在此基础上剔除疑似烟雾打下良好的基础,其基本原理是通过计算相邻帧图像中像素点的灰度差计算出运动物体的位置和形状等信息。基于相邻两帧图像差分法的运动目标提取的主要优点:算法实现简单,程序设计复杂度低;易于实现实时监控;光照的适应性强,受目标阴影影响不大。
代码:
Mat MoveDetect(Mat temp, Mat frame)
{
Mat result = frame.clone(); //1.将background和frame转为灰度图
Mat gray1, gray2;
cvtColor(temp, gray1, CV_BGR2GRAY);
cvtColor(frame, gray2, CV_BGR2GRAY);
//2.将background和frame做差
Mat diff;
absdiff(gray1, gray2, diff);
//imshow("diff", diff);
//3.对差值图diff_thresh进行阈值化处理
Mat diff_thresh;
threshold(diff, diff_thresh, 50, 255, CV_THRESH_BINARY);
//imshow("diff_thresh", diff_thresh);
//4.腐蚀
Mat kernel_erode = getStructuringElement(MORPH_RECT, Size(3, 3));
Mat kernel_dilate = getStructuringElement(MORPH_RECT, Size(18, 18));
erode(diff_thresh, diff_thresh, kernel_erode);
//imshow("erode", diff_thresh);
//5.膨胀
dilate(diff_thresh, diff_thresh, kernel_dilate);
//imshow("dilate", diff_thresh);
//6.查找轮廓并绘制轮廓
findContours(diff_thresh, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, Point());
//drawContours(result, contours, -1, Scalar(0, 0, 255), 2);//在result上绘制轮廓
//7.查找正外接矩形
vector<Rect> boundRect(contours.size());
for (int i = 0; i < contours.size(); i++)
{
boundRect[i] = boundingRect(contours[i]);
a1 = 1;
rectangle(result, boundRect[i], Scalar(255, 0, 0), 2);
//在result上绘制正外接矩形
}
//if (contours.size() != 0) { a1 = 1; }
//else { a1 = 0; }
imshow("Binary", result);
return result;//返回result
}
- 2 在运动物体识别的基础上进行烟雾的传统颜色RGB模型的判断
原理:人眼所能接受的可见光的波长红,绿,蓝 3 色一样,每一个像素的颜色是由 3 个颜色通道所组成,RGB 颜色系统可以让视频检测中分析图像像素各个分量颜色值。烟雾像素点的R、G、B三个颜色分量值相差无几。在运动物体的标记框内进行烟雾的识别,更加有利于提高判断是真实烟雾的可能性。因此判断条件为:
C(min)=min(R,G,B) 条件1
C(max)=max(R,G,B) 条件2
I=(R,G,B)/3 条件3
给出以下三个规则:
|C(max)-C(min)|<T 规则1
L1<I<L2 规则2
D1<I<D2 规则3
判断条件为:
if((规则1 AND规则2) OR(规则1 AND规则3)) 为可以烟雾像素;
if ((fabs(maxValue - minValue)<T4&&(150<I&&I<220))||((80<I&&I<150) && fabs(maxValue - minValue)< T4));
测试视频:
以下代码测试是不在运动物体判断的基础上进行整个视频的测试
#include "opencv2/opencv.hpp"
#include <iostream>
#include "cv.h"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/core/core.hpp"
using namespace cv;
using namespace std;
int T2 = 20;
int T3 = 20;
float T4 = 20;
int a1 = 0;
int redThre = 128; // 115~135
int saturationTh = 60; //55~65
vector<vector<Point> > contours;
Mat result;
Mat temp;
Mat MoveDetect(Mat temp, Mat frame);
Mat CheckColor(Mat &inImg);
void DrawFire(Mat &inputImg, Mat foreImg);
int main()
{
//VideoCapture capture(0);
VideoCapture capture;
capture.open("E:/烟雾素材/yw6.mp4");
capture >> temp;
while (1)
{
Mat frame;
capture >> frame;
if (frame.empty())
break;
MoveDetect(temp, frame);
temp = frame.clone();
//namedWindow("Control", CV_WINDOW_AUTOSIZE);
//cvCreateTrackbar("redThre", "Control", &redThre, 255);
//cvCreateTrackbar("saturationTh", "Control", &saturationTh, 255);
//if (a1 == 1) {
CheckColor(frame);
//}
waitKey(1);
}
return 0;
}
Mat MoveDetect(Mat temp, Mat frame)
{
Mat result = frame.clone(); //1.将background和frame转为灰度图
Mat gray1, gray2;
cvtColor(temp, gray1, CV_BGR2GRAY);
cvtColor(frame, gray2, CV_BGR2GRAY);
//2.将background和frame做差
Mat diff;
absdiff(gray1, gray2, diff);
//imshow("diff", diff);
//3.对差值图diff_thresh进行阈值化处理
Mat diff_thresh;
threshold(diff, diff_thresh, 50, 255, CV_THRESH_BINARY);
//imshow("diff_thresh", diff_thresh);
//4.腐蚀
Mat kernel_erode = getStructuringElement(MORPH_RECT, Size(3, 3));
Mat kernel_dilate = getStructuringElement(MORPH_RECT, Size(18, 18));
erode(diff_thresh, diff_thresh, kernel_erode);
//imshow("erode", diff_thresh);
//5.膨胀
dilate(diff_thresh, diff_thresh, kernel_dilate);
//imshow("dilate", diff_thresh);
//6.查找轮廓并绘制轮廓
findContours(diff_thresh, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, Point());
//drawContours(result, contours, -1, Scalar(0, 0, 255), 2);//在result上绘制轮廓
//7.查找正外接矩形
vector<Rect> boundRect(contours.size());
for (int i = 0; i < contours.size(); i++)
{
boundRect[i] = boundingRect(contours[i]);
a1 = 1;
rectangle(result, boundRect[i], Scalar(255, 0, 0), 2);
//在result上绘制正外接矩形
}
//if (contours.size() != 0) { a1 = 1; }
//else { a1 = 0; }
imshow("Binary", result);
return result;//返回result
}
Mat CheckColor(Mat &inImg)
{
Mat fireImg;
fireImg.create(inImg.size(), CV_8UC1);
Mat multiRGB[3];
int a = inImg.channels();
split(inImg, multiRGB); //将图片拆分成R,G,B,三通道的颜色
for (int i = 0; i < inImg.rows; i++)
{
for (int j = 0; j < inImg.cols; j++)
{
float B, G, R;
B = multiRGB[0].at<uchar>(i, j); //每个像素的R,G,B值,动态地址计算法
G = multiRGB[1].at<uchar>(i, j);
R = multiRGB[2].at<uchar>(i, j);
float maxValue = max(max(B, G), R);
float minValue = min(min(B, G), R);
//与HSI中S分量的计算公式
double S = (1 - 3.0*minValue / (R + G + B));//
float I = (R + G + B) / 3;
//if(((fabs(maxValue-minValue)<T4)&&(150<I&&I<220))||((80<I&&I<150)&&(maxValue==B&&fabs(maxValue-minValue)<T4)))
if ((fabs(maxValue - minValue)<T4&&(150<I&&I<220))||((80<I&&I<150) && fabs(maxValue - minValue)< T4))
{
fireImg.at<uchar>(i, j) = 255;
}
else
{
fireImg.at<uchar>(i, j) = 0;
}
}
}
//erode(fireImg, fireImg, Mat(3, 3, CV_8UC1));
//GaussianBlur(fireImg, fireImg, Size(5, 5), 0, 0);
medianBlur(fireImg, fireImg, 5);
dilate(fireImg, fireImg, Mat(5, 5, CV_8UC1));
//imshow("Binary", fireImg);
DrawFire(inImg, fireImg);
return fireImg;
}
void DrawFire(Mat &inputImg, Mat foreImg)
{
vector<vector<Point>> contours_set;//保存轮廓提取后的点集及拓扑关系
findContours(foreImg, contours_set, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
Point point1;
Point point2;
float a = 0.4, b = 0.75;
float xmin1 = a * inputImg.cols, ymin1 = inputImg.rows, xmax1 = 0, ymax1 = 0;
float xmin2 = b * inputImg.cols, ymin2 = inputImg.rows, xmax2 = a * inputImg.cols, ymax2 = 0;
float xmin3 = inputImg.cols, ymin3 = inputImg.rows, xmax3 = b * inputImg.cols, ymax3 = 0;
Rect finalRect1;
Rect finalRect2;
Rect finalRect3;
vector<vector<Point> >::iterator iter = contours_set.begin();
for (; iter != contours_set.end();)
{
Rect rect = boundingRect(*iter);
float radius;
Point2f center;
minEnclosingCircle(*iter, center, radius);
if (rect.area() > 0)
{
point1.x = rect.x;
point1.y = rect.y;
point2.x = point1.x + rect.width;
point2.y = point1.y + rect.height;
if (point2.x < a*inputImg.cols)
{
if (point1.x < xmin1)
xmin1 = point1.x;
if (point1.y < ymin1)
ymin1 = point1.y;
if (point2.x > xmax1 && point2.x < xmax2)
xmax1 = point2.x;
if (point2.y > ymax1)
ymax1 = point2.y;
}
if (point2.x < b*inputImg.cols&&point2.x > a*inputImg.cols)
{
if (point1.x < xmin2 && point1.x>xmin1)
xmin2 = point1.x;
if (point1.y < ymin2)
ymin2 = point1.y;
if (point2.x > xmax2 && point2.x < xmax3)
xmax2 = point2.x;
if (point2.y > ymax2)
ymax2 = point2.y;
}
if (point2.x < inputImg.cols&&point2.x > b*inputImg.cols)
{
if (point1.x < xmin3 && point1.x>xmin2)
xmin3 = point1.x;
if (point1.y < ymin3)
ymin3 = point1.y;
if (point2.x > xmax3)
xmax3 = point2.x;
if (point2.y > ymax3)
ymax3 = point2.y;
}
//rectangle(inputImg, rect, Scalar(0, 255, 0));
++iter;
}
else
{
iter = contours_set.erase(iter);
}
}
if (xmin1 == a * inputImg.cols&& ymin1 == inputImg.rows&&xmax1 == 0 && ymax1 == 0)
{
xmin1 = ymin1 = xmax1 = ymax1 = 0;
}
if (xmin2 == b * inputImg.cols&& ymin2 == inputImg.rows&& xmax2 == a * inputImg.cols&& ymax2 == 0)
{
xmin2 = ymin2 = xmax2 = ymax2 = 0;
}
if (xmin3 == inputImg.cols&&ymin3 == inputImg.rows&& xmax3 == b * inputImg.cols&& ymax3 == 0)
{
xmin3 = ymin3 = xmax3 = ymax3 = 0;
}
finalRect1 = Rect(xmin1, ymin1, xmax1 - xmin1, ymax1 - ymin1);
finalRect2 = Rect(xmin2, ymin2, xmax2 - xmin2, ymax2 - ymin2);
finalRect3 = Rect(xmin3, ymin3, xmax3 - xmin3, ymax3 - ymin3);
rectangle(inputImg, finalRect1, Scalar(0, 255, 0));
rectangle(inputImg, finalRect2, Scalar(0, 255, 0));
rectangle(inputImg, finalRect3, Scalar(0, 255, 0));
/*vector<Rect> boundRect(contours.size());
for (int i = 0; i < contours.size(); i++)
{
boundRect[i] = boundingRect(contours[i]);
}
for (int i = 0; i < contours.size(); i++)
{
if (boundRect[i].x < finalRect1.x && (boundRect[i].x + boundRect[i].width) < finalRect1.x) {}
else if (boundRect[i].x < (finalRect1.x + finalRect1.width) && (boundRect[i].x + boundRect[i].width) < (finalRect1.x + finalRect1.width)) {}
else if (boundRect[i].x > finalRect1.x && (boundRect[i].x + boundRect[i].width) > finalRect1.x) {}
else if (boundRect[i].x > (finalRect1.x + finalRect1.width) && (boundRect[i].x + boundRect[i].width) > (finalRect1.x + finalRect1.width)) {}
else if (boundRect[i].y < finalRect1.y && (boundRect[i].y + boundRect[i].height) < finalRect1.y) {}
else if (boundRect[i].y < (finalRect1.y + finalRect1.height) && (boundRect[i].y + boundRect[i].height) < (finalRect1.y + finalRect1.height)) {}
else if (boundRect[i].y > finalRect1.y && (boundRect[i].y + boundRect[i].height) > finalRect1.y) {}
else if (boundRect[i].y > (finalRect1.y + finalRect1.height) && (boundRect[i].y + boundRect[i].height) > (finalRect1.y + finalRect1.height)) {}
else { rectangle(inputImg, finalRect1, Scalar(0, 255, 0)); }
}
for (int i = 0; i < contours.size(); i++)
{
if (boundRect[i].x < finalRect2.x && (boundRect[i].x + boundRect[i].width) < finalRect2.x) {}
else if (boundRect[i].x < (finalRect2.x + finalRect2.width) && (boundRect[i].x + boundRect[i].width) < (finalRect2.x + finalRect2.width)) {}
else if (boundRect[i].x > finalRect2.x && (boundRect[i].x + boundRect[i].width) > finalRect2.x) {}
else if (boundRect[i].x > (finalRect2.x + finalRect2.width) && (boundRect[i].x + boundRect[i].width) > (finalRect2.x + finalRect2.width)) {}
else if (boundRect[i].y < finalRect2.y && (boundRect[i].y + boundRect[i].height) < finalRect2.y) {}
else if (boundRect[i].y < (finalRect2.y + finalRect2.height) && (boundRect[i].y + boundRect[i].height) < (finalRect2.y + finalRect2.height)) {}
else if (boundRect[i].y > finalRect2.y && (boundRect[i].y + boundRect[i].height) > finalRect2.y) {}
else if (boundRect[i].y > (finalRect2.y + finalRect2.height) && (boundRect[i].y + boundRect[i].height) > (finalRect2.y + finalRect2.height)) {}
else {rectangle(inputImg, finalRect2, Scalar(0, 255, 0));}
}
for (int i = 0; i < contours.size(); i++)
{
if (boundRect[i].x < finalRect3.x && (boundRect[i].x + boundRect[i].width) < finalRect3.x) {}
else if (boundRect[i].x < (finalRect3.x + finalRect3.width) && (boundRect[i].x + boundRect[i].width) < (finalRect3.x + finalRect3.width)) {}
else if (boundRect[i].x > finalRect3.x && (boundRect[i].x + boundRect[i].width) > finalRect3.x) {}
else if (boundRect[i].x > (finalRect3.x + finalRect3.width) && (boundRect[i].x + boundRect[i].width) > (finalRect3.x + finalRect3.width)) {}
else if (boundRect[i].y < finalRect3.y && (boundRect[i].y + boundRect[i].height) < finalRect3.y) {}
else if (boundRect[i].y < (finalRect3.y + finalRect3.height) && (boundRect[i].y + boundRect[i].height) < (finalRect3.y + finalRect3.height)) {}
else if (boundRect[i].y > finalRect3.y && (boundRect[i].y + boundRect[i].height) > finalRect3.y) {}
else if (boundRect[i].y > (finalRect3.y + finalRect3.height) && (boundRect[i].y + boundRect[i].height) > (finalRect3.y + finalRect3.height)) {}
else {rectangle(inputImg, finalRect3, Scalar(0, 255, 0));}
}*/
imshow("Fire_Detection", inputImg);
}
附上本次测试的测试素材视频:https://video.699pic.com/videos/ing0/ING_VID_0048933_10s.mp4(单击右键另存为即可,不需要花钱)
最后
以上就是寂寞可乐为你收集整理的基于VS和opencv的烟雾识别的全部内容,希望文章能够帮你解决基于VS和opencv的烟雾识别所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复