• 基于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颜色判据
  • 相关阅读:
    数“1”游戏
    第二次冲刺期_每日站立会议_个人记录_文档
    第一次冲刺期——每日站立会议——个人记录——文档
    团队绩效
    其他小组对我们的评价汇总
    Sprint评分表
    大作业项目冲刺阶段(一)
    丹佛机场行李系统Postmortem
    团队项目测试计划
    SCRUM报告(1)
  • 原文地址:https://www.cnblogs.com/alan666/p/8312280.html
Copyright © 2020-2023  润新知