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

📄 dlgreg.cpp

📁 《Visual C++数字图像获取 处理及实践应用》一书的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// DlgReg.cpp : implementation file
//

#include "stdafx.h"
#include "ImageProcessing.h"
#include "ImageProcessingDoc.h"
#include "GlobalApi.h"
#include "DlgReg.h"
#include "DlgAftReg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CDlgReg dialog


CDlgReg::CDlgReg(CWnd* pParent /*=NULL*/, CImageProcessingDoc* pDoc)
	: CDialog(CDlgReg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CDlgReg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// 获取文档类指针
	m_pDoc = pDoc;

	// 设置计算图象位置标志位位FALSE
	m_bCalImgLoc = FALSE;

	// 设置基准图象为原始打开的图象
	m_pDibInit = pDoc->m_pDibInit;

	// 设置待配准图象
	m_pDibSamp = new CDib;

	// 设置选取特征点的数目初始值
	m_nChsFeatureNum = 0;

	// 设置选取特征点的标志位为FALSE
	m_bChoseFeature = FALSE;
}


void CDlgReg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CDlgReg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CDlgReg, CDialog)
	//{{AFX_MSG_MAP(CDlgReg)
	ON_WM_PAINT()
	ON_BN_CLICKED(IDC_REG_OPEN, OnRegOpen)
	ON_BN_CLICKED(IDC_REG_REG, OnRegReg)
	ON_BN_CLICKED(IDC_REG_CHOSE_FEATURE, OnRegChoseFeature)
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDlgReg message handlers

void CDlgReg::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	
	// 如果还没有计算图象的位置,则进行计算
	if(!m_bCalImgLoc){
		CalImageLocation();
	}

	CSize sizeDisplay;
	CPoint pointDisplay;
	
	// 显示基准图象
	if(!m_pDibInit->IsEmpty()){
		sizeDisplay.cx=m_pDibInit->m_lpBMIH->biWidth;
		sizeDisplay.cy=m_pDibInit->m_lpBMIH->biHeight;
		pointDisplay.x = m_rectInitImage.left;
		pointDisplay.y = m_rectInitImage.top;
		m_pDibInit->Draw(&dc,pointDisplay,sizeDisplay);		
	}
	
	// 显示待配准图象
	if(!m_pDibSamp->IsEmpty()){
		sizeDisplay.cx=m_pDibSamp->m_lpBMIH->biWidth;
		sizeDisplay.cy=m_pDibSamp->m_lpBMIH->biHeight;
		pointDisplay.x = m_rectResltImage.left;
		pointDisplay.y = m_rectResltImage.top;
		m_pDibSamp->Draw(&dc,pointDisplay,sizeDisplay);		
	}

	// 显示特征点与配准的特征点
	DrawFeature(&dc);	
}

/*************************************************************************
 *
 * \函数名称:
 *   CalImageLocation()
 *
 * \输入参数:
 *   无
 *
 * \返回值:
 *   无
 *
 * \说明:
 *   该函数设置对话框中的控件位置和大小,并设置显示图象的位置。默认的图象大小为352×288,如果图象小于
 *此大小,则控件大小设置为352×288,并将图象放置在控件中间。
 *
 *************************************************************************
 */
