基于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-环 ...
随机推荐
- javax.servlet.jsp.JspException cannot be resolved to a type 和 javax.servlet.jsp.PageContext cannot be resolved to a type 解决办法
今天我从码云上拉一个项目下来,是个maven项目,闲来无事自己研究研究,发现刚拉下来,项目就有报错,我一看是httpServletRequest cannot be resolved to a typ ...
- poj1753模拟
题目链接http://poj.org/problem?id=1573 题意:从第一行第k个出发按照已给的方向前进,问第几步走出去或第几步进入一个有多少步的循环. 就是按照题意模拟就好了. 代码写完了w ...
- 【bzoj2423】最长公共子序列[HAOI2010](dp)
题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2423 题目大意:求两个字符串的最长公共子序列长度和最长公共子序列个数. 这道题的话,对于 ...
- 浅谈CDN技术的性能与优势
从淘宝架构中的CDN入手分析 使用CDN和反向代理提高网站性能.由于淘宝的服务器不能分布在国内的每个地方,所以不同地区的用户访问需要通过互联路由器经过不同长度的路径来访问服务器,返回路径也一样,所以数 ...
- iOS APP AppIcon& LaunchImage
AppIcon size for iPhone: 29 - Settings @1x 29*29, 58 - Settings @2x 58*58, 87 - Settings @3x 87*87 ...
- mapreduce实现学生平均成绩
思路: 首先从文本读入一行数据,按空格对字符串进行切割,切割后包含学生姓名和某一科的成绩,map输出key->学生姓名 value->某一个成绩 然后在reduce里面对成绩进行遍历 ...
- Hibernate异常_01
1. 在使用 Hibernate(ojdbc14.jar[1536554字节,Win7显示大小为1501KB]) 操作 Oracle10g(32位)的时候,出现如下 error: INFO: HHH0 ...
- 防止xss,sql攻击函数
<?php //php防注入和XSS攻击通用过滤. //by qq:831937 $_GET && SafeFilter($_GET); $_POST && Sa ...
- python中的list()函数和tuple()函数
tuple函数:将一个序列作为参数,并把它转化为元组,如果参数是元组,将会原样返回: >>> tuple([1,2,3]) (1, 2, 3) >>> tuple( ...
- Spring boot临时文件目录报错
基本的错误信息如下: 2018-03-05 at 15:12:03 CST ERROR org.apache.juli.logging.DirectJDKLog 181 log - Servlet.s ...