[OpenCV+VS2015]火焰检测算法(RGB判据)

[OpenCV+VS2015]火焰检测算法(RGB判据)

1 RGB颜色判据介绍

1.1 RGB 颜色模型

根据三基色原理,用基色光单位来表示光的量,则在RGB颜色空间,任意色光F都可以用R、G、B三色不同分量的相加混合而成:

F=r[R]+g[G]+b[B]

当三基色分量都为0(最弱)时混合为黑色光;当三基色分量都为k(最强)时混合为白。改变了F的坐标值,也即改变了F的色值。
采用三维空间来进行描述(如图1),把三种成分的数值当做欧几里得空间中普通笛卡尔坐标系的坐标值。在RGB模型中使用0到1之间的非负数作为立方体的坐标值,将原点(0,0,0)作为黑色,强度值沿坐标轴方向递增到达位于对角线(1,1,1)处的白色。

在这里插入图片描述

图 1 RGB三维空间

一个RGB组合(r,g,b)表示代表一个给定颜色的点在立方体内部、表面或者边上的三维坐标。这种表示方法使得在计算两个颜色相近程度时只需简单计算它们之间的距离:距离越短颜色越接近。

1.2 RGB颜色判据

眼的视网膜上有两类感光器:锥状体和杆状体。锥状体主要位于视网膜的中间部分,称之为中央凹,且对颜色高度敏感,称为白昼视觉或亮视觉;杆状体分布面积较大,用来给出视野内的一般的总体图像,没有彩色感觉,而对低照明度敏感,称为微光视觉或暗视觉。由于锥状体对红、绿、蓝三种颜色的光很敏感,因此一般用于人眼观看的颜色模型是RGB模型。一般来说,无论是在网上下载的图片或视频,还是从摄像机得来的录像,都是RGB模型。
对于普通火焰来说,它的红色分量和绿色分量会很大,并且绿色分量会大于蓝色分量,所以我们写出如下不等式:
R > RedThreshold
R>G>B
其中,RedThreshold为红色分量的阈值。
经过这两个不等式的判断,我们可以通过二值图的方法得到火焰的外形,如图2所示。
在这里插入图片描述

(a)火焰原图
在这里插入图片描述

(b)二值化后图像
图2 用RGB判据对图片二值化

2 算法简介

首先导入一张图片,然后对该图片进行RGB颜色判据,从而二值化,然后对二值化后的图像进行框选选出火焰部分。

2.1 火焰检测函数void FireDetection(Mat &image_input, Mat &image_output)

首先先要检测函数导入的两个参量是否有错,使用if语句进行判断。然后使用image_input.at的方法将RGB三个通道分开。
其中要注意的是RGB三个通道的顺序,在程序中B是第一个,R是最后一个。
然后,把分离出的R、G、B分量进行RGB颜色判据判断,从而二值化。最后输出原始图像和二值化图像。

2.2 框选检测函数void DrawFire(Mat &inputImg, Mat foreImg)

首先保存二值化后的整个火焰的轮廓,然后使用迭代器对每个点进行判断是否是火焰,判断为是则框选,最后输出图像。

2.3 撸代码

void FireDetection(Mat &image_input, Mat &image_output)
{
	image_output = Mat::zeros(image_input.size(), CV_8UC1); //初始化output矩阵
	if (image_input.empty()) {
		printf("could not load image...please try again!/n ");
	}
	if (image_output.empty()||image_output.channels()!= 1) {
		printf("could not initialize output...please try again!/n ");
	}
	/*初始化程序报错*/

	for (int i = 0; i < image_input.rows; i++) {
		for (int j = 0; j < image_input.cols; j++) {
			float R, G, B;
			B = image_input.at<uchar>(i, image_input.channels()*j + 0);
			G = image_input.at<uchar>(i, image_input.channels()*j + 1);
			R = image_input.at<uchar>(i, image_input.channels()*j + 2);

			int minRGB = min(min(R, G), B);
			double S = 1 - 3.0*minRGB / (R + G + B);

			int RedThreshold = 115;
			if (R > RedThreshold && R > G&&G > B)
			{
				image_output.at<uchar>(i, j) = 255;
			}
			else 
			{
				image_output.at<uchar>(i, j) = 0;
			}
		}
	}
	namedWindow("original image", WINDOW_AUTOSIZE);
	imshow("original image", image_input);
	namedWindow("binary image", WINDOW_AUTOSIZE);
	imshow("binary image", image_output);

	DrawFire(image_input, image_output);
}

void DrawFire(Mat &inputImg, Mat foreImg)
{
	vector<vector<Point>> contours_set;//保存轮廓提取后的点集及拓扑关系  

	findContours(foreImg, contours_set, RETR_EXTERNAL, CHAIN_APPROX_NONE);

	Mat result0;
	Scalar holeColor;
	Scalar externalColor;

	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)
		{
			rectangle(inputImg, rect, Scalar(0, 255, 0));  //scalar表示是什么颜色去框选
			++iter;
		}
		else
		{
			iter = contours_set.erase(iter);
		}
	}
	imshow("Detect Fire", inputImg);
}

效果如下
在这里插入图片描述
在这里插入图片描述
感觉还是阔以

  • 4
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值