www.pudn.com > OPENCV_SIFT_VC6.rar > TestSIFTDlg.cpp


// TestSIFTDlg.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "TestSIFT.h" 
#include "TestSIFTDlg.h" 
#include "SIFT.h" 
#include "cvcam.h" 
#include "MatchInfo.h" 
#include "MinHeap.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
 
IplImage *grayImg = NULL; 
 
///////////////////////////////////////////////////////////////////////////// 
// 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() 
 
///////////////////////////////////////////////////////////////////////////// 
// CTestSIFTDlg dialog 
 
CTestSIFTDlg::CTestSIFTDlg(CWnd* pParent /*=NULL*/) 
	: CDialog(CTestSIFTDlg::IDD, pParent) 
{ 
	//{{AFX_DATA_INIT(CTestSIFTDlg) 
	m_pause = FALSE; 
	//}}AFX_DATA_INIT 
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32 
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); 
} 
 
void CTestSIFTDlg::DoDataExchange(CDataExchange* pDX) 
{ 
	CDialog::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CTestSIFTDlg) 
	DDX_Check(pDX, IDC_CHK_PAUSE, m_pause); 
	//}}AFX_DATA_MAP 
} 
 
BEGIN_MESSAGE_MAP(CTestSIFTDlg, CDialog) 
	//{{AFX_MSG_MAP(CTestSIFTDlg) 
	ON_WM_SYSCOMMAND() 
	ON_WM_PAINT() 
	ON_WM_QUERYDRAGICON() 
	ON_BN_CLICKED(ID_EXIT, OnExit) 
	ON_BN_CLICKED(IDC_BTN_CAM, OnBtnCam) 
	ON_WM_CLOSE() 
	ON_BN_CLICKED(IDC_BTN_TRACK, OnBtnTrack) 
	ON_BN_CLICKED(IDC_CHK_PAUSE, OnChkPause) 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CTestSIFTDlg message handlers 
 
BOOL CTestSIFTDlg::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 
	return TRUE;  // return TRUE  unless you set the focus to a control 
} 
 
void CTestSIFTDlg::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 CTestSIFTDlg::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 CTestSIFTDlg::OnQueryDragIcon() 
{ 
	return (HCURSOR) m_hIcon; 
} 
 
/// Begin Global functions  
void drawSq (CKeyPoint* kp,IplImage* img) 
{ 
	CvPoint pt[4]; 
	int size = 10; 
	size *= kp->m_imgScale; 
	pt[0] = cvPoint (-size,-size); 
	pt[1] = cvPoint (-size,size); 
	pt[2] = cvPoint (size,size); 
	pt[3] = cvPoint (size,-size); 
	for (int i = 0; i < 4; i++) 
	{ 
		double angle = kp->m_orientation; 
		double xR = cos (angle) * pt[i].x - sin (angle) * pt[i].y; 
		double yR = sin (angle) * pt[i].x + cos (angle) * pt[i].y; 
		pt[i] = cvPoint ((int)(kp->m_x+xR),(int)(kp->m_y+yR)); 
	} 
	for (i = 0; i < 4; i++) 
		cvLine(img, pt[i], pt[(i+1)%4], cvScalar(0,255,255),1); 
	cvLine (img,cvPoint(kp->m_x,kp->m_y),cvPoint((pt[2].x+pt[3].x)/2,(pt[2].y+pt[3].y)/2),cvScalar(0,255,255),1); 
} 
 
std::vector  keypoints0; 
std::vector  keypoints1; 
BOOL isPause = false; 
 
