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

📄 childview.cpp

📁 实时视频跟踪源码
💻 CPP
字号:
// ChildView.cpp : implementation of the CChildView class
//

#include "stdafx.h"
#include "Tracker.h"
#include "MainFrm.h"
#include "ChildFrm.h"
#include "ChildView.h"
#include "TrackDlg.h"

#include <math.h>

#include <list>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

typedef struct QSEG_ {
    POINT head;
    UINT length;
} QSEG, *LPQSEG;

// CChildView

BYTE CChildView::bThreshold = 250;
DWORD CChildView::dwRectangle = 0;
DWORD CChildView::dwSegment = 0;

CChildView::CChildView()
{
}

CChildView::~CChildView()
{
}


BEGIN_MESSAGE_MAP(CChildView, CWnd)
	ON_WM_PAINT()
    ON_COMMAND(ID_DEVICE_REFRESH, OnDeviceRefresh)
    ON_COMMAND_RANGE(ID_DEVICE_NAME, ID_DEVICE_NAME+CVideoCapWnd::m_dwDeviceMax, OnDeviceName)
    ON_COMMAND(ID_CAPTURE_SOURCE, OnCaptureSource)
    ON_COMMAND(ID_CAPTURE_FORMAT, OnCaptureFormat)
    ON_COMMAND(ID_CAPTURE_DISPLAY, OnCaptureDisplay)    
    ON_WM_SIZE()
    ON_COMMAND_RANGE(ID_CAPTURE_100, ID_CAPTURE_200, OnCaptureZoom)
    ON_COMMAND(ID_TRACK_BRIGHTNESS, OnTrackBrightness)
    ON_COMMAND(ID_TRACK_STOP, OnTrackStop)
    ON_COMMAND(ID_CAPTURE_STOP, OnCaptureStop)
END_MESSAGE_MAP()



// CChildView message handlers

BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs) 
{
	if (!CWnd::PreCreateWindow(cs))
		return FALSE;

	cs.dwExStyle |= WS_EX_CLIENTEDGE;
	cs.style &= ~WS_BORDER;
	cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS, 
		::LoadCursor(NULL, IDC_ARROW), reinterpret_cast<HBRUSH>(COLOR_WINDOW+1), NULL);

	return TRUE;
}

void CChildView::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	
	// TODO: Add your message handler code here
	
	// Do not call CWnd::OnPaint() for painting messages
}

void CChildView::OnDeviceRefresh()
{
    /* -- Get device menu. --*/
    CMenu *mDev = AfxGetMainWnd()->GetMenu()->GetSubMenu(3);
    
    MENUITEMINFO miInfo;    
    do
    {
        /* -- Find position of separator. -- */
        miInfo.cbSize = sizeof(MENUITEMINFO);
        miInfo.fMask = MIIM_TYPE;
        mDev->GetMenuItemInfo(0, &miInfo, TRUE);
        /* -- Delete all entries before separator. -- */
        if (miInfo.fType != MFT_SEPARATOR) {
            mDev->DeleteMenu(0, MF_BYPOSITION);
        }
    }   while (miInfo.fType != MFT_SEPARATOR);    
  
    /* -- Put device names before separator. -- */
    CString strDevName, strDevVer; 
    for (DWORD i=0; i<m_theVideoCapWnd.m_dwDeviceMax; ++i) {
        m_theVideoCapWnd.GetDriverDescription(i, strDevName, strDevVer);
        if (strDevName.GetLength()) {
            mDev->InsertMenu(0, MF_BYPOSITION, ID_DEVICE_NAME+i, strDevName);
        }
    }    
}

