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

📄 detectandtrackdlg.cpp

📁 基于背景差分算法和C均值聚类算法的车辆检测与跟踪
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// DetectAndTrackDlg.cpp : implementation file
//

#include "stdafx.h"
#include "DetectAndTrack.h"
#include "DetectAndTrackDlg.h"
#include "SetLimit.h"
#include <cmath>
#include <algorithm>
#include <functional>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDetectAndTrackDlg dialog

CDetectAndTrackDlg::CDetectAndTrackDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CDetectAndTrackDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CDetectAndTrackDlg)
	m_strGroupResult = _T("");
	m_nCountOfObjects = 0;
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	//数据指针赋初值为空
	m_pbtBitsOfBackGround=NULL;
	m_pbtBitsOfDetect=NULL;
	m_pbtBitsOfDifference=NULL;
	m_pbtBitmap=NULL;
    m_pbtBackup=NULL;

	//聚类数据
	m_nCountOfGroup=3;
			
}

void CDetectAndTrackDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CDetectAndTrackDlg)
	DDX_Text(pDX, IDC_EDIT_GROUP_RESULT, m_strGroupResult);
	DDX_Text(pDX, IDC_EDIT_COUNT_OBJECT, m_nCountOfObjects);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CDetectAndTrackDlg, CDialog)
	//{{AFX_MSG_MAP(CDetectAndTrackDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_COMMAND(IDM_OPEN_BACKGROUND, OnOpenBackground)
	ON_COMMAND(IDM_OPEN_DETECT, OnOpenDetect)
	ON_COMMAND(IDM_EXIT, OnExit)
	ON_COMMAND(IDM_DO_DIFFERENCE, OnDoDifference)
	ON_COMMAND(ID_ABOUT, OnAbout)
	ON_COMMAND(IDM_COUNT_OBJECTS, OnCountObjects)
	ON_COMMAND(IDM_PRETREATMENT_DILATE, OnPretreatmentDilate)
	ON_COMMAND(IDM_PRETREATMENT_ERODT, OnPretreatmentErodt)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDetectAndTrackDlg message handlers

BOOL CDetectAndTrackDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	
	//初始设定三个子窗口,用于图片显示
	m_IWBackGround.Create(0,"BackGround",WS_CHILD|WS_VISIBLE,CRect(10,10,330,310), this, 10000);
    m_IWDetect.Create(0,"Detect",WS_CHILD|WS_VISIBLE,CRect(370,10,690,310), this,10001);
	m_IWDifference.Create(0,"Difference",WS_CHILD|WS_VISIBLE,CRect(10,320,330,620), this,10002);
	
	//初始化不允许统计
	(CFrameWnd*)AfxGetMainWnd()->GetMenu()->EnableMenuItem(IDM_COUNT_OBJECTS,MF_GRAYED);
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CDetectAndTrackDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CDetectAndTrackDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CDetectAndTrackDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}


/************************************************************************/
/*                          图像辅助函数                                */
/************************************************************************/

//获取数据
void CDetectAndTrackDlg::GetPoints(int nWidth, int nHeight, BYTE *pbtBits, BYTE *pbtPoints)
{
	int x,y,p;
    int nByteWidth=nWidth*3;
    if (nByteWidth%4) nByteWidth+=4-(nByteWidth%4);
    for(y=0;y<nHeight;y++)
	{
		for(x=0;x<nWidth;x++)
		{
			p=x*3+y*nByteWidth;
			pbtPoints[x+y*nWidth]=(BYTE)(0.299*(float)pbtBits[p+2]+0.587*(float)pbtBits[p+1]+0.114*(float)pbtBits[p]+0.1);
		}
	}
}

//输出数据
void CDetectAndTrackDlg::PutPoints(int nWidth, int nHeight, BYTE *pbtBits, BYTE *pbtPoints)
{
	
	int nByteWidth=nWidth*3;
	if (nByteWidth%4) nByteWidth+=4-(nByteWidth%4);
	int x,y,p,p1;
	for(y=0;y<nHeight;y++)
	{
		for(x=0;x<nWidth;x++)
		{
			p=x*3+y*nByteWidth;
			p1=x+y*nWidth;
			pbtBits[p]=pbtPoints[p1];
			pbtBits[p+1]=pbtPoints[p1];
			pbtBits[p+2]=pbtPoints[p1];
		}
	}
}
//载入图像
void CDetectAndTrackDlg::LoadBitmap()
{
	BITMAPINFOHEADER *pInfo;    //位图信息头
	pInfo=(BITMAPINFOHEADER *)(m_pbtBitmap+sizeof(BITMAPFILEHEADER));
	m_nWidth=pInfo->biWidth;      //获取位图宽度(单位为像素)
	m_nByteWidth=m_nWidth*3;        //扩展包含RGB分量    	
	if (m_nByteWidth%4) m_nByteWidth+=4-(m_nByteWidth%4);  //字节宽度一定要是四的整数倍,不足应该在后补零
	m_nHeight=pInfo->biHeight;    //获取位图高度
	if (pInfo->biBitCount!=24)    //判断是否为真彩色位图
	{
		if (pInfo->biBitCount!=8)       //只处理256灰度级的位图
		{
			AfxMessageBox("无效位图");  //发出警告
			delete m_pbtBitmap;         //删除位图
			m_pbtBitmap=0;              //为下次加载做初始化
			return;
		}
		unsigned int PaletteSize=1<<pInfo->biBitCount;            //获取调色板大小
		if (pInfo->biClrUsed!=0 && pInfo->biClrUsed<PaletteSize)  //判断文件中出现的灰度色级是否超出biBitCount所表示的范围.
			PaletteSize=pInfo->biClrUsed;
		m_pbtBits=m_pbtBitmap+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); //获取颜色表指针
		RGBQUAD *pPalette=(RGBQUAD *)m_pbtBits;   //定义颜色表结构,并让其指向位图文件中的颜色表  
		m_pbtBits+=sizeof(RGBQUAD)*PaletteSize;   //让lpBits指向BMP文件的IMAGEDATA区域
		m_nLen=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+m_nByteWidth*m_nHeight;  //计算文件大小
		BYTE *lpTemp=m_pbtBitmap;
		m_pbtBitmap=new BYTE[m_nLen];  //开辟空间
		BITMAPFILEHEADER bmh;          //定义位图文件头结构
		BITMAPINFOHEADER bmi;          //定义位图信息头结构
		bmh.bfType='B'+'M'*256;        //文件类型赋值为位图类型
		bmh.bfSize=m_nLen;             //文件大小为m_nLen
		bmh.bfReserved1=0;             //保留值必须为0
		bmh.bfReserved2=0;
		bmh.bfOffBits=54;              //文件头到数据的偏移         
		bmi.biSize=sizeof(BITMAPINFOHEADER); //固定值
		bmi.biWidth=m_nWidth;          //位图宽度
		bmi.biHeight=m_nHeight;        //位图高度
		bmi.biPlanes=1;                //目标设备的位面数,必须为1
		bmi.biBitCount=24;             //颜色深度,即每个像素占24位
		bmi.biCompression=BI_RGB;      //压缩类型为BI_RGB
		bmi.biSizeImage=0;      
		bmi.biXPelsPerMeter=0;        //水平分辨率
		bmi.biYPelsPerMeter=0;        //垂直分辨率
		bmi.biClrUsed=0;              //表示使用2的biBitCount次方的色级
		bmi.biClrImportant=0;         //无重要颜色
		int nBWidth=pInfo->biWidth;    //获取位图宽度
		if (nBWidth%4) nBWidth+=4-(nBWidth%4);  //
		memset(m_pbtBitmap,0,m_nLen);	//清零函数
		memcpy(m_pbtBitmap,&bmh,sizeof(BITMAPFILEHEADER));   //将BITMAPFILEHEADER内容拷到到bmh中
		memcpy(m_pbtBitmap+sizeof(BITMAPFILEHEADER),&bmi,sizeof(BITMAPINFOHEADER));  //将BITMAPINFOHEADER内容拷到bmi中
		BYTE*lpBits2=m_pbtBitmap+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); //lpBits2指向调色板
		int x,y,p1,p2,Palette;
		//像素色彩值的读取
		for(y=0;y<m_nHeight;y++)
		{
			for(x=0;x<m_nWidth;x++)  
			{p1=y*nBWidth+x;        //取得像素下标
			p2=y*m_nByteWidth+x*3;    //三个一组的移动
			if (m_pbtBits[p1]<PaletteSize) Palette=m_pbtBits[p1]; //取得在biClrUsed范围的象素值,如果超出范围则赋值为0
			else Palette=0;
			lpBits2[p2]=pPalette[Palette].rgbBlue;
			lpBits2[p2+1]=pPalette[Palette].rgbGreen; //对调色板的分量进行赋值
			lpBits2[p2+2]=pPalette[Palette].rgbRed;
			}
		}
		delete lpTemp;
	}
	m_pbtBits=m_pbtBitmap+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER); //对于真彩色位图直接获取IMAGEDATA
	if (m_pbtBackup) delete m_pbtBackup;
	m_pbtBackup=new BYTE[m_nLen];
	memcpy(m_pbtBackup,m_pbtBitmap,m_nLen); 
}

/************************************************************************/
/*                        C均值算法辅助函数                             */
/************************************************************************/

//初始筛选出像素值为255的像素点
void CDetectAndTrackDlg::FilterPoints()
{
	m_VectorOfPoints.clear();      //清空容器
	for (int i=0;i<m_nHeight;i++)  //遍历差分图像,筛选出像素值为255的点
	{
		for (int j=0;j<m_nWidth;j++)
		{
			if (m_pbtBitsOfDifference[i*m_nWidth+j]==255)
			{
				CPixelPoint *Point=new CPixelPoint(i,j,-1);  //获取下标,初始聚类设定为-1
				m_VectorOfPoints.push_back(*Point);          //存入容器
				delete Point;                                //释放空间
			}
		}
	}
}

//初始聚类中心
void CDetectAndTrackDlg::InitCenter()
{
	m_VectorOfGroup.clear();
	for (int i=0;i<m_nCountOfGroup;i++)
	{
		//选取前C个像素点为聚类中心
		CGroup *group=new CGroup;                  
		group->m_obOldCenter=m_VectorOfPoints[i];
		group->m_obNewCenter=m_VectorOfPoints[i];
		m_VectorOfGroup.push_back(*group); 
		delete group;

		CPixelPoint point=m_VectorOfGroup[i].m_obOldCenter;
	}	
}

//两项像素点间距离
float CDetectAndTrackDlg::Distance(CPixelPoint &p1, CPixelPoint &p2)
{
	float fDistance=0.0f;
	fDistance=powf((p1.m_nXCoordinate-p2.m_nXCoordinate),2)
		     +powf((p1.m_nYCoordinate-p2.m_nYCoordinate),2);

	return (sqrtf(fDistance));
}

//对像素点进行聚类
void CDetectAndTrackDlg::Allocate()
{
	int nGroupNO;
	float *pfDistance=new float[m_nCountOfGroup];

	for (int i=0;i<m_nCountOfGroup;i++)  //聚类中像素点数目清零
	{
		m_VectorOfGroup[i].m_nCount=0;
	}	
	
	for (i=0;i<m_VectorOfPoints.size();i++)      //遍历像素点
	{
		for (int j=0;j<m_nCountOfGroup;j++)  //与每个聚类中心求距离
		{
			pfDistance[j]=Distance(m_VectorOfPoints[i],m_VectorOfGroup[j].m_obOldCenter);
		}

		nGroupNO=min_element(pfDistance,pfDistance+m_nCountOfGroup)-pfDistance;  //找出属于的类别
		m_VectorOfPoints[i].m_nNumOfClass=nGroupNO;
		m_VectorOfGroup[nGroupNO].m_nCount+=1;
	}

	delete [] pfDistance;
}

//修正聚类中心
void CDetectAndTrackDlg::ReviseCenter()
{
	float fXCoordinate; //X坐标

⌨️ 快捷键说明

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