⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 videopro.cpp

📁 基于视觉的道路识别技术的智能小车导航源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// VideoPro.cpp : implementation file
//

#include <stdafx.h>
#include "AGV.h"
#include "VideoPro.h"
#include <math.h>
//#include "Hough.h"
#include "HSI.h"

// 在计算图像大小时,采用公式:biSizeImage = biWidth' × biHeight。
// 是biWidth',而不是biWidth,这里的biWidth'必须是4的整倍数,表示
// 大于或等于biWidth的,离4最近的整倍数。WIDTHBYTES就是用来计算
// biWidth'
#define WIDTHBYTES(bits)    (((bits) + 31) / 32 * 4)
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CVideoPro

CVideoPro::CVideoPro()
{
    
}

CVideoPro::~CVideoPro()
{
}





/////////////////////////////////////////////////////////////////////////////
// CVideoPro message handlers

BOOL CVideoPro::ToGray(LPBYTE lpBytes,int lHeight,int lWidth)
{
   	int i,j;
	for (i = 0; i < lHeight; i ++)
	{
		for (j = 0; j < lWidth; j ++)
		{
			// 获取各颜色分量
			unsigned char  B= *((unsigned char *)lpBytes + 3*lWidth * i + 3*j);
			
			unsigned char G = *((unsigned char *)lpBytes + 3*lWidth* i+ 3*j+1);
			
			unsigned char R = *((unsigned char *)lpBytes + 3*lWidth* i + 3*j+2);

			// 计算灰度值
			unsigned char Y = (77 * R + 150 * G + 29 * B) / 256;
          //  unsigned char U = 128+(-44 * R -87* G + 131* B)/256 ; 
		 //   unsigned char V = 128+(131 * R - 110 * G -21 * B)/256 ;
				
			// 回写灰度值
			*((unsigned char *)lpBytes + 3*lWidth* i + 3*j) =Y ;
	    	*((unsigned char *)lpBytes + 3*lWidth* i+ 3*j+1) = Y;
			*((unsigned char *)lpBytes + 3*lWidth* i+ 3*j+2) = Y;
		}
	}
 return TRUE;
  
}
//RGB24使用24位来表示一个像素,RGB分量都用8位表示,取值范围为0-255。
//注意在内存中RGB各分量的排列顺序为:BGR BGR BGR…。