void CChildView::OnDeviceName(UINT nID)
{
    /* -- Get device index by subtracting the offset. -- */
    nID = nID - ID_DEVICE_NAME;
    
    CString strErr;
        
    /* -- Create the capture window if we haven't done do. -- */
    if (m_theVideoCapWnd.m_hWnd == NULL) {
        m_theVideoCapWnd.CreateCaptureWindow(CString(""), WS_CHILD | WS_VISIBLE, CRect(0,0,0,0), this, 0);
        if (m_theVideoCapWnd.m_hWnd == NULL) {
            strErr.LoadString(IDS_ERR_CAPWND);
            MessageBox(strErr);
            return;
        }
    }
   
    /* -- Attempt to connect to driver. -- */
    if (m_theVideoCapWnd.DriverConnect(nID) == FALSE) {
        strErr.LoadString(IDS_ERR_CONNECT);
        MessageBox(strErr);
        return;
    }

    /* -- Retrieve device parameters. -- */
    CAPTUREPARMS capParms;        
    if (m_theVideoCapWnd.CaptureGetSetup(&capParms, sizeof(CAPTUREPARMS)) == FALSE) {
        strErr.LoadString(IDS_ERR_GETSETUP);
        MessageBox(strErr);
        return;
    }
    
    /* -- Want separate thread. -- */
    capParms.fYield = TRUE;
    /* -- Do not abort when left mouse button is clicked. -- */
    capParms.fAbortLeftMouse = FALSE;
    /* -- Do not abort when right mouse button is clicked. -- */
    capParms.fAbortRightMouse = FALSE;
    
    /* -- Update device parameters. -- */
    if (m_theVideoCapWnd.CaptureSetSetup(&capParms, sizeof(CAPTUREPARMS)) == FALSE) {
        strErr.LoadString(IDS_ERR_SETSETUP);
        MessageBox(strErr);
        return;
    }

    /* -- Get current state of capture window. -- */
    CAPSTATUS capStat;    
    if (m_theVideoCapWnd.GetStatus(&capStat, sizeof(CAPSTATUS)) == FALSE) {
        strErr.LoadString(IDS_ERR_GETSTAT);
        MessageBox(strErr);
        return;
    }
    
    m_theVideoCapWnd.SetWindowPos(NULL, 0, 0, capStat.uiImageWidth, capStat.uiImageHeight, SWP_NOMOVE | SWP_NOZORDER);
    GetParentFrame()->SetWindowPos(NULL, 0, 0, capStat.uiImageWidth, capStat.uiImageHeight, SWP_NOMOVE);
    
    /* -- Set preview rate. -- */                
    if (m_theVideoCapWnd.PreviewRate(33) == FALSE) {
        strErr.LoadString(IDS_ERR_PREVRATE);
        MessageBox(strErr);
        return;
    }
    
    /* -- Turn on scaling. -- */
    if (m_theVideoCapWnd.PreviewScale(TRUE) == FALSE) {
        strErr.LoadString(IDS_ERR_PREVSCALE);
        MessageBox(strErr);
        return;
    }
    
    /* -- Start preview. -- */
    if (m_theVideoCapWnd.Preview(TRUE) == FALSE) {
        strErr.LoadString(IDS_ERR_PREV);
        MessageBox(strErr);
        return;
    }
}

void CChildView::OnCaptureSource()
{
    CString strErr;

    /* -- Retrieve device capabilities. -- */
    CAPDRIVERCAPS capCap;
    if (m_theVideoCapWnd.DriverGetCaps(&capCap, sizeof(CAPDRIVERCAPS)) == FALSE) {
        strErr.LoadString(IDS_ERR_GETCAPS);
        MessageBox(strErr);
        return;
    }
    
    /* -- Check if device supports video source dialog. -- */
    if (capCap.fHasDlgVideoSource) {
        if (m_theVideoCapWnd.DlgVideoSource() == FALSE) {
            strErr.LoadString(IDS_ERR_SOURCE);
            MessageBox(strErr);
        }
    }
    else {
        strErr = "Device does not support video source dialog.";
        MessageBox(strErr);
    }    
}

void CChildView::OnCaptureFormat()
{
    CString strErr;
    
    /* -- Retrieve device capabilities. -- */
    CAPDRIVERCAPS capCap;
    if (m_theVideoCapWnd.DriverGetCaps(&capCap, sizeof(CAPDRIVERCAPS)) == FALSE) {
        strErr.LoadString(IDS_ERR_GETCAPS);
        MessageBox(strErr);
        return;
    }
    
    /* -- Check if device supports video format dialog. -- */
    if (capCap.fHasDlgVideoFormat) {
        if (m_theVideoCapWnd.DlgVideoFormat() == FALSE) {
            strErr.LoadString(IDS_ERR_FORMAT);
            MessageBox(strErr);
        }
    }
    else {
        strErr = "Device does not support video format dialog.";
        MessageBox(strErr);
    }
}

