车内乘客检测

    最近忙着做大作业没有写过东西,就把做的大作业整理一下贴出来吧。

背景简介

        某城市远郊公共汽车运营公司发现司售人员上交的票款额与实际乘客人数严重不符,造成公司长年亏损。因此,该公司希望能开发一套可以实时清点乘客人数的系统,车上的乘客的数量进行统计最终与司售人员所缴款项进行比对看是否相符合,以达到监视的效果防止公司公共汽车公司财产损失。这是一个实际的问题有着客观的现实背景开发出一套经济实用的乘客检测系统将能帮助该公司避免损失,与此问题类似的实际问题还有很多,比如车站监控系统,认证系统等,因此该系统有着广阔的应用范围。

问题分析

        分析该问题可以发现:基于图像的对车内乘客检测问题的本质是检测图像中某一区域是否存在满足人头部的特征,如果有这些特征则判断该区域有乘客,进行计数即可,若无这些特征则判断为该区域无乘客。归根到底是一个分类问题,且是两类问题,可以考虑使用模式识别中相关的分类的方法进行解决。

     具体而言:乘客坐在车内座位上,从车顶上方向下拍照,由于大多数人的头发较黑,摄像头采集到的照片乘客头部处比较暗,另外乘客的头部轮廓较为独特,大多为圆形或者近似圆形,再者在摄像头位置较为固定的情况下乘客的头部大小较为固定,这些信息都可以用来对某一座位区域内是否含有乘客进行判断。

方法探究

        由于本人近期接触了一些关于Adaboost 相关的一些算法,所以开始就想使用adaboost算法来解决此问题。先做好了前期的准备工作:手工选取正样本(将乘客头部从图片中切割出来保存),选取负样本(车内杂物如车座,车窗,扶手等),训练分类器,由于正样本和负样本都比较少且差异不是特别明显,训练时一直进入死循环,不能产生最后想要的分类器,后来降低分类器阶数虽能跳出循环,产生分类器,但性能很差误检漏检非常多,所以排除此方案。

    后又设想利用之前分析的一些特征有针对性的进行判断,对于本问题可利用的特征目前大致有:区域灰度值,区域面积,区域周长,区域的面积与周长之比。如果对每一个特征的取值范围进行限定,则可以排除干扰区域选择出满足条件的区域,即有乘客的区域。

方法简介

          关于求区域周长和面积比较简单不再赘述,在此重点介绍一下面积与周长之比。

一般地,周长一定,面积有这样的关系:圆>正多边形>不规则多边形其中,正多边形边数越多,越接近圆,所以面积越大;正方形大于长方形;长方形中边长越接近面积越大。周长相等的平面图形中,圆的面积是最大的。      

在此定义圆度概念:一个图形的面积与周长的比值除以与该图形等面积相等的圆的半径。

所以对于图像中的某一区域若圆度越接近0.5越可能是圆,因此可以利用此特征寻找区域内比较圆和饱满的区域。如下图所示右侧区域的圆度比左侧区域的圆度大且更接近于0. 5   

本次作业采用VC++6.0和Opencv 1.0在Windows7系统下完成。


// convert_raw2Ipl.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "cv.h"
#include "highgui.h"

#define BYET unsigned char 
#define fnum 50
#include "iostream"

