上文向大家介绍了如何用最简单的RGB判据来初步提取火焰区域,现在我要给大家分享的是一种更加直观的判据——HSI判据。
为什么说HSI判据是更加直观的判据呢?老规矩,先介绍一下HSI色彩模型: HSI颜色模型用H、S、I三参数描述颜色特性,其中:
H表示颜色的色调,它表示人的感官对不同颜色的感受,如红色、绿色、蓝色等,它也可表示一定范围的颜色,如暖色、冷色等。
H的单位是°,代表与红轴的角度。

    S表示颜色的饱和度,纯光谱色是完全饱和的,加入白光会稀释饱和度。饱和度越大,颜色看起来就会越鲜艳。
I对应成像亮度和图像灰度。 HSI模型的建立基于两个重要的事实: ① I分量与图像的彩色信息无关;② H和S分量与人感受颜色的方式是紧密相联的。
这些特点使得HSI模型非常适合彩色特性检测与分析。 对比一下RGB和HSI模型:

    得出由RGB模型转化为HSI模型的公式:

    假设R、G、B分量已经归一化到[0,1],那么求出来的S分量和I分量的值也会被归一化到[0,1]。当S分量为0的时候,对应的H分量也应该为0。

    用OpenCV1.0可以根据上面的公式和条件写出模型转化函数的代码:
int cvBGR2HSI(IplImage*img_bgr, IplImage*img_hsi){
if (img_bgr == NULL || img_hsi == NULL){
printf("func cvBGR2HSI Error:\n");
printf("img_bgr == NULL || img_hsi == NULL\n");
return -1;
} if (img_bgr->nChannels != 3 || img_hsi->nChannels != 3){
printf("func cvBGR2HSI Error:\n");
printf("img_bgr->nChannels != 3 || img_hsi->nChannels != 3\n");
return -1;
} double eps = 1.111e-016;
double pi = 3.1416;
double num = 0;
double den = 0;
double theta = 0;
double R, G, B, H, S, I;
for (int i = 0; i < img_bgr->height; i++){
uchar*ptr1 = (uchar*)(img_bgr->imageData + i*img_bgr->widthStep);
uchar*ptr2 = (uchar*)(img_hsi->imageData + i*img_hsi->widthStep);
for (int j = 0; j < img_bgr->width; j++){
R = double(ptr1[3 * j + 2]) / 255.0;
G = double(ptr1[3 * j + 1]) / 255.0;
B = double(ptr1[3 * j + 0]) / 255.0;
num = 0.5*((R - G) + (R - B));
den = sqrt((R - G)*(R - G) + (R - B)*(G - B));
theta = acos(num / (den + eps)); H = theta;
if (B>G){
H = 2 * pi - H;
}
H = H / (2 * pi);
num = min(min(R, G), B);
den = R + G + B;
if (den < eps){
den = eps;
}
S = 1 - 3 * num / den;
if (S < eps){
H = 0;
}
I = (R + G + B) / 3.0; ptr2[3 * j + 0] = H * 360;
ptr2[3 * j + 1] = S * 255;
ptr2[3 * j + 2] = I * 255;
}
}
return 0;
}
   在代码中要注意的是在OpenCV中RGB三通道的排列顺序:先存放B分量,再存放G分量,最后才是R分量,这与MATLAB里面的规则是不同的。

有了模型转化函数之后,我们就可以在HSI色彩模型内使用HSI判据了。HSI判据很简单,也很直观,它的规则是每个分量设定两个阈值,满足
阈值条件的置1,不满足的置0。具体表达式如下:
H_min < H < H_max AND
S_min < S < S_max AND
I_min < I < I_max 在OpenCV1.0中可以轻松写出上面的代码:
int cvHSI_CHK(IplImage*img_hsi, IplImage*hsi_chk, int H_min, int H_max, int S_min, int S_max, int I_min, int I_max)
{
if (img_hsi == NULL || hsi_chk == NULL){
printf("func cvHSI_CHK Error:\n");
printf("img_hsi == NULL || hsi_chk == NULL)\n");
return -1;
} if (img_hsi->nChannels != 3 || hsi_chk->nChannels != 1){
printf("func cvHSI_CHK Error:\n");
printf("img_hsi->nChannels != 3 || hsi_chk->nChannels != 1)\n");
return -1;
} CvSize size = cvGetSize(img_hsi); IplImage*H = cvCreateImage(size, 8, 1);
IplImage*S = cvCreateImage(size, 8, 1);
IplImage*I = cvCreateImage(size, 8, 1);
IplImage*mask = cvCreateImage(size, 8, 1); cvSplit(img_hsi, H, S, I, NULL); cvCmpS(H, H_min, mask, CV_CMP_GE); cvCmpS(H, H_max, H, CV_CMP_LE);
cvMul(H, mask, H); cvCmpS(S, S_min, mask, CV_CMP_GE);
cvCmpS(S, S_max, S, CV_CMP_LE);
cvMul(S, mask, S); cvCmpS(I, I_min, mask, CV_CMP_GE);
cvCmpS(I, I_max, I, CV_CMP_LE);
cvMul(I, mask, I); cvMul(H, S, H);
cvMul(H, I, hsi_chk);
cvConvertScale(hsi_chk, hsi_chk, 1.0 / 255); cvReleaseImage(&H);
cvReleaseImage(&S);
cvReleaseImage(&I);
cvReleaseImage(&mask); return 0;
}
 根据实验经验,博主给出一组参考阈值:
    H_min = 0    H_max = 60
S_min = 20 S_max = 100
I_min = 100 I_max = 255 参考上面给出的色相环可以轻松设定H分量的两个阈值,如果是想要检测其他颜色的火焰,可以根据需要做修改。
S分量的阈值较小,这与火焰所处的环境有关,若是在露天较明亮的地方检验,则需要调低一点;若在室内较暗的地方检验,则需要调高一点。
I分量的阈值较大,依据这么一个先验知识:火焰是会发光的。 最后,我们代入参考阈值检验一下图片看看效果如何:

    我们可以看出,火焰的基本轮廓都提取出来了。若大家想要把整个区域都提取出来,可以自行尝试其它阈值。


基于OpenCV的火焰检测(三)——HSI颜色判据的更多相关文章

  1. 基于OpenCV的火焰检测(二)——RGB颜色判据

    上文跟大家分享了在做火焰检测中常用到的图像预处理方法,从这一篇博文开始,我将向大家介绍如何一步一步地检测出火焰区域.火焰提取要用 到很多判据,今天我要向大家介绍的是最简单的但是很有效的判据--RGB判 ...

  2. 基于OpenCV的火焰检测(一)——图像预处理

    博主最近在做一个基于OpenCV的火焰检测的项目,不仅可以检测图片中的火焰,还可以检测视频中的火焰,最后在视频检测的基础上推广到摄像头实时检测.在做这个项目的时候,博主参考了很多相关的文献,用了很多种 ...

  3. 基于OpenCv的人脸检测、识别系统学习制作笔记之一

    基于OpenCv从视频文件到摄像头的人脸检测 在OpenCv中读取视频文件和读取摄像头的的视频流然后在放在一个窗口中显示结果其实是类似的一个实现过程. 先创建一个指向CvCapture结构的指针 Cv ...

  4. 【AdaBoost算法】基于OpenCV实现人脸检测Demo

    一.关于检测算法 分类器训练: 通过正样本与负样本训练可得到分类器,opencv有编译好的训练Demo,按要求训练即可生成,这里我们直接使用其已经训练好的分类器检测: 检测过程: 检测过程很简单,可以 ...

  5. 基于Opencv的人脸检测及识别

    一.实验目的:我这里完成的是,将8张人脸图片(4组,每组两张)存入库中,选取1张图片,程序识别出与其匹配的另一张. 这里介绍分三个步骤完成该工作,①程序读取摄像头.拍照 ②程序从电脑文档中读取图片   ...

  6. 基于OpenCv的人脸检测、识别系统学习制作笔记之三

    1.在windows下编写人脸检测.识别系统.目前已完成:可利用摄像头提取图像,并将人脸检测出来,未进行识别. 2.在linux下进行编译在windows环境下已经能运行的代码. 为此进行了linux ...

  7. 基于OpenCv的人脸检测、识别系统学习制作笔记之二

    在网上找到了一个博客,里面有大量内容适合初学者接触和了解人脸检测的博文,正好符合我目前的学习方面,故将链接放上来,后续将分类原博客的博文并加上学习笔记. 传送门: http://blog.sina.c ...

  8. 基于opencv的人脸检测的web应用

    参考资料 https://github.com/bsdnoobz/web-based-face-detect http://opencv-code.com/projects/web-based-int ...

  9. OpenCV学习系列(一) Mac下OpenCV + xcode人脸检测实现

    # OpenCV学习系列(一) Mac下OpenCV + xcode人脸检测实现 [-= 博客目录 =-] 1-学习目标 1.1-本章介绍 1.2-实践内容 1.3-相关说明 2-学习过程 2.1-环 ...

随机推荐

  1. linux 安装tomcat7

    wget http://mirror.bit.edu.cn/apache/tomcat/tomcat-7/v7.0.81/bin/apache-tomcat-7.0.81.tar.gz 解压安装包 t ...

  2. oracle 计算时间差

    1.计算时间差(相隔星期,天数,小时,分钟,秒) SELECT TO_CHAR(date1,'MMDDYYYY:HH24:MI:SS') date1, TO_CHAR(date2,'MMDDYYYY: ...

  3. matplotlib两种画散点图的方式

    对于matplotlib.pyplot( as plt ) 先输入主体数据部分: import numpy as np import matplotlib.pyplot as plt X_train ...

  4. CSS3中的变形功能

    一.变形主要值得是利用transform功能来实现文字或图片的旋转,缩放,倾斜,移动这四种处理. 1.旋转-----transform:rotate(xxdeg);( IE9以上,safari 3.1 ...

  5. PhpSpreadsheet如何读取excel文件

    PhpSpreadsheet如何读取excel文件 一.总结 一句话总结:万能的百度,直接搜代码就好,绝对有,毕竟github上面4000+的关注,说明很多人用了这个,使用照着demo倒是异常简单 二 ...

  6. c#加密,java解密(3DES加密)

    c#代码 using System; using System.Security; using System.Security.Cryptography; using System.IO; using ...

  7. Page 生命周期阶段 以及 生命周期事件

    MSDN 关于 页面生命周期事件的详细介绍: http://msdn.microsoft.com/zh-cn/library/ms178472.aspx ASP.NET  页面生命周期,当IIS接收访 ...

  8. The tag handler class for "c:set"(org.apache.taglibs.standard.tag.rt.core.UrlTag)was not found on the Java Build Path

    1.源码: <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> < ...

  9. C++结构体成员列表初始化

    C++关于struct和class的区别,可以看上一篇文章:c ++ class和struct[转] 结构体成员列表初始化,来个例子: #include <iostream> #inclu ...

  10. IE9 placeholder 不兼容的解决

    坑爹的IE9-,真的是够够的了,不过公司不要求兼容这个玩意了,自己觉得兼容这个鬼还是挺有挑战性的,自己也碰到不少难题,一个个解决. css: .placeholderColor { color : # ...