基于OpenCV的火焰检测(三)——HSI颜色判据
来源:互联网 发布:武汉淘宝培训 编辑:程序博客网 时间:2024/05/16 11:28
上文向大家介绍了如何用最简单的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的火焰检测(四)——RGB与HSI的结合判据
0 0
- 基于OpenCV的火焰检测(三)——HSI颜色判据
- 基于OpenCV的火焰检测(三)——HSI颜色判据
- 基于OpenCV的火焰检测(四)——RGB与HSI的结合判据
- 基于OpenCV的火焰检测(五)——两个颜色模型的主分量判据
- 基于OpenCV的火焰检测(二)——RGB颜色判据
- 基于OpenCV的火焰检测(二)——RGB颜色判据
- 基于OpenCV的火焰检测(一)——图像预处理
- 基于OpenCV的火焰检测(一)——图像预处理
- 基于HSI空间颜色三角形的边缘检测方法
- opencv<三>基于opencv的canny检测
- 基于Ohta颜色空间的火焰分割
- 基于OpenCV的条形码区域检测(三)
- 使用OpenCV实现RGB、HSI、CMYK颜色空间的转换
- 基于HSI颜色模型实现去除照片的“红眼现象”
- 基于HSI颜色模型实现去除照片的“红眼现象”
- 基于HSI颜色模型实现去除照片的“红眼现象”
- OpenCV_火焰检测——完整代码
- opencv学习笔记(一):基于YCrCb颜色空间的肤色检测
- Dynamo 译文 Dynamo: Amazon's Highly Available Key-value Store
- IIPP迷你项目(一)“Rock-paper-scissor-lizard-Spock”
- ubuntu系统 /etc目录下配置文件的作用
- 【编程马拉松】【005-猴子分桃】
- 基础BFS+DFS poj3083
- 基于OpenCV的火焰检测(三)——HSI颜色判据
- 第4章第1节练习题2 二叉树的基本操作(非递归实现)
- 获取url
- Mac上Safari不能关键字搜索
- K近邻算法
- SpringMVC学习笔记(4):绑定数据(2)
- 如何给UItableView的headerView添加可伸展的Cell.headerView根据里面的tableView进行变化
- Duilib扩展—双击、右键消息扩展
- 强大的原生DOM选择器querySelector和querySelectorAll