📄 detectandtrackdlg.cpp
字号:
// 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 + -