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;
}