void CChildView::OnCaptureDisplay()
{
    CString strErr;
    
    /* -- Retrieve device capabilities. -- */    
    CAPDRIVERCAPS capCap;
    if (m_theVideoCapWnd.DriverGetCaps(&capCap, sizeof(CAPDRIVERCAPS)) == FALSE) {
        strErr.LoadString(IDS_ERR_GETCAPS);
        MessageBox(strErr);
        return;
    }
    
    /* -- Check if device supports video display dialog. -- */
    if (capCap.fHasDlgVideoDisplay) {
        if (m_theVideoCapWnd.DlgVideoDisplay() == FALSE) {
            strErr.LoadString(IDS_ERR_DISPLAY);
            MessageBox(strErr);
        }
    }
    else {
        strErr = "Device does not support video display dialog.";
        MessageBox(strErr);
    }
}

void CChildView::OnSize(UINT nType, int cx, int cy)
{
    CWnd::OnSize(nType, cx, cy);

    // TODO: Add your message handler code here
    
    /* -- Centralize the video capture window. -- */
    if (m_theVideoCapWnd.m_hWnd != NULL) {
        CRect paRect, cpRect;
        GetClientRect(&paRect);
        m_theVideoCapWnd.GetClientRect(&cpRect);
        m_theVideoCapWnd.SetWindowPos(NULL, 0, 0, paRect.Width(), paRect.Height(), SWP_NOMOVE | SWP_NOZORDER);
    }
    else {
        /* -- Resize the child window. -- */
        GetParentFrame()->SetWindowPos(NULL, 0, 0, 200, 200, SWP_NOMOVE);
    }
}

void CChildView::OnCaptureZoom(UINT nID)
{
    if (m_theVideoCapWnd.m_hWnd != NULL) {
        /* -- Get current state of capture window. -- */
        CAPSTATUS capStat;    
        if (m_theVideoCapWnd.GetStatus(&capStat, sizeof(CAPSTATUS))) {
            UINT nZoom = nID - ID_CAPTURE_100 + 1;
            UINT nWidth = capStat.uiImageWidth * nZoom;
            UINT nHeight = capStat.uiImageHeight * nZoom;
            m_theVideoCapWnd.SetWindowPos(NULL, 0, 0, nWidth, nHeight, SWP_NOMOVE | SWP_NOZORDER);
            CMDIChildWnd *pChild = DYNAMIC_DOWNCAST(CMDIChildWnd, GetParentFrame());
            pChild->MDIRestore();
            GetParentFrame()->SetWindowPos(NULL, 0, 0, nWidth, nHeight, SWP_NOMOVE);
        }
        else {
            CString strErr;
            strErr.LoadString(IDS_ERR_GETSTAT);
            MessageBox(strErr);
        }
    }
}

LRESULT CChildView::FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVideoHdr)
{
    CVideoCapWnd theVideoCapWnd; 
    CAPSTATUS capStat;
    
    theVideoCapWnd.Attach(hWnd);
    
    if (theVideoCapWnd.GetStatus(&capStat, sizeof(CAPSTATUS))) {
    
        UINT nWidth = capStat.uiImageWidth;
        UINT nHeight = capStat.uiImageHeight;
        LPBYTE lpData = lpVideoHdr->lpData;
        
        ASSERT(lpVideoHdr->dwBytesUsed == nWidth * nHeight * 3);
        
        if (dwRectangle)
        {
            BYTE Y; int index; bool init = false; 
                          
            /* -- Variables used by simple tracking algorithm. -- */
            POINT pTop, pBottom, pLeft, pRight;
            
            for (int i=0; i<nHeight; ++i) {
                for (int j=0; j<nWidth; ++j) {
                    index = 3*(i*nWidth+j);
                    Y = floor(0.299*lpData[index+2] + 0.587*lpData[index+1] + 0.114*lpData[index] + 0.5);

                    if (Y > bThreshold) {
                        if (init) {
                            if (pLeft.x > j) {
                                pLeft.x = j;
                                pLeft.y = i;
                            }
                            if (pRight.x < j) {
                                pRight.x = j;
                                pRight.y = i;
                            }
                            pBottom.x = j;
                            pBottom.y = i;
                        }
                        else {
                            pTop.x = pBottom.x = pLeft.x = pRight.x = j;
                            pTop.y = pBottom.y = pLeft.y = pRight.y = i;
                            init = true;
                        }
                    }
                }
            }

            /* -- Data regarding object being tracked stored, do something simple about it.  -- */
            if (init) {
                for (int i=pLeft.x; i<=pRight.x; ++i) {
                    // -- For pTop.y and pBottom.y --
                    index = 3*((pTop.y)*nWidth + i);
                    lpData[index]   = 0;
                    lpData[index+1] = 0;
                    lpData[index+2] = 255;

                    index = 3*((pBottom.y)*nWidth + i);
                    lpData[index]   = 0;
                    lpData[index+1] = 0;
                    lpData[index+2] = 255;
                }

                for (int i=pTop.y; i<=pBottom.y; ++i) {
                    // -- For pLeft.x and pRight.x --
                    index = 3*((i)*nWidth + pLeft.x);
                    lpData[index]   = 0;
                    lpData[index+1] = 0;
                    lpData[index+2] = 255;

                    index = 3*((i)*nWidth + pRight.x);
                    lpData[index]   = 0;
                    lpData[index+1] = 0;
                    lpData[index+2] = 255;
                }
            }
        }
    
        else if (dwSegment)
        {
            BYTE Y; int index;        

            /* -- Variables used by the new tracking algorithm. -- */
            QSEG segment;
            std::list<QSEG> object;

            for (int i=0; i<nHeight; ++i) {
                segment.length = 0;
                for (int j=0; j<nWidth; ++j) {
                    index = 3*(i*nWidth+j);
                    Y = floor(0.299*lpData[index+2] + 0.587*lpData[index+1] + 0.114*lpData[index] + 0.5);

                    if (Y > bThreshold) {
                        if (segment.length == 0) {
                            segment.head.x = j;
                            segment.head.y = i;
                        }
                        ++segment.length;
                    }
                }
                if (segment.length) {
                    object.push_back(segment);
                }
            }
            
            /* -- Data regarding object being tracked stored, do something simple about it.  -- */            
            for (std::list<QSEG>::iterator i=object.begin(); i!=object.end(); ++i) {
                index = 3*((*i).head.y*nWidth + (*i).head.x);
                lpData[index]   = 255;
                lpData[index+1] = 0;
                lpData[index+2] = 255;                
               
                index = 3*((*i).head.y*nWidth + (*i).head.x + (*i).length);
                lpData[index]   = 255;
                lpData[index+1] = 0;
                lpData[index+2] = 255;
            }
        }    
    }    

    theVideoCapWnd.Detach();
    
    return 0;
}

void CChildView::OnTrackBrightness()
{
    // TODO: Add your command handler code here
    CTrackDlg dlg;
    if (dlg.DoModal()) {
        bThreshold = atoi(dlg.m_strBrightness);        
        if (dlg.m_blRectangle == BST_CHECKED) {
            dwRectangle = 1;
            dwSegment = 0;
        }
        else if (dlg.m_blSegment == BST_CHECKED) {
            dwRectangle = 0;
            dwSegment = 1;
        }
        else {
            dwRectangle = 0;
            dwSegment = 0;
        }
        m_theVideoCapWnd.SetCallbackOnFrame(FrameCallbackProc);        
    }
}

void CChildView::OnTrackStop()
{
    // TODO: Add your command handler code here
    m_theVideoCapWnd.SetCallbackOnFrame((FrameCallback)(NULL));    
}

void CChildView::OnCaptureStop()
{
    // TODO: Add your command handler code here
    m_theVideoCapWnd.DriverDisconnect();
}

⌨️ 快捷键说明

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