void CDlgReg::CalImageLocation()
{
	// 获得控件IDC_REG_INIT_IMAGE的句柄,并获得控件的初始位置信息
	CWnd* pWnd=GetDlgItem(IDC_REG_INIT_IMAGE);
	WINDOWPLACEMENT *winPlacement;
	winPlacement=new WINDOWPLACEMENT;
	pWnd->GetWindowPlacement(winPlacement);
	
	// 图象宽度
	int nImageWidth;
	nImageWidth = m_pDibInit->m_lpBMIH->biWidth;

	// 图象高度
	int nImageHeight;
	nImageHeight = m_pDibInit->m_lpBMIH->biHeight;

	
	// 调整控件IDC_REG_INIT_IMAGE的大小位置,并同时设置显示基准图象的位置
	if(nImageHeight > 352){
		winPlacement->rcNormalPosition.bottom = winPlacement->rcNormalPosition.top + nImageHeight;	
		m_rectInitImage.bottom = winPlacement->rcNormalPosition.bottom;
		m_rectInitImage.top    = winPlacement->rcNormalPosition.top;		
	}
	else{
		winPlacement->rcNormalPosition.bottom = winPlacement->rcNormalPosition.top + 352;
		m_rectInitImage.bottom = winPlacement->rcNormalPosition.top + 176 + nImageHeight/2;
		m_rectInitImage.top    = winPlacement->rcNormalPosition.top + 176 - nImageHeight/2;
	}
	if(nImageWidth > 288){
		winPlacement->rcNormalPosition.right = winPlacement->rcNormalPosition.left + nImageWidth;
		m_rectInitImage.right = winPlacement->rcNormalPosition.right;
		m_rectInitImage.left  = winPlacement->rcNormalPosition.left;			
	}
	else{
		winPlacement->rcNormalPosition.right = winPlacement->rcNormalPosition.left + 288;
		m_rectInitImage.right = winPlacement->rcNormalPosition.left + 144 + nImageWidth/2;
		m_rectInitImage.left  = winPlacement->rcNormalPosition.left + 144 - nImageWidth/2;
	}

	// 设置IDC_REG_INIT_IMAGE控件的大小位置
	pWnd->SetWindowPlacement(winPlacement);	
			
	// 获得显示基准图象控件的右边位置,以便确认显示待配准图象控件的位置
	int nIniImgRight;
	nIniImgRight = winPlacement->rcNormalPosition.right;
	
	int  nIniImgLeft;
	nIniImgLeft   = winPlacement->rcNormalPosition.left;

	// 获得IDC_REG_INIT_IMAGE控件的下边位置,以便调整其他控件的位置
	int nIniImgBottom;
	nIniImgBottom = winPlacement->rcNormalPosition.bottom;

	// 获得控件IDC_REG_RESLT_IMAGE的句柄,并获得初始位置信息
	pWnd=GetDlgItem(IDC_REG_RESLT_IMAGE);
	pWnd->GetWindowPlacement(winPlacement);
	
	// 如果还未打开待配准图象,则设置待配准图象大小和基准图象大小相等
	if(!m_pDibSamp->IsEmpty()){
		nImageWidth  = m_pDibSamp->m_lpBMIH->biWidth;
		nImageHeight = m_pDibSamp->m_lpBMIH->biHeight;
	}
	
	// 调整控件IDC_REG_RESLT_IMAGE的大小位置,并同时设置显示待配准图象的位置

	// 先调整控件的左边位置,和IDC_REG_INIT_IMAGE控件相隔15个象素
	winPlacement->rcNormalPosition.left = nIniImgRight + 15;

	if(nImageHeight > 352){		
		winPlacement->rcNormalPosition.bottom = winPlacement->rcNormalPosition.top + nImageHeight;	
		m_rectResltImage.bottom = winPlacement->rcNormalPosition.bottom;
		m_rectResltImage.top    = winPlacement->rcNormalPosition.top;		
	}
	else{
		winPlacement->rcNormalPosition.bottom = winPlacement->rcNormalPosition.top + 352;
		m_rectResltImage.bottom = winPlacement->rcNormalPosition.top + 176 + nImageHeight/2;
		m_rectResltImage.top    = winPlacement->rcNormalPosition.top + 176 - nImageHeight/2;
	}
	if(nImageWidth > 288){
		winPlacement->rcNormalPosition.right = winPlacement->rcNormalPosition.left + nImageWidth;
		m_rectResltImage.right = winPlacement->rcNormalPosition.right;
		m_rectResltImage.left  = winPlacement->rcNormalPosition.left;			
	}
	else{
		winPlacement->rcNormalPosition.right = winPlacement->rcNormalPosition.left + 288;
		m_rectResltImage.right = winPlacement->rcNormalPosition.left + 144 + nImageWidth/2;
		m_rectResltImage.left  = winPlacement->rcNormalPosition.left + 144 - nImageWidth/2;
	}

	// 设置IDC_REG_RESLT_IMAGE控件的大小位置
	pWnd->SetWindowPlacement(winPlacement);
	
	if(nIniImgBottom < winPlacement->rcNormalPosition.bottom)
		nIniImgBottom = winPlacement->rcNormalPosition.bottom;


	nIniImgBottom = winPlacement->rcNormalPosition.bottom;
	
	nIniImgRight  = winPlacement->rcNormalPosition.right;
	
	// 设置控件IDOK的位置大小
	pWnd=GetDlgItem(IDOK);
	pWnd->GetWindowPlacement(winPlacement);
	winPlacement->rcNormalPosition.top = nIniImgBottom +15;
	winPlacement->rcNormalPosition.bottom = nIniImgBottom + 60;
	pWnd->SetWindowPlacement(winPlacement);
	
	// 设置控件IDCANCEL的位置大小
	pWnd=GetDlgItem(IDCANCEL);
	pWnd->GetWindowPlacement(winPlacement);
	winPlacement->rcNormalPosition.top = nIniImgBottom +15;
	winPlacement->rcNormalPosition.bottom = nIniImgBottom + 60;
	pWnd->SetWindowPlacement(winPlacement);

	// 设置控件IDC_REG_OPEN的位置大小
	pWnd=GetDlgItem(IDC_REG_OPEN);
	pWnd->GetWindowPlacement(winPlacement);
	winPlacement->rcNormalPosition.top = nIniImgBottom +15;
	winPlacement->rcNormalPosition.bottom = nIniImgBottom + 60;
	pWnd->SetWindowPlacement(winPlacement);
	
	// 设置控件IDC_REG_REG的位置大小
	pWnd=GetDlgItem(IDC_REG_REG);
	pWnd->GetWindowPlacement(winPlacement);
	winPlacement->rcNormalPosition.top = nIniImgBottom +15;
	winPlacement->rcNormalPosition.bottom = nIniImgBottom + 60;
	pWnd->SetWindowPlacement(winPlacement);
	
	
	// 设置控件IDC_REG_CHOSE_FEATUR的位置大小
	pWnd=GetDlgItem(IDC_REG_CHOSE_FEATURE);
	pWnd->GetWindowPlacement(winPlacement);
	winPlacement->rcNormalPosition.top = nIniImgBottom +15;
	winPlacement->rcNormalPosition.bottom = nIniImgBottom + 60;
	pWnd->SetWindowPlacement(winPlacement);

	// 调整此对话框的大小
	//pWnd = GetDlgItem(IDD_DLG_REG);
	this->GetWindowPlacement(winPlacement);
	//winPlacement->rcNormalPosition.top = nIniImgBottom +15;
	winPlacement->rcNormalPosition.bottom = nIniImgBottom + 300;
	winPlacement->rcNormalPosition.left   = nIniImgLeft   - 20;
	winPlacement->rcNormalPosition.right  = nIniImgRight  + 20;
	this->SetWindowPlacement(winPlacement);

	// 释放已分配内存
	delete winPlacement;

	// 设置计算图象控件位置标志位为TRUE
	m_bCalImgLoc = TRUE;
}

/*************************************************************************
 *
 * \函数名称:
 *   DrawFeature()
 *
 * \输入参数:
 *   无
 *
 * \返回值:
 *   无
 *
 * \说明:
 *   该函数根据类的成员变量确定特征点的数目和位置,并在图象中进行显示。
 *
 *************************************************************************
 */
void CDlgReg::DrawFeature(CDC* pDC)
{
	// 循环变量
	int i;

	// 临时变量
	CPoint pointTemp;

	// 半径
	int nRadius;
	nRadius = 5;

	// 设置画图类型
	pDC->SelectStockObject(HOLLOW_BRUSH);

	// 声明画笔
	CPen penWhite(PS_SOLID,1,RGB(255,255,255));
	CPen *pOldPen;

	// 将画笔选入,并保存以前的画笔
	pOldPen = pDC->SelectObject(&penWhite);

	for(i=0; i<m_nChsFeatureNum; i++){
		// 首先显示特征点
		
		// 确定此点的显示位置
		pointTemp.x = m_pPointSampl[i].x + m_rectResltImage.left;
		pointTemp.y = m_pPointSampl[i].y + m_rectResltImage.top ;		

		// 画出此特征点,其中园的半径为nRadius
		CRect rectSamp(pointTemp.x-nRadius , pointTemp.y-nRadius , 
			pointTemp.x+nRadius , pointTemp.y+nRadius);
		pDC->Ellipse(rectSamp);

		// 再显示配准特征点
		// 确定此点的显示位置
		pointTemp.x = m_pPointBase[i].x + m_rectInitImage.left;
		pointTemp.y = m_pPointBase[i].y + m_rectInitImage.top ;		

		// 画出此特征点,其中园的半径为nRadius
		CRect rectBase(pointTemp.x-nRadius , pointTemp.y-nRadius , 
			pointTemp.x+nRadius , pointTemp.y+nRadius);
		pDC->Ellipse(rectBase);
	}

	// 回复以前的画笔
	pDC->SelectObject(pOldPen);
	penWhite.DeleteObject();
}

/*************************************************************************
 *
 * \函数名称:
 *   OnRegOpen()
 *
 * \输入参数:
 *   无
 *
 * \返回值:
 *   无
 *
 * \说明:
 *   该函数打开待配准图象,并将图象存放在m_pDibSamp中。
 *
 *************************************************************************
 */
void CDlgReg::OnRegOpen() 
{
	// TODO: Add your control notification handler code here
	CFileDialog dlg(TRUE,"bmp","*.bmp");
	if(dlg.DoModal() == IDOK)
	{
 
	 	CFile file;
	 
	 	CString strPathName;
 
		strPathName = dlg.GetPathName();
 
		// 打开文件
		if( !file.Open(strPathName, CFile::modeRead | CFile::shareDenyWrite))
		{
			// 返回	
			return ;
		}

		// 读入模板图象
		if(!m_pDibSamp->Read(&file)){
			// 恢复光标形状
			EndWaitCursor();

			// 清空已分配内存
			m_pDibSamp->Empty();

			// 返回
 			return;
		}
	}
	
	// 判断是否是8-bpp位图(这里为了方便,只处理8-bpp位图的模板配准,其它的可以类推)
	if(m_pDibSamp->m_nColorTableEntries != 256)
	{
		// 提示用户
		MessageBox("目前只支持256色位图!", "系统提示" , MB_ICONINFORMATION | MB_OK);

		// 清空已分配内存
		m_pDibSamp->Empty();

		// 返回
		return;
	}

	// 如果打开新的待配准文件,将图象位置设置标志位设为FALSE,以便再次调整位置
	m_bCalImgLoc = FALSE;

	// 更新显示
	this->UpdateData();
	this->Invalidate();
}



/*************************************************************************
 *
 * \函数名称:
 *   OnRegChoseFeatureOnRegReg()
 *
 * \输入参数:
 *   无
 *
 * \返回值:
 *   无
 *
 * \说明:
 *   该函数设置选取特征点标志位,然后调用函数在待配准图象中选取特征点,并
 *配准这些特征点。特征点的数目至少应该选取三个。
 *
 *************************************************************************
 */
void CDlgReg::OnRegChoseFeature() 
{
	// 如果待配准图象尚未打开,则不能进行特征点选取工作
	if((m_pDibSamp->IsEmpty())){
		AfxMessageBox("尚未打开待配准图象文件,请打开待配准图象");
		return;
	}
	// 设置选取特征点标志位
	m_bChoseFeature = TRUE;	
	
	AfxMessageBox("请在待配准图象中选取特征点");
}

/*************************************************************************
 *
 * \函数名称:
 *   OnLButtonUp()
 *
 * \输入参数:
 *   无
 *
 * \返回值:
 *   无
 *
 * \说明:
 *   该函数根据鼠标所标定的位置设置特征点。然后调用特征配准函数配准此特征点。
 *特征点的数目至少应该选取三个。
 *
 *************************************************************************
 */
void CDlgReg::OnLButtonUp(UINT nFlags, CPoint point) 
{

⌨️ 快捷键说明

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