BOOL CVideoPro::RgbTrans(LPBYTE lpBytes, int lHeight, int lWidth)
{
   int i,j;
   int leftX,leftY;
   int  rightX,rightY;
   	RGB rgb;
    HSI hsi;
    LUV luv;      
            
   
//   LONG result;
	// 对各像素进行灰度转换
	// 计算图像每行的字节数
   leftX=int(0.2*lWidth);
   leftY=int(0.05*lHeight);
   rightX=int(0.8*lWidth);
   rightY=int(0.4*lHeight);
   double SumI,SumH,SumS;
   double Hue,Int,Sat;
   SumI=SumH=SumS=0;
// unsigned char YY,UU,VV;
 /*
 for (i = leftY; i < rightY; i ++)
	{
		for (j = leftX; j <rightX; j ++)
		{
			// 获取各颜色分量
			unsigned char  B= *((unsigned char *)lpBytes + 3*lWidth * i + 3*j);
			
			unsigned char G = *((unsigned char *)lpBytes + 3*lWidth* i+ 3*j+1);
			
			unsigned char R = *((unsigned char *)lpBytes + 3*lWidth* i + 3*j+2);
			rgb.b=B;
            rgb.g=G;
			rgb.r=R;
            RgbToHsi(&rgb,&hsi);
		//	*((unsigned char *)lpBytes + 3*lWidth * i + 3*j)=(unsigned char )(255*(hsi.Intensity));
		    SumI=SumI+hsi.Intensity;
            SumH=SumH+hsi.Hue;
			SumS=SumS+hsi.Saturation;
		}
	}
 Int=SumI/(rightY-leftY)/(rightX-leftX);
 Hue=SumH/(rightY-leftY)/(rightX-leftX);
 Sat=SumS/(rightY-leftY)/(rightX-leftX);

*/
   LUV Coreluv;
 GetCoreRegion(lpBytes,  lHeight,  lWidth,  &Coreluv);
for (i = 0; i < lHeight; i ++)
	{
		for (j = 0; j < lWidth; j ++)
		{
			// 获取各颜色分量
			unsigned char B = *((unsigned char *)lpBytes + 3*lWidth * i + 3*j);
			
			unsigned char G = *((unsigned char *)lpBytes + 3*lWidth* i+ 3*j+1);
			
			unsigned char R = *((unsigned char *)lpBytes + 3*lWidth* i + 3*j+2);
	    	rgb.r=R;
            rgb.g=G;
			rgb.b=B;
		 	/*
			rgb.r=212;
            rgb.g=178;
			rgb.b=143;
		*/	
			double l0,u0,v0,rp;
		    l0=115.68;
			u0=4.27;
			v0=-2.50;
		/*	//灰色水泥路面参考值
			
			l0=Coreluv.l;//126.38;
			u0=Coreluv.u;//33.51;
			v0=Coreluv.v;//29.14;
		*/
		
            RgbToLuv(&rgb,&luv);
			rp=sqrt((luv.l-l0)*(luv.l-l0)+(luv.u-u0)*(luv.u-u0)+(luv.v-v0)*(luv.v-v0));
		//	double
            //RgbToHsi(&rgb,&hsi);//hsi.Hue>0.85* Hue && hsi.Hue<0.99* Hue &&hsi.Saturation>0.805* Sat &&
		//	if ( hsi.Hue>30.47 && hsi.Hue<35)
            if ( rp<15)
			{
			*((unsigned char *)lpBytes + 3*lWidth * i + 3*j)=255;
			*((unsigned char *)lpBytes + 3*lWidth * i + 3*j+1)=255;
		    *((unsigned char *)lpBytes + 3*lWidth * i + 3*j+2)=255;
			}
			else
				{
			*((unsigned char *)lpBytes + 3*lWidth * i + 3*j)=0;
			*((unsigned char *)lpBytes + 3*lWidth * i + 3*j+1)=0;
		    *((unsigned char *)lpBytes + 3*lWidth * i + 3*j+2)=0;
			}

		}
	}
	
 return TRUE;
	
}
/*************************************************************************
 *
 * 函数名称:
 *   MedianFilter()
 *
 * 参数:
 *   HDIB hDIB          - 待处理的DIB
 *
 * 返回值:
 *   返回值
 *
 * 说明:
 *   该函数将彩色位图进行中值滤波处理
 *
 ************************************************************************/
void CVideoPro::MedianFilter(LPBYTE lpDIBBits, int lHeight, int lWidth)

{
	// 循环变量
	LONG i;
	LONG j;
	LONG k;
	LONG l;
	// 掩码模版
	unsigned char mask[9];
	// 计算图像每行的字节数
	LONG lLineBytes = lWidth * 3;
	// 申请并分配中间缓存
	HLOCAL hLocal = LocalAlloc(GHND, lWidth * 3* lHeight);
	if (hLocal == NULL)
		return;
	LPBYTE m_temp = (LPBYTE)LocalLock(hLocal);
        //复制图像数据
	memcpy( m_temp, lpDIBBits, lWidth *3* lHeight );
	
	// 模版滤波
	for (i = 0; i < lWidth; i++)			//被处理像素在i列
	{
		for (j = 0; j < lHeight; j++)		//被处理像素在j行
		{
			// 索引
			int	id = 0;

			// 进行小区域模版滤波
			for (k = i - 1; k < i + 2; k++)
			{
				for(l = j - 1; l < j + 2; l++)
				{
					// 防止内存溢出
					if (k >= 0 && l >= 0 && k < lWidth && l < lHeight)
					{
					  mask[id] = *((unsigned char *)lpDIBBits + l * lLineBytes + k * 3);
					  id++;
					}
				}
			}
			
			// 中间变量
		unsigned char T;
			
			// 冒泡排序法
			for (k = 0; k < 8; k++)		
			{
				for (l = 8; l > k; l--)					
				{
					if (mask[l] < mask[l - 1])
					{
						T = mask[l];
						mask[l] = mask[l - 1];
						mask[l - 1] = T;
					}
					
				}
			}
	
       	     //中值排序法start
		/*	int i;
			int nHisto[256];
			int nMedian,nSize=9;
			for( i = 0; i < 256; i++) nHisto[ i ] = 0;
			//统计相同灰度值出现的次数				
			for( i = 0; i < nSize; i++)
			{    
				nHisto[(int)mask[i]]++;
			}

			//取直方图的中值
			int nCount = 0;
			for( i = 0; i < 256; i++)
			{ 
				//存放直方图中相同灰度值出现次数的累加和
				nCount += nHisto[i];
				if(nCount >= (int)(nSize / 2 + 1))
				{  
					nMedian = i;
					break;
				}
			}	
			//中值排序法end;
*/
	      m_temp[j * lWidth* 3 + i* 3 ]=mask[4]; //nMedian;
			
		}
	}

	// 将转换后的中间缓存数据回存到DIB
	for (i = 0; i < lHeight; i ++)
	{
		for (j = 0; j < lWidth; j ++)
		{
			*((unsigned char *)lpDIBBits + lWidth * i*3 + 3*j) = 
			*((unsigned char *)lpDIBBits + lWidth * i*3 + 3*j+1) =
			*((unsigned char *)lpDIBBits + lWidth * i*3 + 3*j+2) = m_temp [ lWidth * i* 3 +j* 3];
		}
	}
	
	
	LocalUnlock(hLocal);
	LocalFree(hLocal);


}




 void CVideoPro::GetIntensity(LPBYTE lpDIBBits, int lHeight, int lWidth, int *nNs_Y,WINDOW w)
 {
   // 循环变量
 	LONG i;
 	LONG j;
 
 	// 变量初始化
 	memset(nNs_Y, 0, sizeof(nNs_Y));
 
 
 
 	// 计算图像每行的字节数
 	LONG lLineBytes = lWidth * 3;

 	// 对各像素进行灰度转换
 	for (i = w.BottomY; i < w.TopY; i ++)
 	{
 		for (j = w.LeftX; j < w.RightX; j ++)
 		{
 			unsigned char Y = *((unsigned char *)lpDIBBits + lLineBytes * i + 3*j);
 		
 
 			
 
			// 灰度统计计数
 			nNs_Y[Y]++;		
 		}
 	}
 
 }

