基于OpenCV的火焰检测(三)——HSI颜色判据
上文向大家介绍了如何用最简单的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颜色判据的更多相关文章
- 基于OpenCV的火焰检测(二)——RGB颜色判据
上文跟大家分享了在做火焰检测中常用到的图像预处理方法,从这一篇博文开始,我将向大家介绍如何一步一步地检测出火焰区域.火焰提取要用 到很多判据,今天我要向大家介绍的是最简单的但是很有效的判据--RGB判 ...
- 基于OpenCV的火焰检测(一)——图像预处理
博主最近在做一个基于OpenCV的火焰检测的项目,不仅可以检测图片中的火焰,还可以检测视频中的火焰,最后在视频检测的基础上推广到摄像头实时检测.在做这个项目的时候,博主参考了很多相关的文献,用了很多种 ...
- 基于OpenCv的人脸检测、识别系统学习制作笔记之一
基于OpenCv从视频文件到摄像头的人脸检测 在OpenCv中读取视频文件和读取摄像头的的视频流然后在放在一个窗口中显示结果其实是类似的一个实现过程. 先创建一个指向CvCapture结构的指针 Cv ...
- 【AdaBoost算法】基于OpenCV实现人脸检测Demo
一.关于检测算法 分类器训练: 通过正样本与负样本训练可得到分类器,opencv有编译好的训练Demo,按要求训练即可生成,这里我们直接使用其已经训练好的分类器检测: 检测过程: 检测过程很简单,可以 ...
- 基于Opencv的人脸检测及识别
一.实验目的:我这里完成的是,将8张人脸图片(4组,每组两张)存入库中,选取1张图片,程序识别出与其匹配的另一张. 这里介绍分三个步骤完成该工作,①程序读取摄像头.拍照 ②程序从电脑文档中读取图片 ...
- 基于OpenCv的人脸检测、识别系统学习制作笔记之三
1.在windows下编写人脸检测.识别系统.目前已完成:可利用摄像头提取图像,并将人脸检测出来,未进行识别. 2.在linux下进行编译在windows环境下已经能运行的代码. 为此进行了linux ...
- 基于OpenCv的人脸检测、识别系统学习制作笔记之二
在网上找到了一个博客,里面有大量内容适合初学者接触和了解人脸检测的博文,正好符合我目前的学习方面,故将链接放上来,后续将分类原博客的博文并加上学习笔记. 传送门: http://blog.sina.c ...
- 基于opencv的人脸检测的web应用
参考资料 https://github.com/bsdnoobz/web-based-face-detect http://opencv-code.com/projects/web-based-int ...
- OpenCV学习系列(一) Mac下OpenCV + xcode人脸检测实现
# OpenCV学习系列(一) Mac下OpenCV + xcode人脸检测实现 [-= 博客目录 =-] 1-学习目标 1.1-本章介绍 1.2-实践内容 1.3-相关说明 2-学习过程 2.1-环 ...
随机推荐
- 如何修改windows系统远程桌面默认端口
此文档概述如何修改windows系统远程桌面的默认端口,众所周知windows系统默认的远程桌面端口是3389,这样对于开启远程桌面的计算机有一定的安全威胁,修改远程桌面的默认端口可以提高系统的安全性 ...
- WEB开发中常见漏洞
1.sql注入 SQL注入在黑客领域是一种非常常见的攻击手段,大家应该都听说过很多数据泄漏的案例,其中大部分都是采用SQL注入来获取数据的. SQL注入一般是前端向后台提交数据的时候,在数据中加入SQ ...
- Hadoop学习1(初识hadoop)
Hadoop生态系统的特点 1)源代码开源 2)社区活跃,参与者多 3)涉及分布式存储和计算的各方面 4)已得到企业界的验证 Hadoop构成 1) 分布式文件系统HDFS(Hadoop Distri ...
- Android 手机上获取手机当前上网IP地址
[转] 原文 Android 手机上获取手机当前上网IP地址 (手机网关给手机号分配的IP) 每个手机上网通过移动网关的时候,网关都会给该手 ...
- SpringBoot中使用Spring Data Jpa 实现简单的动态查询的两种方法
软件152 尹以操 首先谢谢大佬的简书文章:http://www.jianshu.com/p/45ad65690e33# 这篇文章中讲的是spring中使用spring data jpa,使用了xml ...
- dajngo之中间件总结
一.中间件: a.中间件是什么? - 中间件是一个类 b. 返回值注意 -(1)无返回值:继续执行后续函数中间件和视图函数 -(2)有返回值:执行自己的 ...
- Windows 摄像头数据
1. FFmpeg获取DirectShow设备数据(摄像头,录屏) http://blog.csdn.net/leixiaohua1020/article/details/38284961 2.
- Linux下DB2的TCP配置
1切换到db2实例用户下(uppdb) su - uppdb 2查看db2是否开启tcp服务 db2set -all 设置tcp服务:db2set DB2COMM=TCPIP 3查看是否配置db2 t ...
- asp.net 锚点
可以使用锚点,但这里可使用灵活处理 首先获取需要滚动到的位置的id,如,可以设置一个元素(,注:要在form里),另外在form的任意位置设置 代码如下: 注:a标签里不要有内容,在回传的地方调用 代 ...
- python切片、迭代、生成器、列表生成式等高级特性学习
python高级特性 1行代码能实现的功能,决不写5行代码.请始终牢记,代码越少,开发效率越高. 切片 当我们要取一个list中的前n各元素时,如果前n个少的话,我们还可以一个一个的取,但是若前n个元 ...