上文向大家介绍了如何用最简单的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. 【atcoder】All Your Paths are Different Lengths[arc102D](乱搞)

    题目传送门:https://arc102.contest.atcoder.jp/tasks/arc102_b 这道题有点毒瘤啊,罚时上天.. 显然若$ l=2^n $那么就可以直接二进制拆分,但是如果 ...

  2. 暑假爆零欢乐赛SRM08题解

    这真的是披着CF外衣的OI赛制?我怎么觉得这是披着部分分外衣的CF?果然每逢cf赛制必掉rating,还是得%%%cyc橙名爷++rp.. A题就是找一找序列里有没有两个连在一起的0或1,并且不能向两 ...

  3. processing学习整理---Input(输入)

    1.鼠标1D. 左右移动鼠标可移动天平. “mouseX”变量用于控制矩形的大小和颜色. void setup(){ size(640,360); noStroke(); colorMode(RGB, ...

  4. java创建多线程的三种方式

    /***************************继承Thread类创建多线程************************/ public class FirstThread extends ...

  5. poj 2478 Farey Sequence 欧拉函数前缀和

    Farey Sequence Time Limit: 1000MS   Memory Limit: 65536K       Description The Farey Sequence Fn for ...

  6. 【转】ORACLE的数据类型

    原文;http://linjian004.bokee.com/3916067.html 常用的数据库字段类型如下: 字段类型 中文说明 限制条件 其它说明 CHAR 固定长度字符串 最大长度2000 ...

  7. 在调用boostrap的model时获取到是哪个html元素调用

    调用的html代码: <a class="bk-round bk-border-info bk-border-darken bk-bg-lighten bk-border-3x bk- ...

  8. 微软面向高并发应用而推出的新程序库——TPL Dataflow

    TPL Dataflow库的几个扩展函数 TPL Dataflow是微软面向高并发应用而推出的新程序库.借助于异步消息传递与管道,它可以提供比线程池更好的控制.本身TPL库在DataflowBlock ...

  9. Microsoft Prism安装使用教程 搭建WPF松耦合架构框架

    Microsoft Prism安装使用教程 搭建WPF松耦合架构框架 Prism是由微软Patterns & Practices团队开发的项目,目的在于帮助开发人员构建松散耦合的.更灵活.更易 ...

  10. 搭建Rsync服务器

    部署Rsync服务器需要创建至少 一个配置文件,默认在系统中并不存在Rsync配置文件,对于服务器而言,配置文件创建完成后,使用守护进程模式启动rsync程序即可. 使用Centos 系统安装 部署R ...