void CVideoPro::Threshold(LPBYTE lpDIBBits, int lHeight, int lWidth,WINDOW w)
{
    int i,j;
    int nHistogramBuffer[256];
   	GetIntensity(lpDIBBits,lHeight,lWidth,nHistogramBuffer, w);
	// 计算图像每行的字节数
	LONG lLineBytes = lWidth * 3;
    float Sigma[256];
	float Mean1, Mean2;
	
	//Sigma[256]数组清零
	for( i = 0;i < 256; i++) Sigma[i] = 0.0;
	
	int nLevelLow = 0;
	int nLevelHigh = 0;
	
	//查找最小灰度值
	i = 0;
	while(nLevelLow == 0)
	{
		if( nHistogramBuffer[i] != 0 )
		{
			nLevelLow = i;
		}
		i++;
	}

	//查找最大灰度值
	i = 255;
	while(nLevelHigh == 0)
	{
		if( nHistogramBuffer[i] != 0 )
		{
			nLevelHigh = i;
		}
		i--;
	}
   
	//th循环,小于阈值th的像素归为第一类,大于th的像素归为第二类
	//th=0、1、2、…、nLevel。
	for(int th = nLevelLow; th <= nLevelHigh; th++)   
	{
		long lGrayLow = 0;
		long lGrayHigh = 0;
		long lSumLow = 0;
		long lSumHigh = 0;
		for(i = nLevelLow; i < th; i++)
		{
			lSumLow += nHistogramBuffer[i];
			lGrayLow += i * nHistogramBuffer[i];
		}
		for(i = th; i <= nLevelHigh; i++)
		{
			lSumHigh += nHistogramBuffer[i];
			lGrayHigh += i * nHistogramBuffer[i];
		}
		
		if( lSumLow > 0 )
		{
			Mean1 = (float)lGrayLow / lSumLow;
		}
		else
		{
			Mean1 = 0.0;
		}
		if( lSumHigh > 0)
		{
			Mean2 = (float)lGrayHigh / lSumHigh;
		}
		else
		{
			Mean2 = 0.0;
		}
		
		//计算两类之间的方差
		Sigma[th] = (float)lSumLow * lSumHigh 
			* (Mean1 - Mean2) * (Mean1 - Mean2);
	}
	
	//th循环结束,求方差最大的阈值
	float MaxSigma = Sigma[nLevelLow];
	int Thresh = 0;
	for( i = nLevelLow + 1; i <= nLevelHigh; i++)
	{
		if(MaxSigma < Sigma[i])
		{
			MaxSigma = Sigma[i];
			Thresh = i;
		}
	}
	
	// 对各像素进行灰度转换
	for (i = w.BottomY; i < w.TopY; i ++)
	{
		for (j = w.LeftX; j < w.RightX; j ++)
		{
			unsigned char  Y= *((unsigned char *)lpDIBBits + 3*lWidth * i + 3*j);
			if(Y < Thresh)
			{
			// 回写灰度值
			*((unsigned char *)lpDIBBits + 3*lWidth* i + 3*j) = 0;
	    	*((unsigned char *)lpDIBBits + 3*lWidth* i+ 3*j+1) = 0;
			*((unsigned char *)lpDIBBits + 3*lWidth* i+ 3*j+2) = 0;
			}else
            {
			// 回写灰度值
			*((unsigned char *)lpDIBBits + 3*lWidth* i + 3*j) = 255;
	    	*((unsigned char *)lpDIBBits + 3*lWidth* i+ 3*j+1) = 255;
			*((unsigned char *)lpDIBBits + 3*lWidth* i+ 3*j+2) = 255;
			}
		}
	}
		
}

