zoukankan      html  css  js  c++  java
  • 基于OpenCV的火焰检测(二)——RGB颜色判据

     上文跟大家分享了在做火焰检测中常用到的图像预处理方法,从这一篇博文开始,我将向大家介绍如何一步一步地检测出火焰区域。火焰提取要用
    到很多判据,今天我要向大家介绍的是最简单的但是很有效的判据——RGB判据。
    
        在介绍这个判据之前,博主首先给大家简单介绍一下RGB模型。根据三基色原理,用基色光单位来表示光的量,则在RGB颜色空间,任意色光F都可
    以用R、G、B三色不同分量的相加混合而成:
    
                                        F=r[R]+g[G]+b[B]
    
        当三基色分量都为0(最弱)时混合为黑色光;当三基色分量都为k(最强)时混合为白。改变了F的坐标值,也即改变了F的色值。
    

    RGB立体彩色模型

        人眼的视网膜上有两类感光器:锥状体和杆状体。锥状体主要位于视网膜的中间部分,称之为中央凹,且对颜色高度敏感,称为白昼视觉或亮视觉;
    杆状体分布面积较大,用来给出视野内的一般的总体图像,没有彩色感觉,而对低照明度敏感,称为微光视觉或暗视觉。由于锥状体对红、绿、蓝三种
    颜色的光很敏感,因此一般用于人眼观看的颜色模型是RGB模型。一般来说,无论是在网上下载的图片或视频,还是从摄像机得来的录像,都是RGB
    模型。所以,我们从网上下载了一幅火焰图像,不用进行任何的颜色模型转换就可以使用RGB颜色判据来提取区域。
    
        对于普通的火焰来说,它的红色分量和绿色分量会很大,并且绿色分量会大于蓝色分量,所以我们设下的简单判据是:
                        R > R_avg    AND
                        G > G_avg    AND
                        R > G > B
        其中,R_avg为红色分量的均值。
        在OpenCV1.0中实现很简单,下面先摆出代码:
    int cvBGR_CHK(IplImage*img_bgr, IplImage*bgr_chk){
        if (img_bgr == NULL || bgr_chk == NULL){
            printf("func cvBGR_CHK Error:
    ");
            printf("img_bgr == NULL || bgr_chk == NULL
    ");
            return -1;
        }
        if (img_bgr->nChannels != 3 || bgr_chk->nChannels != 1){
            printf("func cvBGR_CHK Error:
    ");
            printf("img_bgr->nChannels != 3 || bgr_chk->nChannels != 1
    ");
            return -1;
        }
        CvScalar avg;
        avg = cvAvg(img_bgr);
        CvSize size = cvGetSize(img_bgr);
        IplImage*R = cvCreateImage(size, 8, 1);
        IplImage*G = cvCreateImage(size, 8, 1);
        IplImage*B = cvCreateImage(size, 8, 1);
        IplImage*tmp1 = cvCreateImage(size, 8, 1);
        IplImage*tmp2 = cvCreateImage(size, 8, 1);
        cvSplit(img_bgr, B, G, R, NULL);
        cvCmpS(R, avg.val[2], tmp1, CV_CMP_GT);
        cvCmpS(G, avg.val[1], tmp2, CV_CMP_GT);
        cvMul(tmp1, tmp2, tmp1);
        cvCmp(R, G, tmp2, CV_CMP_GT);
        cvCmp(G, B, G, CV_CMP_GT);
        cvMul(tmp2, G, tmp2);
        cvMul(tmp1, tmp2, tmp1);
        cvConvertScale(tmp1, bgr_chk, 1.0 / 255);
        cvReleaseImage(&R);
        cvReleaseImage(&G);
        cvReleaseImage(&B);
        cvReleaseImage(&tmp1);
        cvReleaseImage(&tmp2);
    
        return 0;
    }
    
       函数cvBGR_CHK的功能是实现图像的RGB检测,把符合RGB判据的素点置为1,否则置为0,返回的是只有0和1的二值化模板。
    
        对于写代码的习惯,博主在这里说一下闲话。有些人可能觉得上面函数的格式有点奇怪,特别是返回值,有什么卵用?我的C++老师曾经说过,在做
    项目的时候,较为复杂的函数一般不要把返回值作为输出结果。什么意思呢?众所周知,函数返回值只有一个,若想返回两个值或者更多个,用这种
    方法就行不通了。对于返回两个或更多个值的函数,在C语言中在输入变量后面,这样就可以轻轻松松地输出两个值。那么返回值不就可以写出void
    型的吗?我们的确可以使用void,但是你们想一下,在一个大项目中,往往不止一个函数,那如果运行起来报错了,那么应该怎么找错呢?用断点找?
    定位到具体函数要花一定的时间;用编译器自带的检错工具?往往输出并没有什么卵用的信息。如果我们在每个函数里面设定一个对输入输出变量的异
    常情况进行自动报错的功能,就会大大简化查错的程序。比如说,在上面的函数中,把检错语句屏蔽掉,我分配给输出变量的内存有三个通道,那么函
    数执行肯定会报错,那么我们可不可以简简单单地从系统报错的信息中解决问题呢?首先,我们先运行一把,看看报错信息是啥。
    
        Unhandled exception at 0x75D3D3CF in FireDectect.exe: Microsoft C++ exception: cv::Exception at memory location 0x0023F3A8.
    
        有谁可以看出是哪里出了问题吗?反正我不能。再点一下“中断”按钮有木有好的提示?
    

    按了中断之后的弹出内容

        ……什么鬼?
        所以说,返回简单的错误信息很重要吧。如果取消屏蔽,那么就会输出:
    
    func cvBGR_CHK Error:
    img_bgr->nChannels != 3 || bgr_chk->nChannels != 1
    
        那我们可以很快解决木有?
        所以,博主做项目的时候都会采用这种习惯来写函数,这样会大大节省查找低级错误的时间。
        闲话就说到这里,下面我们来检测一下图片看看效果如何:
    

    原图 
    运行后的图像

        更多的检测就不在这里重复了,或者有些情况效果不是很好,但要记住,这只是众多判据的其中一个,我们可以两三个判据结合来更精确地提
    取区域,这就是以后要分享的东西了。
        今天就分享到这里~欢迎大家多来评论,来找出博主可能存在的错误,希望能和各位图像爱好者共同成长~以后更新会更频繁,大家要继续关注噢~
    那么我们下次见~
    
        下文预告:基于OpenCV的火焰检测(三)——HSI颜色判据
  • 相关阅读:
    Head first javascript(七)
    Python Fundamental for Django
    Head first javascript(六)
    Head first javascript(五)
    Head first javascript(四)
    Head first javascript(三)
    Head first javascript(二)
    Head first javascript(一)
    Sicily 1090. Highways 解题报告
    Python GUI programming(tkinter)
  • 原文地址:https://www.cnblogs.com/alan666/p/8312280.html
Copyright © 2011-2022 走看看