void callback (IplImage *camImg) 
{ 
	if (isPause) 
		return; 
	cvFlip (camImg,NULL,0); 
	camImg->origin = 0; 
	if (grayImg == NULL) 
		grayImg = cvCreateImage (cvGetSize(camImg),IPL_DEPTH_8U,1); 
	cvCvtColor (camImg,grayImg,CV_RGB2GRAY); 
	CSIFT sift; 
	keypoints0.clear(); 
	sift.detect(grayImg,&keypoints0); 
	for (int i = 0; i < keypoints0.size(); i++) 
		drawSq (keypoints0[i],camImg); 
	for (i = 0; i < keypoints0.size(); i++) 
		delete keypoints0[i]; 
	cvShowImage ("cam",camImg); 
} 
 
 
CMatchInfo findNearest (CKeyPoint* kp0,int index0,std::vector& keypoints) 
{ 
	CMinHeap heap; 
	for (int index1 = 0; index1 < keypoints.size(); index1++) 
	{ 
		CKeyPoint* kp1 = keypoints[index1]; 
		int dim = kp0->m_xDim*kp0->m_yDim*kp0->m_oDim; 
		double dist = 0; 
		double secondMin = heap.get2ndMin(); 
		bool tooLarge = false; 
		for (int j = 0; j < dim; j++) 
		{ 
			double diff = (kp0->m_featureVec[j]-kp1->m_featureVec[j]); 
			dist += diff * diff; 
			if (dist > secondMin) 
			{ 
				tooLarge = true; 
				break; 
			} 
		} 
		if (tooLarge) 
			continue; 
		CMatchInfo info; 
 		info.m_distance = dist; 
		info.m_index0 = index0; 
		info.m_index1 = index1; 
		heap.insert (info); 
	} 
	if (heap.getSize() >= 2) 
	{ 
		CMatchInfo min1st = heap.deleteMin(); 
		CMatchInfo min2nd = heap.deleteMin(); 
		double ratio = min1st.m_distance/min2nd.m_distance; 
		if (ratio < 0.8) 
			return min1st; 
	} 
	CMatchInfo dummy; 
	return dummy; 
} 
 
void findCorrespond (std::vector& keypoints0,std::vector& keypoints1, 
					 CMinHeap& corrHeap) 
{ 
	for (int i = 0; i < keypoints0.size(); i++) 
	{ 
		CMatchInfo info = findNearest (keypoints0[i],i,keypoints1); 
		if (info.m_index0 >= 0) 
			corrHeap.insert (info); 
	} 
} 
 
IplImage *showImg = NULL; 
 
void stereocallback (IplImage *camImg0, IplImage *camImg1) 
{ 
	if (isPause) 
		return; 
	cvFlip (camImg0,NULL,0); 
	camImg0->origin = 0; 
	cvFlip (camImg1,NULL,0); 
	camImg1->origin = 0; 
 
	CSIFT sift; 
	keypoints0.clear(); 
	keypoints1.clear(); 
	if (grayImg == NULL) 
		grayImg = cvCreateImage (cvGetSize(camImg0),IPL_DEPTH_8U,1); 
	cvCvtColor (camImg0,grayImg,CV_RGB2GRAY); 
	sift.detect(grayImg,&keypoints0); 
	cvCvtColor (camImg1,grayImg,CV_RGB2GRAY); 
	sift.detect(grayImg,&keypoints1); 
	 
	int i; 
	//for (i = 0; i < keypoints0.size(); i++) 
	//	drawSq (keypoints0[i],camImg0); 
	//for (i = 0; i < keypoints1.size(); i++) 
	//	drawSq (keypoints1[i],camImg1); 
	 
	//TRACE ("%d , %d\n",keypoints0.size(),keypoints1.size()); 
 
	if (showImg == NULL) 
		showImg = cvCreateImage (cvSize(cvGetSize(camImg0).width*2,cvGetSize(camImg0).height),IPL_DEPTH_8U,3); 
	cvSetImageROI (showImg,cvRect(0,0,cvGetSize(camImg0).width,cvGetSize(camImg1).height)); 
	cvCopy (camImg0,showImg); 
	cvSetImageROI (showImg,cvRect(cvGetSize(camImg0).width,0,cvGetSize(camImg0).width,cvGetSize(camImg1).height)); 
	cvCopy (camImg1,showImg); 
	cvSetImageROI (showImg,cvRect(0,0,cvGetSize(camImg0).width*2,cvGetSize(camImg0).height)); 
	 
	CMinHeap corrHeap; 
	findCorrespond (keypoints0,keypoints1,corrHeap); 
	//TRACE ("Correct match : %d\n",corrHeap.getSize());	 
	if (corrHeap.getSize() >= 10) 
		for (i = 0; i < 10; i++)  
		{ 
			CMatchInfo info = corrHeap.deleteMin(); 
			//TRACE ("Found match\n"); 
			CvPoint pt0 = cvPoint (keypoints0[info.m_index0]->m_x,keypoints0[info.m_index0]->m_y); 
			CvPoint pt1 = cvPoint (keypoints1[info.m_index1]->m_x,keypoints1[info.m_index1]->m_y); 
			pt1.x += cvGetSize(camImg0).width; 
			cvCircle(showImg, pt0, 2, cvScalar(0,0,255), 2); 
			cvCircle(showImg, pt1, 2, cvScalar(0,0,255), 2); 
			cvLine(showImg, pt0, pt1, cvScalar(0,0,255),1); 
		} 
 
	for (i = 0; i < keypoints0.size(); i++) 
		delete keypoints0[i]; 
	for (i = 0; i < keypoints1.size(); i++) 
		delete keypoints1[i]; 
 
	cvShowImage ("cam",showImg); 
} 
 
/// End Global functions  
 
void CTestSIFTDlg::OnClose()  
{ 
	ClearResource(); 
	CDialog::OnClose(); 
} 
 
void CTestSIFTDlg::OnExit()  
{ 
	ClearResource(); 
	DestroyWindow(); 
} 
 
void CTestSIFTDlg::ClearResource() 
{ 
	cvcamStop( ); 
	cvcamExit( ); 
	cvDestroyWindow ("Image"); 
	if (grayImg != NULL) 
		cvReleaseImage (&grayImg); 
	if (showImg != NULL) 
		cvReleaseImage (&showImg); 
	cvDestroyWindow ("cam");	 
} 
 
void CTestSIFTDlg::OnBtnCam()  
{ 
	cvNamedWindow ("cam",CV_WINDOW_AUTOSIZE); 
	//cvCreateTrackbar ("mode","Debug",&debugindex,PARAMCOUNT-1,NULL);//trackChange); 
	int ncams = cvcamGetCamerasCount(); 
	if (ncams == 0) 
	{ 
		MessageBox ("Please plug-in camera"); 
		return; 
	} 
	cvcamSetProperty(0, CVCAM_PROP_ENABLE, CVCAMTRUE); 
	//cvcamSetProperty(0, CVCAM_PROP_RENDER, CVCAMTRUE); 
	cvcamSetProperty(0, CVCAM_PROP_CALLBACK, callback); 
	cvcamInit( ); 
	cvcamStart( ); 
	cvDestroyWindow ("cvcam window"); 
} 
 
void CTestSIFTDlg::OnBtnTrack()  
{ 
	// TODO: Add your control notification handler code here 
	if (cvcamGetCamerasCount() < 2) 
	{ 
		MessageBox ("Please plug-in 2 cameras"); 
		return; 
	} 
	cvNamedWindow ("cam",CV_WINDOW_AUTOSIZE); 
	cvcamSetProperty(0, CVCAM_PROP_ENABLE, CVCAMTRUE);  
	cvcamSetProperty(1, CVCAM_PROP_ENABLE, CVCAMTRUE);  
 
	int width = 320; 
	int height = 240; 
	cvcamSetProperty(0, CVCAM_RNDWIDTH, &width); 
	cvcamSetProperty(0, CVCAM_RNDHEIGHT, &height); 
	cvcamSetProperty(1, CVCAM_RNDWIDTH, &width); 
	cvcamSetProperty(1, CVCAM_RNDHEIGHT, &height); 
	cvcamSetProperty(1, CVCAM_STEREO_CALLBACK , stereocallback); 
	cvcamInit(); 
	cvcamStart(); 
	cvDestroyWindow ("cvcam window"); 
} 
 
void CTestSIFTDlg::OnChkPause()  
{ 
	// TODO: Add your control notification handler code here 
	UpdateData(true); 
	isPause = m_pause;  
}