BOOL CVideoPro::Hough(LPBYTE lpDIBBits, int lHeight, int lWidth,WINDOW w)
{
    BYTE *lpSrc;
    MaxValue MaxValue1;
    int iMaxAngleNumber;
    int iDist;
    int step_distance=1;//步进距离
    double step_angle=PI/180;//步进角
    //循环变量
    int i,k,m;
	long s;
	int x;
    int y;
	double sintab[180],costab[180];
	for(x=0;x<180;x++)
	{
	  sintab[x]=sin(x*PI/180);
	  costab[x]=cos(x*PI/180);
	}
    //存储变换域中的两个最大值
    //计算变换域的尺寸
    m = (int) (sqrt(lWidth*lWidth + lHeight*lHeight)/step_distance);
    //角度从0-180,每格step_angle 度
    iMaxAngleNumber = int(PI/step_angle);
	int *buf,**lpTransArea;
	HGLOBAL    hbuf,hDistAlpha;

 	//分配内存用来处理数据
	if(( hbuf=GlobalAlloc(GHND,2*m*iMaxAngleNumber* sizeof(int)))==NULL){
		//MessageBox(hWnd,"Error alloc memory!","Error Message",MB_OK|MB_ICONEXCLAMATION);
		return FALSE;
	}
	buf=(int *)GlobalLock(hbuf);
	//分配内存用来处理数据
	if(( hDistAlpha=GlobalAlloc(GHND,2*m* sizeof(int)))==NULL){
		//MessageBox(hWnd,"Error alloc memory!","Error Message",MB_OK|MB_ICONEXCLAMATION);
		return FALSE;
	}
    
    lpTransArea=(int **)GlobalLock(hDistAlpha);
    
	for(i=0;i<2*m;i++)
	{
	  lpTransArea[i]=buf+i*180;//置每行的首地址,每行180度
	  memset(lpTransArea[i],0,180);//计数单元初始化为零
	}
    
   	// 计算图像每行的字节数
	LONG lLineBytes = 3*lWidth  ;
	int count=0;
 	for(y =w.BottomY;y<w.TopY;y++) 
	 {
		for(x =w.LeftX;x<w.RightX;x++)
		{

		// 指向源图像第j行,第i个象素的指针			
		 lpSrc = (BYTE *)(lpDIBBits + lLineBytes * y + 3*x);
		//如果是白点,则在变换域的对应各点上加1
    	 if( *lpSrc==255)
			{		//注意步长
		
			 for(k=w.MinAngle; k<w.MaxAngle;k++)
			  
			  {   //计算距离:
		         s =(long)(x*costab[k]+y*sintab[k]);
				//变换域的对应点上加1
				if(s>=0)
					lpTransArea[s][k]++;
				else
                   // lpTransArea[int(fabs(s))+m][k]++;
                      lpTransArea[int(s+2*m)][k]++;
			   }
			 
		     }
		}
	}
		
   //找到变换域中的最大值点 && fabs(k-90)>5
MaxValue1.Value=0;
     //找到最大值点
	for (iDist=0; iDist<2*m;iDist++)
	{
	  for(k=w.MinAngle; k<w.MaxAngle;k++)
		{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -