📄 handvufilter.cpp
字号:
/** * HandVu - a library for computer vision-based hand gesture * recognition. * Copyright (C) 2004 Mathias Kolsch, matz@cs.ucsb.edu * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * $Id: HandVuFilter.cpp,v 1.22 2005/10/30 23:00:43 matz Exp $**/#include "StdAfx.h"
#include <initguid.h>
#if (1100 > _MSC_VER)
#include <olectlid.h>
#else
#include <olectl.h>
#endif
//#define USE_FDL
#include "HandVuFilterGUIDs.h"
#include "Common.h"
#include "HandVuFilter.h"
#include "HandVuFilterProp.h"
#include "MaintenanceApp.h"
#ifdef USE_FDL
#include "FrameDataLib.h"
#endif USE_FDL
#ifdef HAVE_USER_STUDY
#include "../hv_UserStudy/UserStudyA.h"
#include "../hv_UserStudy/UserStudyB.h"
#endif HAVE_USER_STUDY
#include "HandVu.h"
// wrong #define causes a warning in ipl.h ... annoying:
//#undef _VXWORKS
#include <CV.h>
#include "resource.h"
#ifndef M_PI
#define M_PI 3.141592653589793
#endif /* M_PI */
// Setup information
const AMOVIESETUP_MEDIATYPE sudPinTypes =
{
&MEDIATYPE_Video, // Major type
&MEDIASUBTYPE_NULL // Minor type
};
const AMOVIESETUP_PIN sudpPins[] =
{
{ L"Input", // Pins string name
FALSE, // Is it rendered
FALSE, // Is it an output
FALSE, // Are we allowed none
FALSE, // And allowed many
&CLSID_NULL, // Connects to filter
NULL, // Connects to pin
1, // Number of types
&sudPinTypes // Pin information
},
{ L"Output", // Pins string name
FALSE, // Is it rendered
TRUE, // Is it an output
FALSE, // Are we allowed none
FALSE, // And allowed many
&CLSID_NULL, // Connects to filter
NULL, // Connects to pin
1, // Number of types
&sudPinTypes // Pin information
}
};
const AMOVIESETUP_FILTER sudHandVuFilter =
{
&CLSID_HandVuFilter, // Filter CLSID
L"HandVuFilter", // String name
MERIT_DO_NOT_USE, // Filter merit
2, // Number of pins
sudpPins // Pin information
};
// List of class IDs and creator functions for the class factory. This
// provides the link between the OLE entry point in the DLL and an object
// being created. The class factory will call the static CreateInstance
CFactoryTemplate g_Templates[] = {
{ L"HandVuFilter (Filter)"
, &CLSID_HandVuFilter
, CHandVuFilter::CreateInstance
, NULL
, &sudHandVuFilter }
,
{ L"HandVuFilter (Property Page)"
, &CLSID_HandVuFilterPropertyPage
, CHandVuFilterProperties::CreateInstance }
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
//
// DllRegisterServer
//
// Handles sample registry and unregistry
//
STDAPI DllRegisterServer()
{
return AMovieDllRegisterServer2( TRUE );
} // DllRegisterServer
//
// DllUnregisterServer
//
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2( FALSE );
} // DllUnregisterServer
//
// Constructor
//
CHandVuFilter::CHandVuFilter(TCHAR *tszName,
LPUNKNOWN punk,
HRESULT *phr,
bool bModifiesData /* = true */)
: CTransInPlaceFilter(tszName, punk, CLSID_HandVuFilter, phr, bModifiesData),
m_img_bottom_up(false),
m_cxImage(-1),
m_cyImage(-1),
m_show_maintenanceapp(false),
m_FDL_only(false),
m_take_one_snapshot(false),
m_is_initialized(false),
m_FDL_is_initialized(false),
m_pColorHeader(NULL),
m_pOverlay(NULL),
#ifdef HAVE_USER_STUDY
m_pUserStudyA(NULL),
m_pUserStudyB(NULL),
#endif
CPersistStream(punk, phr)
{
string root_dir("C:\\hv_tmp");
_mkdir(root_dir.c_str());
string fname_root(root_dir + "\\hvsnap_"); hvSetSaveFilenameRoot(fname_root);
m_params.immediate_apply = true;
// debugging:
DbgSetModuleLevel(LOG_CUSTOM1, 3);
} // (Constructor)
CHandVuFilter::~CHandVuFilter()
{
hvUninitialize();
}
//
// CreateInstance
//
// Provide the way for COM to create a HandVuFilter object
//
CUnknown *CHandVuFilter::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
{
CHandVuFilter *pNewObject =
new CHandVuFilter(NAME("HandVuFilter"), punk, phr);
if (pNewObject == NULL) {
*phr = E_OUTOFMEMORY;
}
return pNewObject;
} // CreateInstance
//
// NonDelegatingQueryInterface
//
// Reveals IHandVuFilter and ISpecifyPropertyPages
//
STDMETHODIMP CHandVuFilter::NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
CheckPointer(ppv,E_POINTER);
if (riid == IID_IHandVuFilter) {
return GetInterface((IHandVuFilter *) this, ppv);
} else if (riid == IID_ISpecifyPropertyPages) {
return GetInterface((ISpecifyPropertyPages *) this, ppv);
} else {
return CTransInPlaceFilter::NonDelegatingQueryInterface(riid, ppv);
}
} // NonDelegatingQueryInterface
//
// Transform (in place)
//
HRESULT CHandVuFilter::Transform(IMediaSample *pMediaSample)
{
#if 0
static dropme = false;
if (dropme) {
dropme = false;
m_bSampleSkipped = true;
return S_FALSE;
} else {
dropme = true;
}
#endif //0
CAutoLock lock(&m_HandVuFilterLock);
AM_MEDIA_TYPE* pType = &m_pInput->CurrentMediaType();
VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pType->pbFormat;
BYTE *pData; // Pointer to the actual image buffer
long lDataLen; // Holds length of any given sample
pMediaSample->GetPointer(&pData);
lDataLen = pMediaSample->GetSize();
m_bSampleSkipped = false;
if (!m_is_initialized) {
VERBOSE0(3, "HandVuFilter: init during playback");
// Get the image properties from the BITMAPINFOHEADER
int iPixelSize = pvi->bmiHeader.biBitCount / 8;
int width = pvi->bmiHeader.biWidth;
int height = pvi->bmiHeader.biHeight;
HRESULT hr = Initialize(width, height, iPixelSize, NULL);
if (!SUCCEEDED(hr)) {
throw HVException("HandVuFilter: concurrent initialization");
}
}
{ // test if change from initialization
int width = pvi->bmiHeader.biWidth;
int height = pvi->bmiHeader.biHeight;
bool img_bottom_up = true;
if (height<0) {
// norm for RGB images
img_bottom_up = false;
height = -height;
}
if (width!=m_cxImage || height!=m_cyImage || img_bottom_up!=m_img_bottom_up) {
VERBOSE0(1, "HandVuFilter: format changed!");
throw HVException("HandVuFilter: format changed!");
}
}
m_pColorHeader->imageData = (char*) pData;
m_pColorHeader->imageSize = lDataLen;
REFERENCE_TIME st_start, st_end;
pMediaSample->GetTime(&st_start, &st_end);
m_t_sample = st_start/10;
#ifdef HAVE_USER_STUDY
// check DV input for marks
if (m_pUserStudyB) {
if (!m_pIAMTCReader) {
AfxMessageBox("need time code reader for StudyHV2");
} else {
m_pUserStudyB->AtTimecode(GetTimecode());
}
}
#endif
if (m_img_bottom_up) {
cvMirror(m_pColorHeader, NULL, 0); // flip on horizontal axis
}
// ------- main library call ---------
VERBOSE0(5, "HandVuFilter: will process frame"); hvAction action = HV_INVALID_ACTION;
action = hvProcessFrame(m_pColorHeader);
VERBOSE0(5, "HandVuFilter: HandVu finished processing frame"); // -------
for (int i=0; i<(int)m_HVFListenerPtrs.size(); i++) {
m_HVFListenerPtrs[i]->FrameTransformed(action!=HV_DROP_FRAME);
}
if (action==HV_DROP_FRAME) {
// HandVu recommends dropping the frame entirely
#ifdef HAVE_USER_STUDY
if (m_pUserStudyA) {
m_pUserStudyA->DontDraw(m_pColorHeader);
}
#endif
m_bSampleSkipped = true;
VERBOSE0(3, "HandVuFilter: dropping frame");
return S_FALSE;
} else if (action==HV_SKIP_FRAME) {
// HandVu recommends displaying the frame, but not doing any further
// processing on it - keep going
} else if (action==HV_PROCESS_FRAME) {
// full processing was done and is recommended for following steps;
// keep going
} else {
ASSERT(0); // unknown action
}
if (m_show_maintenanceapp) {
ASSERT(m_pOverlay);
//
// overlay
//
hvState state;
hvGetState(0, state); COverlayEvent event;
event.m_ptr1_tracked = state.tracked;
event.m_ptr1_recognized = state.recognized;
event.m_ptr1_x = state.center_xpos;
event.m_ptr1_y = state.center_ypos;
event.m_ptr1_type = state.posture;
m_pOverlay->Tracked(event); m_pOverlay->Draw(m_pColorHeader);
}
#ifdef HAVE_USER_STUDY
if (m_pUserStudyA) {
hvVState state;
hvGetState(0, state); COverlayEvent event;
event.m_ptr1_tracked = state.tracked;
event.m_ptr1_recognized = state.recognized;
event.m_ptr1_x = state.center_xpos;
event.m_ptr1_y = state.center_ypos;
event.m_ptr1_type = state.posture;
m_pUserStudyA->Tracked(event);
m_pUserStudyA->Draw(m_pColorHeader);
}
if (m_pUserStudyB) {
hvState state;
hvGetState(0, state); COverlayEvent event;
event.m_ptr1_tracked = state.tracked;
event.m_ptr1_recognized = state.recognized;
event.m_ptr1_x = state.center_xpos;
event.m_ptr1_y = state.center_ypos;
event.m_ptr1_type = state.posture;
m_pUserStudyB->Tracked(event);
m_pUserStudyB->Draw(m_pColorHeader);
}
#endif
if (m_take_one_snapshot) {
m_take_one_snapshot = false;
SaveImageArea(m_pColorHeader);
}
#ifdef USE_FDL
if (m_FDL_only && action==HV_PROCESS_FRAME) {
if (!m_FDL_is_initialized) {
int iPixelSize = pvi->bmiHeader.biBitCount / 8;
FDL_Initialize(m_cxImage, m_cyImage, iPixelSize);
m_FDL_is_initialized = true;
}
FDL_PutImage((BYTE*) m_pColorHeader->imageData);
m_bSampleSkipped = true;
VERBOSE0(4, "HandVuFilter: frame sent to FDL, no display");
return S_FALSE;
}
#endif USE_FDL
if (m_img_bottom_up) {
cvMirror(m_pColorHeader, NULL, 0); // flip on horizontal axis
}
VERBOSE0(3, "HandVuFilter: processed frame");
return NOERROR;
} // Transform (in place)
RefTime CHandVuFilter::GetSampleTimeUsec() const
{
return m_t_sample;
}
RefTime CHandVuFilter::GetCurrentTimeUsec() const
{
if (m_tStart.m_time==0) {
return 0;
}
CRefTime t_curr;
((CHandVuFilter*)this)->StreamTime(t_curr);
return t_curr.m_time/10;
}
// Check the input type is OK - return an error otherwise
HRESULT CHandVuFilter::CheckInputType(const CMediaType *mtIn)
{
// check this is a VIDEOINFOHEADER type
if (*mtIn->FormatType() != FORMAT_VideoInfo) {
return E_INVALIDARG;
}
// Can we transform this type
if (CanPerformHandVuFilter(mtIn)) {
return NOERROR;
}
return E_FAIL;
}
//
// Checktransform
//
// Check a transform can be done between these formats
//
HRESULT CHandVuFilter::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
{
if (CanPerformHandVuFilter(mtIn)) {
if (*mtIn == *mtOut) {
return NOERROR;
}
}
return E_FAIL;
} // CheckTransform
//
// DecideBufferSize
//
// Tell the output pin's allocator what size buffers we
// require. Can only do this when the input is connected
//
HRESULT CHandVuFilter::DecideBufferSize(IMemAllocator *pAlloc,ALLOCATOR_PROPERTIES *pProperties)
{
// Is the input pin connected
if (m_pInput->IsConnected() == FALSE) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -