opencv 火灾检测

采用了一个模型, 这个模型是看别人的代码实现的。


感谢http://tieba.baidu.com/p/3116037207?pid=52443907177&cid=0#52443907177, 我提取了他的代码的核心部分, 并加了一些注释。


以下是代码:h文件:

#include
#include 

using namespace cv;
class ProcessImage
{
public:
	ProcessImage(void);
	~ProcessImage(void);
	static IplImage* Process(IplImage* img);  //图像处理
};


cpp文件:

#include "ProcessImage.h"



IplImage* imgToShow;
CvMemStorage * storage = cvCreateMemStorage(0);  
CvSeq * contour = 0; 


ProcessImage::ProcessImage(void)
{
}

ProcessImage::~ProcessImage(void)
{
}



//An Early Fire-Detection Method Based on Image Processing
// 检测火焰
// 要求, (1)R>RT   (2)R>=G>=B   (3)S>=( (255-R) * ST / RT )
// RGB为红绿蓝值, S为饱和度
// RT为红色阈值, ST为饱和度阈值 
IplImage* ProcessColorModel(IplImage *RGBimg)
{
	IplImage * pImgFire = cvCreateImage(cvSize(RGBimg->width,RGBimg->height), IPL_DEPTH_8U, 3);
	IplImage *dst = cvCreateImage( cvGetSize(RGBimg), IPL_DEPTH_8U, 1 );
	
	cvSet(pImgFire, cvScalar(0,0,0),0);
	int RedThreshold=115;  //115~135 
	int SaturationThreshold=55;  //55~65

	for(int j = 0;j < RGBimg->height;j++)
	{
		for (int i = 0;i < RGBimg->widthStep;i+=3)
		{
			uchar B = (uchar)RGBimg->imageData[j*RGBimg->widthStep+i];
			uchar G = (uchar)RGBimg->imageData[j*RGBimg->widthStep+i+1];
			uchar R = (uchar)RGBimg->imageData[j*RGBimg->widthStep+i+2];
			uchar maxv=max(max(R,G),B); 
			uchar minv=min(min(R,G),B); 
			double S = (1 - 3.0*minv/(R+G+B));

			//(1)R>RT   (2)R>=G>=B   (3)S>=( (255-R) * ST / RT )
			if( R>RedThreshold && R>=G && G>=B && S>0.20 && S>(255-R)/20  &&S>=((255-R)*SaturationThreshold/RedThreshold))
			{
				pImgFire->imageData[i+RGBimg->widthStep*j] = 255;
				pImgFire->imageData[i+1+RGBimg->widthStep*j] = 255;
				pImgFire->imageData[i+2+RGBimg->widthStep*j] = 255;
			}
			else
			{
				pImgFire->imageData[i+RGBimg->widthStep*j] = 0;
				pImgFire->imageData[i+1+RGBimg->widthStep*j] = 0;
				pImgFire->imageData[i+2+RGBimg->widthStep*j] = 0;
			}

		}
	}
	cvCvtColor(pImgFire,dst,CV_BGR2GRAY);
	cvReleaseImage(&pImgFire);
	return dst;

}

// Find contour
void FindContours( IplImage* dst )
{
	cvFindContours(dst,storage,&contour,sizeof(CvContour),CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE);
	//cvRectangle(imgToShow,cvPoint(137,117),cvPoint(200,200),cv::Scalar(255,0,0),2);
	if(contour)
		cvDrawContours(dst,contour,cvScalarAll(255),cvScalarAll(255),100);   //画轮廓
	//cvShowImage("Contours",dst);
	CvMoments m;
	CvMat mat;
	double M00;
	CvSeq*	contour2=contour;
	IplImage *pTmp=cvCreateImage(cvGetSize(dst),IPL_DEPTH_8U,1);
	cvSet(pTmp, cvScalar(0,0,0),0);
	IplImage *pTmp1=cvCreateImage(cvGetSize(dst),IPL_DEPTH_8U,1);
	cvSet(pTmp1, cvScalar(0,0,0),0);
	for(;contour2!=0;contour2=contour2->h_next)
	{ 
		CvRect rect=cvBoundingRect(contour2); //得到边界的矩形框
		cvDrawContours(pTmp,contour2,CV_RGB(255,255,255),CV_RGB(255,255,255),-1, 1, 8);
		cvRectangle(pTmp,cvPoint(rect.x,rect.y),cvPoint(rect.x+rect.width,rect.y+rect.height),CV_RGB(255,255,255),3,CV_AA,0);

		int n=contour->total;
		CvRect r=((CvContour*)contour2)->rect;
		CvPoint2D32f center;
		cvMoments(cvGetSubRect(pTmp,&mat,r),&m,0);
		M00=cvGetSpatialMoment(&m,0,0);
		center.x=cvGetSpatialMoment(&m,1,0)/M00; //重心为(centerx.+r.x,center.y+r.y)
		center.y=cvGetSpatialMoment(&m,0,1)/M00;
		double nHalfW,nHalfH;
		nHalfW=center.x<(r.width-center.x)?center.x:(r.width-center.x);
		nHalfH=center.y<(r.height-center.y)?center.y:(r.height-center.y);
		cvDrawContours(pTmp1,contour2,CV_RGB(255,255,255),CV_RGB(255,255,255),-1, 1, 8);
		cvRectangle(pTmp1,cvPoint(center.x+r.x-nHalfW,center.y+r.y-nHalfH),cvPoint(center.x+r.x+nHalfW,center.y+r.y+nHalfH),CV_RGB(255,255,255),3,CV_AA,0);
		cvRectangle(imgToShow,cvPoint(center.x+r.x-nHalfW,center.y+r.y-nHalfH),cvPoint(center.x+r.x+nHalfW,center.y+r.y+nHalfH),CV_RGB(107,180,229),3,CV_AA,0);
		//cvSaveImage("contoursss.bmp",pTmp);
		//cvSaveImage("contoursss1.bmp",pTmp1);
		
		//MessageBox(FindWindow("CFireDetectionApp","FireDetection"),"find!","1122",MB_OK);
	}
	cvReleaseImage(&pTmp);
	cvReleaseImage(&pTmp1);
}



IplImage* ProcessImage::Process(IplImage* img)
{
	//cvRectangle(img,cvPoint(137,117),cvPoint(200,200),cv::Scalar(255,0,0),2);
	//dst = process_rgb(img);
	//cvSaveImage("temp.jpg",temp2);
	imgToShow = img;
	IplImage* dst = ProcessColorModel(img);
	
	// 具体做检测
	// 现在的到的是一些列的点
	// 要把他们变成区域
	//cvSmooth(dst, dst, CV_GAUSSIAN,15,15,0,0); //滤波
	cvSmooth(dst, dst, CV_BLUR,15,15,0,0); //滤波
	cvThreshold( dst, dst, 60, 255, CV_THRESH_BINARY);
	cvSmooth(dst, dst, CV_MEDIAN, 15, 15 ,0 ,0);
	cvErode(dst, dst, 0, 1);
	//cvSaveImage("fushi.jpg",dst);
	cvDilate(dst, dst, 0, 1);
	//cvSaveImage("penzhang.jpg",dst);
	//IplImage* dst = cvCreateImage(cvSize(img->width,img->height), IPL_DEPTH_8U, 1);
	//cvSet(dst,cvScalar(0),0);初始化图片函数
	
	 // 找到区域
	// 画一个框
	FindContours(dst);
	cvReleaseImage(&dst);
	return imgToShow;
}

main

文件:

#include "ProcessImage.h"

int main()
{
	// 读取图片
	IplImage* img = cvLoadImage("1.jpg");

	// 检测图片
	IplImage* fireImage = ProcessImage::Process(cvCloneImage(img));

	// 显示
	cvNamedWindow("src", CV_WINDOW_AUTOSIZE);
	cvNamedWindow("dst", CV_WINDOW_AUTOSIZE);

	cvShowImage("src", img);
	cvShowImage("dst", fireImage);

	cvWaitKey(0);

	// 释放内存
	cvReleaseImage(&img);
	cvReleaseImage(&fireImage);

	cvDestroyAllWindows();

	return 0;
}

效果:

opencv 火灾检测_第1张图片opencv 火灾检测_第2张图片

你可能感兴趣的:(opencv)