#include "string.h"
#include "stdlib.h"
#include "stdio.h"
using namespace std;
void ImageBlendEnhance(IplImage *src, IplImage *dst);
int ImAdjust(IplImage* src, IplImage* dst);
int main(int argc, char* argv[])
{

	
		//IplImage *mid_img;
		IplConvKernel *element=0;//声明一个结构元素 
		int element_shape=CV_SHAPE_ELLIPSE ;//长方形形状的元素  
        CvMemStorage* storage = cvCreateMemStorage(0); 
        CvSeq* contour = 0; 
		element = cvCreateStructuringElementEx(3*2+1, 3*2+1,3,3,element_shape,0);//创建结构元素  

       CvMoments moments;
       CvMat *region; 
       CvPoint pt1,pt2; 
       double m00 = 0, m10, m01, mu20, mu11, mu02, inv_m00; 
       double a, b, c; 
       int xc, yc; 
       long int area=0;
	   long int length=0;

	    float ratio=0.0;
		float rad=0;


        BYTE *image;
        int width=0;
     	int height=0;
		IplImage *mid_img;
    	FILE *fpImg;//创建文件指针
           
     	fpImg = fopen("F://Program Files//Microsoft Visual Studio//MyProjects//convert_raw2Ipl//data//28.raw", "rb");//打开文件
	      if( fpImg==0 )                //如果不成功输出消
		  {
	         printf("不能打开文件");	
	         return 0;
		  }

        fread( &width, sizeof(int), 1, fpImg);
        fread( &height, sizeof(int), 1, fpImg);

	    image = new BYTE[width*height];

	    fread( image, sizeof(BYTE), width*height, fpImg);
	    fclose(fpImg);
	    CvSize wholesize,region2size;//整幅图的大小,区域2大小
    	wholesize.width=width;
     	wholesize.height=height;
        region2size.width=150;
    	region2size.height=100;
        mid_img=cvCreateImage(wholesize,8,1);

    	mid_img->imageData=(char*)image;//转换完成
       
       IplImage* temp = cvCreateImage(region2size,8,1);
	   IplImage* dst = cvCreateImage(region2size,8,3);
       int i,j;

	   for(i=0;i<temp->height;i++)
	    	for(j=0;j<temp->width;j++)
			{
		    	((uchar*)(temp->imageData+i*temp->widthStep))[j]=
		    	((uchar*)(	mid_img->imageData+(i+30)*mid_img->widthStep))[j+55];

			}
         
	        
		ImageBlendEnhance(temp, temp);//增强
        ImAdjust(temp,temp);
		

		cvEqualizeHist(temp,temp);	//直方图均衡
		cvEqualizeHist(temp,temp);
            double ave=0.0;
				int n=0;
			for(i=0;i<temp->height;i++)
	    	for(j=0;j<temp->width;j++)
			{
		    	ave+=((uchar*)(temp->imageData+i*temp->widthStep))[j];
		    	n++;
			}

			ave=ave/n;
            
	        cvThreshold( temp, temp, ave*0.42, 255, CV_THRESH_BINARY );//二值化
			//cvAdaptiveThreshold( temp, temp, 255, CV_ADAPTIVE_THRESH_MEAN_C,CV_THRESH_BINARY, 5, -9);
		

			for(int k=0;k<3;k++)
			{  
				cvDilate(temp,temp,element,1);//膨胀图像
			    cvErode(temp,temp,element,1);//腐蚀图像 
            }
			
        	cvNot( temp, temp ); //取反
			


			cvZero( dst );

			cvFindContours( 
				    temp, 
				  storage,
				 &contour, 
				sizeof(CvContour),
				CV_RETR_TREE,
				CV_CHAIN_APPROX_SIMPLE, 
				cvPoint(0,0) 
				   );
			//提取轮廓并保存到序列contour中
             
            
			 
			 //轮廓

             for( ; contour != 0; contour = contour->h_next ) 
			 { 
				CvScalar color = CV_RGB( 255, 255,255 ); //定义区域填充色为白色
				cvDrawContours( dst, contour, color, color, -1, CV_FILLED, 8,cvPoint(0,0) );//画轮廓
                contour = cvApproxPoly( contour, sizeof(CvContour), storage, CV_POLY_APPROX_DP, 3, 1 ); 
				//用多边形逼近轮廓
                
				area=fabs(cvContourArea(contour));//算面积
				length= cvArcLength(contour);//算周长
				rad=sqrt(area/3.14);//算等面积圆的半径
				ratio =area/length;//算ratio 

                if((area>=370)&&(ratio>0.238*rad)&&(length<=600)&&(length>=110))//判决表达式
				{   region=(CvMat*)contour; 
                    cvMoments( region, &moments,0 );  
                 
                    / 
					//计算距,确定轮廓中心
                    m00 = moments.m00; 
                    m10 = moments.m10; 
                    m01 = moments.m01; 
                    mu11 = moments.mu11; 
                    mu20 = moments.mu20; 
                    mu02 = moments.mu02;

                       inv_m00 = 1. / m00; 
                       xc = cvRound( m10 * inv_m00 ); 
                       yc = cvRound( m01 * inv_m00 ); 
                        a = mu20 * inv_m00; 
                       b = mu11 * inv_m00; 
                       c = mu02 * inv_m00; 
					
						pt1.x=xc-1;pt1.y=yc; 
						pt2.x=xc+1;pt2.y=yc; 
						cvLine( dst, pt1, pt2, CV_RGB(0,255,0), 2, CV_AA, 0 ); //画出中心
						pt1.x=xc;pt1.y=yc-1; 
						pt2.x=xc;pt2.y=yc+1; 
						cvLine( dst, pt1, pt2, CV_RGB(0,255,0), 2, CV_AA, 0 );//画出中心
				}
			 } 
             

			CvScalar circle_color = CV_RGB( 0, 255,0 ); 
            CvPoint center;
			center.x=xc+55;
			center.y=yc+30;
			IplImage *Multi_channels_img=cvCreateImage(wholesize, IPL_DEPTH_8U, 3);
			cvCvtColor(mid_img, Multi_channels_img, CV_GRAY2BGR);

			cvCircle(Multi_channels_img,center,30,circle_color,2,8);
             
			cvEqualizeHist(mid_img,mid_img);


		    
            
		
		
           	cvNamedWindow("zhuan");
            cvNamedWindow("cut");
            cvNamedWindow("dst");
			cvShowImage("dst",dst);
         	cvShowImage("zhuan",Multi_channels_img);
         	cvShowImage("cut",temp);
        	cvWaitKey(0);

		   cvReleaseImage(&temp); 
		   cvReleaseImage(&mid_img);



	return 0;
}












void ImageBlendEnhance(IplImage *src, IplImage *dst)
{
	IplImage *gray=NULL;
	gray=cvCreateImage(cvGetSize(src), 8, 1);
	if (src->nChannels!=1)
		cvCvtColor(src, gray, CV_BGR2GRAY);
	else
		cvCopy(src,gray);
	IplImage *tempimg=NULL;
	tempimg=cvCreateImage(cvGetSize(src), 8, 1);
	//直接对比度增强
	double maxpixel=-10;
	int h=src->height;
	int w=src->width;
	int i, j;
	for (i=0; i<h; i++)
	{
		for (j=0; j<w; j++)
		{
			CvScalar s;
			s=cvGet2D(gray, i, j);
			if (s.val[0]>maxpixel)
				maxpixel=(double)s.val[0];
		}
	}
	double sum=0.0;
	double ave;//3*3窗口像素的均值
	double c;//对比度
	double c1;//非线性变换后的对比度
	for (i=1; i<h-1; i++)
	{
		for (j=1; j<w-1; j++)
		{
			sum=0.0;
			for (int m=-1; m<2; m++)
			{
				for (int n=-1; n<2; n++)
				{
					CvScalar pix;
					pix=cvGet2D(gray, i+m, j+n);
					sum+=pix.val[0];
				}
			}
			ave=(double)sum/9;
			CvScalar pixel;
			pixel=cvGet2D(gray, i, j);
			c=abs((pixel.val[0]-ave))/(pixel.val[0]+ave);
			c1=4*c-6*pow(c,2)+4*pow(c,3)-pow(c,4);//求非线性变换后的对比度,c1的函数是经过试验得出的效果比较好处理函数,并不是唯一的
			CvScalar s;
			double temp;
			if (pixel.val[0]<=ave)
			{
				temp=ave*(1-c1)/(1+c1);
				s.val[0]=temp;
				cvSet2D(tempimg, i, j, s);
			}
			else
			{
				temp=maxpixel-(maxpixel-ave)*(1-c1)/(1+c1);
				s.val[0]=temp;
				cvSet2D(tempimg, i, j, s);
			}
		}
	} 
}




int ImAdjust(IplImage* src, IplImage* dst)
{
	double low1,high1,bottom1,top1;
	int N[256];
	double CN[256];
	double low,high,gamma;
	double val = 0;
	double sum = 0;
	int x,y,z;

	bool flag;
	gamma = 1;
	low = 0.01;
	high = 0.99;
	bottom1 = 0;
	top1 = 1;
	flag = FALSE;
	int k = 0,j = 0;
	
	memset(N,0,256*4);
	memset(CN,0,256*4);

	for(y = 0; y < src->height; y++)
	{
		for (x = 0; x < src->width; x++)
		{
			val = ((uchar*)(src->imageData + src->widthStep*y))[x];
			int i = (uchar)val;
			N[i]++;
		}
	}

	for (z = 0; z < 256; z++)
	{
		sum += N[z];
		CN[z] = sum;
	}

	for (z =0; z < 256; z++)
	{
		CN[z] /= sum;
		if (flag == false)
		{
			if(CN[z] >= 0.01)
			{
				k = z;
				flag = true;
			}
		}
		else
		{
			if (CN[z] >= 0.99)
			{
				j = z ;
				break;
			}
		}
	}
	if(k == j)
	{
		low1 = 0;
		high1 = 1;
	}
	else
	{
		low1 = k;
		high1 = j;
	}
		
	 double low2 = low1;
	 double high2 = high1;
	 double bottom2 = bottom1*255;
	 double top2 = top1*255;
	 double err_in = high2 - low2;
	 double err_out = top2 - bottom2;

	   // intensity transform
	  for( y = 0; y < src->height; y++)
	  {
		for (x = 0; x < src->width; x++)
		{
			val = ((uchar*)(src->imageData + src->widthStep*y))[x];
			val = pow((val - low2)/err_in, gamma) * err_out + bottom2;
			val = val + 0.5;
			if(val>255) val=255; if(val<0) val=0; // Make sure src is in the range [low,high]
			((uchar*)(dst->imageData + dst->widthStep*y))[x] = (uchar) val;
		}
	  }
	return 0;
}
















随着车辆数量的不断增长,汽车安全问题也逐渐引起了广泛的关注。而安全带作为一项基本的被动安全措施,对车辆驾驶者和乘客来说至关重要。统计数据表明,在发生交通事故时,系安全带的乘客生还率要远高于没有系安全带的乘客。因此,车内安全带的正确使用与否,直接关系到乘客安全。 基于计算机视觉的车内安全带检测,就是一种通过计算机视觉技术对车内乘坐者的安全带使用情况进行检测的技术,该技术可以实现实时检测和提醒,有效地提高车内乘坐者的安全性。目前,基于计算机视觉的车内安全带检测技术已经在一些汽车制造企业中得到了应用。 该技术的实现需要经过以下几个步骤:首先,通过摄像头采集车内的图像;接着,利用算法进行图像识别并判断安全带是否系好;最后,如果乘客未系安全带,则车辆的报警系统会立即发出警报提醒驾驶员。 基于计算机视觉的车内安全带检测技术的优点是显而易见的。一方面,它可以提高汽车安全性能,有效降低交通事故的发生率;另一方面,这项技术的实现不需要大量的物质和人力投入,成本较低,操作简单。 综上所述,基于计算机视觉的车内安全带检测技术是一项十分重要的技术。随着科学技术的不断发展和进步,该技术有望在未来的汽车安全措施中得到更广泛的应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值