Commit bd0d8429 authored by Vadim Pisarevsky's avatar Vadim Pisarevsky

added support for Ximea cameras (patch by Marian Zajko), fixed GCC warnings in…

added support for Ximea cameras (patch by Marian Zajko), fixed GCC warnings in MOG2 background subtractor.
parent d58459cc
...@@ -428,6 +428,7 @@ set(WITH_EIGEN ON CACHE BOOL "Include Eigen2/Eigen3 support") ...@@ -428,6 +428,7 @@ set(WITH_EIGEN ON CACHE BOOL "Include Eigen2/Eigen3 support")
set(WITH_CUDA ON CACHE BOOL "Include NVidia Cuda Runtime support") set(WITH_CUDA ON CACHE BOOL "Include NVidia Cuda Runtime support")
set(WITH_OPENNI OFF CACHE BOOL "Include OpenNI support") set(WITH_OPENNI OFF CACHE BOOL "Include OpenNI support")
set(WITH_XIMEA OFF CACHE BOOL "Include XIMEA cameras support")
# =================================================== # ===================================================
# Macros that checks if module have been installed. # Macros that checks if module have been installed.
...@@ -1025,6 +1026,17 @@ if(WITH_OPENNI) ...@@ -1025,6 +1026,17 @@ if(WITH_OPENNI)
include(OpenCVFindOpenNI.cmake) include(OpenCVFindOpenNI.cmake)
endif() endif()
############################### XIMEA ################################
set(HAVE_XIMEA FALSE)
if(WITH_XIMEA)
include(OpenCVFindXimea.cmake)
endif()
if(XIMEA_FOUND)
set(HAVE_XIMEA TRUE)
endif()
############################## Eigen ############################## ############################## Eigen ##############################
if(WITH_EIGEN) if(WITH_EIGEN)
...@@ -1632,6 +1644,7 @@ status(" OpenEXR:" WITH_OPENEXR AND OPENEXR_FOUND THEN YES ...@@ -1632,6 +1644,7 @@ status(" OpenEXR:" WITH_OPENEXR AND OPENEXR_FOUND THEN YES
status(" OpenNI:" HAVE_OPENNI THEN YES ELSE NO) status(" OpenNI:" HAVE_OPENNI THEN YES ELSE NO)
status(" OpenNI PrimeSensor Modules:" status(" OpenNI PrimeSensor Modules:"
HAVE_OPENNI_PRIME_SENSOR_MODULE THEN YES ELSE NO) HAVE_OPENNI_PRIME_SENSOR_MODULE THEN YES ELSE NO)
status(" XIMEA:" HAVE_XIMEA THEN YES ELSE NO)
# video # video
status("") status("")
......
# - Find XIMEA
# This module finds if XIMEA Software package is installed
# and determines where the binaries and header files are.
# This code sets the following variables:
#
# XIMEA_FOUND - True if XIMEA API found
# XIMEA_PATH: - Path to the XIMEA API folder
# XIMEA_LIBRARY_DIRS - XIMEA libraries folder
#
# Created: 5 Aug 2011 by Marian Zajko (marian.zajko@ximea.com)
#
set(XIMEA_FOUND)
set(XIMEA_PATH)
set(XIMEA_LIBRARY_DIR)
# Try to find the XIMEA API path in registry.
GET_FILENAME_COMPONENT(XIMEA_PATH "[HKEY_CURRENT_USER\\Software\\XIMEA\\CamSupport\\API;Path]" ABSOLUTE)
if(XIMEA_PATH)
set(XIMEA_FOUND 1)
# set LIB folders
set(XIMEA_LIBRARY_DIR "${XIMEA_PATH}\\x86")
else()
set(XIMEA_FOUND 0)
endif()
mark_as_advanced(FORCE XIMEA_FOUND)
mark_as_advanced(FORCE XIMEA_PATH)
mark_as_advanced(FORCE XIMEA_LIBRARY_DIR)
\ No newline at end of file
...@@ -184,3 +184,5 @@ ...@@ -184,3 +184,5 @@
/* VideoInput library */ /* VideoInput library */
#cmakedefine HAVE_VIDEOINPUT #cmakedefine HAVE_VIDEOINPUT
/* XIMEA camera support */
#cmakedefine HAVE_XIMEA
...@@ -287,7 +287,9 @@ enum ...@@ -287,7 +287,9 @@ enum
CV_CAP_OPENNI =900, // OpenNI (for Kinect) CV_CAP_OPENNI =900, // OpenNI (for Kinect)
CV_CAP_ANDROID =1000 // Android CV_CAP_ANDROID =1000, // Android
CV_CAP_XIAPI =1100 // XIMEA Camera API
}; };
/* start capturing frames from camera: index = camera_index + domain_offset (CV_CAP_*) */ /* start capturing frames from camera: index = camera_index + domain_offset (CV_CAP_*) */
...@@ -372,7 +374,30 @@ enum ...@@ -372,7 +374,30 @@ enum
// Properties of cameras available through GStreamer interface // Properties of cameras available through GStreamer interface
CV_CAP_GSTREAMER_QUEUE_LENGTH = 200, // default is 1 CV_CAP_GSTREAMER_QUEUE_LENGTH = 200, // default is 1
CV_CAP_PROP_PVAPI_MULTICASTIP = 300 // ip for anable multicast master mode. 0 for disable multicast CV_CAP_PROP_PVAPI_MULTICASTIP = 300, // ip for anable multicast master mode. 0 for disable multicast
// Properties of cameras available through XIMEA SDK interface
CV_CAP_PROP_XI_DOWNSAMPLING = 400, // Change image resolution by binning or skipping.
CV_CAP_PROP_XI_DATA_FORMAT = 401, // Output data format.
CV_CAP_PROP_XI_OFFSET_X = 402, // Horizontal offset from the origin to the area of interest (in pixels).
CV_CAP_PROP_XI_OFFSET_Y = 403, // Vertical offset from the origin to the area of interest (in pixels).
CV_CAP_PROP_XI_TRG_SOURCE = 404, // Defines source of trigger.
CV_CAP_PROP_XI_TRG_SOFTWARE = 405, // Generates an internal trigger. PRM_TRG_SOURCE must be set to TRG_SOFTWARE.
CV_CAP_PROP_XI_GPI_SELECTOR = 406, // Selects general purpose input
CV_CAP_PROP_XI_GPI_MODE = 407, // Set general purpose input mode
CV_CAP_PROP_XI_GPI_LEVEL = 408, // Get general purpose level
CV_CAP_PROP_XI_GPO_SELECTOR = 409, // Selects general purpose output
CV_CAP_PROP_XI_GPO_MODE = 410, // Set general purpose output mode
CV_CAP_PROP_XI_LED_SELECTOR = 411, // Selects camera signalling LED
CV_CAP_PROP_XI_LED_MODE = 412, // Define camera signalling LED functionality
CV_CAP_PROP_XI_MANUAL_WB = 413, // Calculates White Balance(must be called during acquisition)
CV_CAP_PROP_XI_AUTO_WB = 414, // Automatic white balance
CV_CAP_PROP_XI_AEAG = 415, // Automatic exposure/gain
CV_CAP_PROP_XI_EXP_PRIORITY = 416, // Exposure priority (0.5 - exposure 50%, gain 50%).
CV_CAP_PROP_XI_AE_MAX_LIMIT = 417, // Maximum limit of exposure in AEAG procedure
CV_CAP_PROP_XI_AG_MAX_LIMIT = 418, // Maximum limit of gain in AEAG procedure
CV_CAP_PROP_XI_AEAG_LEVEL = 419, // Average intensity of output signal AEAG should achieve(in %)
CV_CAP_PROP_XI_TIMEOUT = 420 // Image capture timeout in milliseconds
}; };
enum enum
......
...@@ -132,6 +132,9 @@ CV_IMPL CvCapture * cvCreateCameraCapture (int index) ...@@ -132,6 +132,9 @@ CV_IMPL CvCapture * cvCreateCameraCapture (int index)
#endif #endif
#ifdef HAVE_ANDROID_NATIVE_CAMERA #ifdef HAVE_ANDROID_NATIVE_CAMERA
CV_CAP_ANDROID, CV_CAP_ANDROID,
#endif
#ifdef HAVE_XIMEA
CV_CAP_XIAPI,
#endif #endif
-1 -1
}; };
...@@ -238,36 +241,43 @@ CV_IMPL CvCapture * cvCreateCameraCapture (int index) ...@@ -238,36 +241,43 @@ CV_IMPL CvCapture * cvCreateCameraCapture (int index)
#ifdef HAVE_UNICAP #ifdef HAVE_UNICAP
case CV_CAP_UNICAP: case CV_CAP_UNICAP:
capture = cvCreateCameraCapture_Unicap (index); capture = cvCreateCameraCapture_Unicap (index);
if (capture) if (capture)
return capture; return capture;
break; break;
#endif #endif
#ifdef HAVE_PVAPI #ifdef HAVE_PVAPI
case CV_CAP_PVAPI: case CV_CAP_PVAPI:
capture = cvCreateCameraCapture_PvAPI (index); capture = cvCreateCameraCapture_PvAPI (index);
if (capture) if (capture)
return capture; return capture;
break; break;
#endif #endif
#ifdef HAVE_OPENNI #ifdef HAVE_OPENNI
case CV_CAP_OPENNI: case CV_CAP_OPENNI:
capture = cvCreateCameraCapture_OpenNI (index); capture = cvCreateCameraCapture_OpenNI (index);
if (capture) if (capture)
return capture; return capture;
break; break;
#endif #endif
#ifdef HAVE_ANDROID_NATIVE_CAMERA #ifdef HAVE_ANDROID_NATIVE_CAMERA
case CV_CAP_ANDROID: case CV_CAP_ANDROID:
capture = cvCreateCameraCapture_Android (index); capture = cvCreateCameraCapture_Android (index);
if (capture) if (capture)
return capture; return capture;
break;
#endif
#ifdef HAVE_XIMEA
case CV_CAP_XIAPI:
capture = cvCreateCameraCapture_Ximea (index);
if (capture)
return capture;
break; break;
#endif #endif
} }
} }
......
#include "precomp.hpp"
#include "xiApi.h"
#include "xiExt.h"
/**********************************************************************************/
class CvCaptureCAM_XIMEA : public CvCapture
{
public:
CvCaptureCAM_XIMEA() { init(); }
virtual ~CvCaptureCAM_XIMEA() { close(); }
virtual bool open( int index );
virtual void close();
virtual double getProperty(int);
virtual bool setProperty(int, double);
virtual bool grabFrame();
virtual IplImage* retrieveFrame(int);
virtual int getCaptureDomain() { return CV_CAP_XIAPI; } // Return the type of the capture object: CV_CAP_VFW, etc...
protected:
void init();
void errMsg(char* msg, int errNum);
IplImage* frame;
HANDLE hmv;
DWORD numDevices;
XI_IMG image;
int width;
int height;
int format;
int timeout;
};
/**********************************************************************************/
CvCapture* cvCreateCameraCapture_XIMEA( int index )
{
CvCaptureCAM_XIMEA* capture = new CvCaptureCAM_XIMEA;
if( capture->open( index ))
return capture;
delete capture;
return 0;
}
/**********************************************************************************/
// Enumerate connected devices
void CvCaptureCAM_XIMEA::init()
{
xiGetNumberDevices( &numDevices);
hmv = NULL;
}
/**********************************************************************************/
// Initialize camera input
bool CvCaptureCAM_XIMEA::open( int wIndex )
{
int mvret = XI_OK;
if(numDevices == 0)
return false;
if((mvret = xiOpenDevice( wIndex, &hmv)) != XI_OK)
{
errMsg("Open XI_DEVICE failed", mvret);
return false;
}
// always use auto exposure/gain
xiSetParamInt( hmv, XI_PRM_AEAG, 1);
// always use auto white ballance
xiSetParamInt( hmv, XI_PRM_AUTO_WB, 1);
xiGetParamInt( hmv, XI_PRM_WIDTH, &width);
xiGetParamInt( hmv, XI_PRM_HEIGHT, &height);
// default image format RGB24
xiSetParamInt( hmv, XI_PRM_IMAGE_DATA_FORMAT, XI_RGB24);
format = XI_RGB24;
// allocate frame buffer for RGB24 image
frame = cvCreateImage(cvSize( width, height), IPL_DEPTH_8U, 3);
//default capture timeout 10s
timeout = 10000;
return true;
}
/**********************************************************************************/
void CvCaptureCAM_XIMEA::close()
{
xiCloseDevice(hmv);
hmv = NULL;
}
/**********************************************************************************/
bool CvCaptureCAM_XIMEA::grabFrame()
{
int mvret = XI_OK;
image.size = sizeof(XI_IMG);
if((mvret = xiGetImage( hmv, timeout, &image)) != XI_OK)
{
errMsg("Error during GetImage", mvret);
return false;
}
return true;
}
/**********************************************************************************/
IplImage* CvCaptureCAM_XIMEA::retrieveFrame(int)
{
// update cvImage after format has changed
if( image.width != width || image.height != height || image.frm != format)
{
cvReleaseImage(&frame);
switch( image.frm)
{
case XI_MONO8 : frame = cvCreateImage(cvSize( image.width, image.height), IPL_DEPTH_8U, 1); break;
case XI_MONO16 : frame = cvCreateImage(cvSize( image.width, image.height), IPL_DEPTH_16U, 1); break;
case XI_RGB24 : frame = cvCreateImage(cvSize( image.width, image.height), IPL_DEPTH_8U, 3); break;
case XI_RGB32 : frame = cvCreateImage(cvSize( image.width, image.height), IPL_DEPTH_8U, 4); break;
}
// update global image format
format = image.frm;
width = image.width;
height = image.height;
}
// copy pixel data
switch( image.frm)
{
case XI_MONO8 : memcpy( frame->imageData, image.bp, image.width*image.height); break;
case XI_MONO16 : memcpy( frame->imageData, image.bp, image.width*image.height*sizeof(WORD)); break;
case XI_RGB24 : memcpy( frame->imageData, image.bp, image.width*image.height*3); break;
case XI_RGB32 : memcpy( frame->imageData, image.bp, image.width*image.height*sizeof(DWORD)); break;
}
return frame;
}
/**********************************************************************************/
double CvCaptureCAM_XIMEA::getProperty( int property_id )
{
if(hmv == NULL)
return 0;
int ival = 0;
float fval = 0;
switch( property_id )
{
// OCV parameters
case CV_CAP_PROP_POS_FRAMES : return (double) image.nframe;
case CV_CAP_PROP_FRAME_WIDTH : xiGetParamInt( hmv, XI_PRM_WIDTH, &ival); return ival;
case CV_CAP_PROP_FRAME_HEIGHT : xiGetParamInt( hmv, XI_PRM_HEIGHT, &ival); return ival;
case CV_CAP_PROP_FPS : xiGetParamFloat( hmv, XI_PRM_FRAMERATE, &fval); return fval;
case CV_CAP_PROP_GAIN : xiGetParamFloat( hmv, XI_PRM_GAIN, &fval); return fval;
case CV_CAP_PROP_EXPOSURE : xiGetParamInt( hmv, XI_PRM_EXPOSURE, &ival); return ival;
// XIMEA camera properties
case CV_CAP_PROP_XI_DOWNSAMPLING : xiGetParamInt( hmv, XI_PRM_DOWNSAMPLING, &ival); return ival;
case CV_CAP_PROP_XI_DATA_FORMAT : xiGetParamInt( hmv, XI_PRM_IMAGE_DATA_FORMAT, &ival); return ival;
case CV_CAP_PROP_XI_OFFSET_X : xiGetParamInt( hmv, XI_PRM_OFFSET_X, &ival); return ival;
case CV_CAP_PROP_XI_OFFSET_Y : xiGetParamInt( hmv, XI_PRM_OFFSET_Y, &ival); return ival;
case CV_CAP_PROP_XI_TRG_SOURCE : xiGetParamInt( hmv, XI_PRM_TRG_SOURCE, &ival); return ival;
case CV_CAP_PROP_XI_GPI_SELECTOR : xiGetParamInt( hmv, XI_PRM_GPI_SELECTOR, &ival); return ival;
case CV_CAP_PROP_XI_GPI_MODE : xiGetParamInt( hmv, XI_PRM_GPI_MODE, &ival); return ival;
case CV_CAP_PROP_XI_GPI_LEVEL : xiGetParamInt( hmv, XI_PRM_GPI_LEVEL, &ival); return ival;
case CV_CAP_PROP_XI_GPO_SELECTOR : xiGetParamInt( hmv, XI_PRM_GPO_SELECTOR, &ival); return ival;
case CV_CAP_PROP_XI_GPO_MODE : xiGetParamInt( hmv, XI_PRM_GPO_MODE, &ival); return ival;
case CV_CAP_PROP_XI_LED_SELECTOR : xiGetParamInt( hmv, XI_PRM_LED_SELECTOR, &ival); return ival;
case CV_CAP_PROP_XI_LED_MODE : xiGetParamInt( hmv, XI_PRM_LED_MODE, &ival); return ival;
case CV_CAP_PROP_XI_AUTO_WB : xiGetParamInt( hmv, XI_PRM_AUTO_WB, &ival); return ival;
case CV_CAP_PROP_XI_AEAG : xiGetParamInt( hmv, XI_PRM_AEAG, &ival); return ival;
case CV_CAP_PROP_XI_EXP_PRIORITY : xiGetParamFloat( hmv, XI_PRM_EXP_PRIORITY, &fval); return fval;
case CV_CAP_PROP_XI_AE_MAX_LIMIT : xiGetParamInt( hmv, XI_PRM_EXP_PRIORITY, &ival); return ival;
case CV_CAP_PROP_XI_AG_MAX_LIMIT : xiGetParamFloat( hmv, XI_PRM_AG_MAX_LIMIT, &fval); return fval;
case CV_CAP_PROP_XI_AEAG_LEVEL : xiGetParamInt( hmv, XI_PRM_AEAG_LEVEL, &ival); return ival;
case CV_CAP_PROP_XI_TIMEOUT : return timeout;
}
return 0;
}
/**********************************************************************************/
bool CvCaptureCAM_XIMEA::setProperty( int property_id, double value )
{
int ival = (int) value;
float fval = (float) value;
int mvret = XI_OK;
switch(property_id)
{
// OCV parameters
case CV_CAP_PROP_FRAME_WIDTH : mvret = xiSetParamInt( hmv, XI_PRM_WIDTH, ival); break;
case CV_CAP_PROP_FRAME_HEIGHT : mvret = xiSetParamInt( hmv, XI_PRM_HEIGHT, ival); break;
case CV_CAP_PROP_FPS : mvret = xiSetParamFloat( hmv, XI_PRM_FRAMERATE, fval); break;
case CV_CAP_PROP_GAIN : mvret = xiSetParamFloat( hmv, XI_PRM_GAIN, fval); break;
case CV_CAP_PROP_EXPOSURE : mvret = xiSetParamInt( hmv, XI_PRM_EXPOSURE, ival); break;
// XIMEA camera properties
case CV_CAP_PROP_XI_DOWNSAMPLING : mvret = xiSetParamInt( hmv, XI_PRM_DOWNSAMPLING, ival); break;
case CV_CAP_PROP_XI_DATA_FORMAT : mvret = xiSetParamInt( hmv, XI_PRM_IMAGE_DATA_FORMAT, ival); break;
case CV_CAP_PROP_XI_OFFSET_X : mvret = xiSetParamInt( hmv, XI_PRM_OFFSET_X, ival); break;
case CV_CAP_PROP_XI_OFFSET_Y : mvret = xiSetParamInt( hmv, XI_PRM_OFFSET_Y, ival); break;
case CV_CAP_PROP_XI_TRG_SOURCE : mvret = xiSetParamInt( hmv, XI_PRM_TRG_SOURCE, ival); break;
case CV_CAP_PROP_XI_GPI_SELECTOR : mvret = xiSetParamInt( hmv, XI_PRM_GPI_SELECTOR, ival); break;
case CV_CAP_PROP_XI_TRG_SOFTWARE : mvret = xiSetParamInt( hmv, XI_PRM_TRG_SOURCE, 1); break;
case CV_CAP_PROP_XI_GPI_MODE : mvret = xiSetParamInt( hmv, XI_PRM_GPI_MODE, ival); break;
case CV_CAP_PROP_XI_GPI_LEVEL : mvret = xiSetParamInt( hmv, XI_PRM_GPI_LEVEL, ival); break;
case CV_CAP_PROP_XI_GPO_SELECTOR : mvret = xiSetParamInt( hmv, XI_PRM_GPO_SELECTOR, ival); break;
case CV_CAP_PROP_XI_GPO_MODE : mvret = xiSetParamInt( hmv, XI_PRM_GPO_MODE, ival); break;
case CV_CAP_PROP_XI_LED_SELECTOR : mvret = xiSetParamInt( hmv, XI_PRM_LED_SELECTOR, ival); break;
case CV_CAP_PROP_XI_LED_MODE : mvret = xiSetParamInt( hmv, XI_PRM_LED_MODE, ival); break;
case CV_CAP_PROP_XI_AUTO_WB : mvret = xiSetParamInt( hmv, XI_PRM_AUTO_WB, ival); break;
case CV_CAP_PROP_XI_MANUAL_WB : mvret = xiSetParamInt( hmv, XI_PRM_LED_MODE, ival); break;
case CV_CAP_PROP_XI_AEAG : mvret = xiSetParamInt( hmv, XI_PRM_AEAG, ival); break;
case CV_CAP_PROP_XI_EXP_PRIORITY : mvret = xiSetParamFloat( hmv, XI_PRM_EXP_PRIORITY, fval); break;
case CV_CAP_PROP_XI_AE_MAX_LIMIT : mvret = xiSetParamInt( hmv, XI_PRM_EXP_PRIORITY, ival); break;
case CV_CAP_PROP_XI_AG_MAX_LIMIT : mvret = xiSetParamFloat( hmv, XI_PRM_AG_MAX_LIMIT, fval); break;
case CV_CAP_PROP_XI_AEAG_LEVEL : mvret = xiSetParamInt( hmv, XI_PRM_AEAG_LEVEL, ival); break;
case CV_CAP_PROP_XI_TIMEOUT : timeout = ival; break;
}
if(mvret != XI_OK)
{
errMsg("Set parameter error", mvret);
return false;
}
else
return true;
}
/**********************************************************************************/
void CvCaptureCAM_XIMEA::errMsg(char* msg, int errNum)
{
char buf[512];
sprintf( buf, "%s : %d\n", msg, errNum);
OutputDebugString(buf);
}
/**********************************************************************************/
\ No newline at end of file
...@@ -133,6 +133,7 @@ CvVideoWriter* cvCreateVideoWriter_VFW( const char* filename, int fourcc, ...@@ -133,6 +133,7 @@ CvVideoWriter* cvCreateVideoWriter_VFW( const char* filename, int fourcc,
CvCapture* cvCreateCameraCapture_DShow( int index ); CvCapture* cvCreateCameraCapture_DShow( int index );
CvCapture* cvCreateCameraCapture_OpenNI( int index ); CvCapture* cvCreateCameraCapture_OpenNI( int index );
CvCapture* cvCreateCameraCapture_Android( int index ); CvCapture* cvCreateCameraCapture_Android( int index );
CvCapture* cvCreateCameraCapture_XIMEA( int index );
CVAPI(int) cvHaveImageReader(const char* filename); CVAPI(int) cvHaveImageReader(const char* filename);
CVAPI(int) cvHaveImageWriter(const char* filename); CVAPI(int) cvHaveImageWriter(const char* filename);
......
...@@ -204,69 +204,68 @@ typedef struct CvGaussBGModel2 ...@@ -204,69 +204,68 @@ typedef struct CvGaussBGModel2
CvGaussBGStatModel2Params params; CvGaussBGStatModel2Params params;
CvGaussBGStatModel2Data data; CvGaussBGStatModel2Data data;
int countFrames; int countFrames;
} } CvGaussBGModel2;
CvGaussBGModel2;
CVAPI(CvBGStatModel*) cvCreateGaussianBGModel2( IplImage* first_frame, CVAPI(CvBGStatModel*) cvCreateGaussianBGModel2( IplImage* first_frame,
CvGaussBGStatModel2Params* params CV_DEFAULT(NULL) ); CvGaussBGStatModel2Params* params CV_DEFAULT(NULL) );
//shadow detection performed per pixel //shadow detection performed per pixel
// should work for rgb data, could be usefull for gray scale and depth data as well // should work for rgb data, could be usefull for gray scale and depth data as well
// See: Prati,Mikic,Trivedi,Cucchiarra,"Detecting Moving Shadows...",IEEE PAMI,2003. // See: Prati,Mikic,Trivedi,Cucchiarra,"Detecting Moving Shadows...",IEEE PAMI,2003.
CV_INLINE int _icvRemoveShadowGMM(float* data, int nD, CV_INLINE int _icvRemoveShadowGMM(float* data, int nD,
unsigned char nModes, unsigned char nModes,
CvPBGMMGaussian* pGMM, CvPBGMMGaussian* pGMM,
float m_fTb, float m_fTb,
float m_fTB, float m_fTB,
float m_fTau) float m_fTau)
{ {
float tWeight = 0; float tWeight = 0;
float numerator, denominator; float numerator, denominator;
// check all the components marked as background: // check all the components marked as background:
for (int iModes=0;iModes<nModes;iModes++) for (int iModes=0;iModes<nModes;iModes++)
{ {
CvPBGMMGaussian g=pGMM[iModes]; CvPBGMMGaussian g=pGMM[iModes];
numerator = 0.0f; numerator = 0.0f;
denominator = 0.0f; denominator = 0.0f;
for (int iD=0;iD<nD;iD++) for (int iD=0;iD<nD;iD++)
{ {
numerator += data[iD] * g.mean[iD]; numerator += data[iD] * g.mean[iD];
denominator += g.mean[iD]* g.mean[iD]; denominator += g.mean[iD]* g.mean[iD];
} }
// no division by zero allowed // no division by zero allowed
if (denominator == 0) if (denominator == 0)
{ {
return 0; return 0;
}; };
float a = numerator / denominator; float a = numerator / denominator;
// if tau < a < 1 then also check the color distortion // if tau < a < 1 then also check the color distortion
if ((a <= 1) && (a >= m_fTau)) if ((a <= 1) && (a >= m_fTau))
{ {
float dist2a=0.0f; float dist2a=0.0f;
for (int iD=0;iD<nD;iD++) for (int iD=0;iD<nD;iD++)
{ {
float dD= a*g.mean[iD] - data[iD]; float dD= a*g.mean[iD] - data[iD];
dist2a += (dD*dD); dist2a += (dD*dD);
} }
if (dist2a<m_fTb*g.variance*a*a) if (dist2a<m_fTb*g.variance*a*a)
{ {
return 2; return 2;
} }
}; };
tWeight += g.weight; tWeight += g.weight;
if (tWeight > m_fTB) if (tWeight > m_fTB)
{ {
return 0; return 0;
}; };
}; };
return 0; return 0;
} }
//update GMM - the base update function performed per pixel //update GMM - the base update function performed per pixel
...@@ -284,402 +283,402 @@ CV_INLINE int _icvRemoveShadowGMM(float* data, int nD, ...@@ -284,402 +283,402 @@ CV_INLINE int _icvRemoveShadowGMM(float* data, int nD,
//http://www.zoranz.net/Publications/zivkovic2004PAMI.pdf //http://www.zoranz.net/Publications/zivkovic2004PAMI.pdf
CV_INLINE int _icvUpdateGMM(float* data, int nD, CV_INLINE int _icvUpdateGMM(float* data, int nD,
unsigned char* pModesUsed, unsigned char* pModesUsed,
CvPBGMMGaussian* pGMM, CvPBGMMGaussian* pGMM,
int m_nM, int m_nM,
float m_fAlphaT, float m_fAlphaT,
float m_fTb, float m_fTb,
float m_fTB, float m_fTB,
float m_fTg, float m_fTg,
float m_fVarInit, float m_fVarInit,
float m_fVarMax, float m_fVarMax,
float m_fVarMin, float m_fVarMin,
float m_fPrune) float m_fPrune)
{ {
//calculate distances to the modes (+ sort) //calculate distances to the modes (+ sort)
//here we need to go in descending order!!! //here we need to go in descending order!!!
bool bBackground=0;//return value -> true - the pixel classified as background bool bBackground=0;//return value -> true - the pixel classified as background
//internal: //internal:
bool bFitsPDF=0;//if it remains zero a new GMM mode will be added bool bFitsPDF=0;//if it remains zero a new GMM mode will be added
float m_fOneMinAlpha=1-m_fAlphaT; float m_fOneMinAlpha=1-m_fAlphaT;
unsigned char nModes=*pModesUsed;//current number of modes in GMM unsigned char nModes=*pModesUsed;//current number of modes in GMM
float totalWeight=0.0f; float totalWeight=0.0f;
////// //////
//go through all modes //go through all modes
int iMode=0; int iMode=0;
CvPBGMMGaussian* pGauss=pGMM; CvPBGMMGaussian* pGauss=pGMM;
for (;iMode<nModes;iMode++,pGauss++) for (;iMode<nModes;iMode++,pGauss++)
{ {
float weight = pGauss->weight;//need only weight if fit is found float weight = pGauss->weight;//need only weight if fit is found
weight=m_fOneMinAlpha*weight+m_fPrune; weight=m_fOneMinAlpha*weight+m_fPrune;
//// ////
//fit not found yet //fit not found yet
if (!bFitsPDF) if (!bFitsPDF)
{ {
//check if it belongs to some of the remaining modes //check if it belongs to some of the remaining modes
float var=pGauss->variance; float var=pGauss->variance;
//calculate difference and distance //calculate difference and distance
float dist2=0.0f; float dist2=0.0f;
#if (CV_BGFG_MOG2_NDMAX==1) #if (CV_BGFG_MOG2_NDMAX==1)
float dData=pGauss->mean[0]-data[0]; float dData=pGauss->mean[0]-data[0];
dist2=dData*dData; dist2=dData*dData;
#else #else
float dData[CV_BGFG_MOG2_NDMAX]; float dData[CV_BGFG_MOG2_NDMAX];
for (int iD=0;iD<nD;iD++) for (int iD=0;iD<nD;iD++)
{ {
dData[iD]=pGauss->mean[iD]-data[iD]; dData[iD]=pGauss->mean[iD]-data[iD];
dist2+=dData[iD]*dData[iD]; dist2+=dData[iD]*dData[iD];
} }
#endif #endif
//background? - m_fTb - usually larger than m_fTg //background? - m_fTb - usually larger than m_fTg
if ((totalWeight<m_fTB)&&(dist2<m_fTb*var)) if ((totalWeight<m_fTB)&&(dist2<m_fTb*var))
bBackground=1; bBackground=1;
//check fit //check fit
if (dist2<m_fTg*var) if (dist2<m_fTg*var)
{ {
///// /////
//belongs to the mode - bFitsPDF becomes 1 //belongs to the mode - bFitsPDF becomes 1
bFitsPDF=1; bFitsPDF=1;
//update distribution //update distribution
//update weight //update weight
weight+=m_fAlphaT; weight+=m_fAlphaT;
float k = m_fAlphaT/weight; float k = m_fAlphaT/weight;
//update mean //update mean
#if (CV_BGFG_MOG2_NDMAX==1) #if (CV_BGFG_MOG2_NDMAX==1)
pGauss->mean[0]-=k*dData; pGauss->mean[0]-=k*dData;
#else #else
for (int iD=0;iD<nD;iD++) for (int iD=0;iD<nD;iD++)
{ {
pGauss->mean[iD]-=k*dData[iD]; pGauss->mean[iD]-=k*dData[iD];
} }
#endif #endif
//update variance //update variance
float varnew = var + k*(dist2-var); float varnew = var + k*(dist2-var);
//limit the variance //limit the variance
pGauss->variance = MIN(m_fVarMax,MAX(varnew,m_fVarMin)); pGauss->variance = MIN(m_fVarMax,MAX(varnew,m_fVarMin));
//sort //sort
//all other weights are at the same place and //all other weights are at the same place and
//only the matched (iModes) is higher -> just find the new place for it //only the matched (iModes) is higher -> just find the new place for it
for (int iLocal = iMode;iLocal>0;iLocal--) for (int iLocal = iMode;iLocal>0;iLocal--)
{ {
//check one up //check one up
if (weight < (pGMM[iLocal-1].weight)) if (weight < (pGMM[iLocal-1].weight))
{ {
break; break;
} }
else else
{ {
//swap one up //swap one up
CvPBGMMGaussian temp = pGMM[iLocal]; CvPBGMMGaussian temp = pGMM[iLocal];
pGMM[iLocal] = pGMM[iLocal-1]; pGMM[iLocal] = pGMM[iLocal-1];
pGMM[iLocal-1] = temp; pGMM[iLocal-1] = temp;
pGauss--; pGauss--;
} }
} }
//belongs to the mode - bFitsPDF becomes 1 //belongs to the mode - bFitsPDF becomes 1
///// /////
} }
}//!bFitsPDF) }//!bFitsPDF)
//check prune //check prune
if (weight<-m_fPrune) if (weight<-m_fPrune)
{ {
weight=0.0; weight=0.0;
nModes--; nModes--;
} }
pGauss->weight=weight;//update weight by the calculated value pGauss->weight=weight;//update weight by the calculated value
totalWeight+=weight; totalWeight+=weight;
} }
//go through all modes //go through all modes
////// //////
//renormalize weights //renormalize weights
for (iMode = 0; iMode < nModes; iMode++) for (iMode = 0; iMode < nModes; iMode++)
{ {
pGMM[iMode].weight = pGMM[iMode].weight/totalWeight; pGMM[iMode].weight = pGMM[iMode].weight/totalWeight;
} }
//make new mode if needed and exit //make new mode if needed and exit
if (!bFitsPDF) if (!bFitsPDF)
{ {
if (nModes==m_nM) if (nModes==m_nM)
{ {
//replace the weakest //replace the weakest
pGauss=pGMM+m_nM-1; pGauss=pGMM+m_nM-1;
} }
else else
{ {
//add a new one //add a new one
pGauss=pGMM+nModes; pGauss=pGMM+nModes;
nModes++; nModes++;
} }
if (nModes==1) if (nModes==1)
{ {
pGauss->weight=1; pGauss->weight=1;
} }
else else
{ {
pGauss->weight=m_fAlphaT; pGauss->weight=m_fAlphaT;
//renormalize all weights //renormalize all weights
for (iMode = 0; iMode < nModes-1; iMode++) for (iMode = 0; iMode < nModes-1; iMode++)
{ {
pGMM[iMode].weight *=m_fOneMinAlpha; pGMM[iMode].weight *=m_fOneMinAlpha;
} }
} }
//init //init
memcpy(pGauss->mean,data,nD*sizeof(float)); memcpy(pGauss->mean,data,nD*sizeof(float));
pGauss->variance=m_fVarInit; pGauss->variance=m_fVarInit;
//sort //sort
//find the new place for it //find the new place for it
for (int iLocal = nModes-1;iLocal>0;iLocal--) for (int iLocal = nModes-1;iLocal>0;iLocal--)
{ {
//check one up //check one up
if (m_fAlphaT < (pGMM[iLocal-1].weight)) if (m_fAlphaT < (pGMM[iLocal-1].weight))
{ {
break; break;
} }
else else
{ {
//swap one up //swap one up
CvPBGMMGaussian temp = pGMM[iLocal]; CvPBGMMGaussian temp = pGMM[iLocal];
pGMM[iLocal] = pGMM[iLocal-1]; pGMM[iLocal] = pGMM[iLocal-1];
pGMM[iLocal-1] = temp; pGMM[iLocal-1] = temp;
} }
} }
} }
//set the number of modes //set the number of modes
*pModesUsed=nModes; *pModesUsed=nModes;
return bBackground; return bBackground;
} }
// a bit more efficient implementation for common case of 3 channel (rgb) images // a bit more efficient implementation for common case of 3 channel (rgb) images
CV_INLINE int _icvUpdateGMM_C3(float r,float g, float b, CV_INLINE int _icvUpdateGMM_C3(float r,float g, float b,
unsigned char* pModesUsed, unsigned char* pModesUsed,
CvPBGMMGaussian* pGMM, CvPBGMMGaussian* pGMM,
int m_nM, int m_nM,
float m_fAlphaT, float m_fAlphaT,
float m_fTb, float m_fTb,
float m_fTB, float m_fTB,
float m_fTg, float m_fTg,
float m_fVarInit, float m_fVarInit,
float m_fVarMax, float m_fVarMax,
float m_fVarMin, float m_fVarMin,
float m_fPrune) float m_fPrune)
{ {
//calculate distances to the modes (+ sort) //calculate distances to the modes (+ sort)
//here we need to go in descending order!!! //here we need to go in descending order!!!
bool bBackground=0;//return value -> true - the pixel classified as background bool bBackground=0;//return value -> true - the pixel classified as background
//internal: //internal:
bool bFitsPDF=0;//if it remains zero a new GMM mode will be added bool bFitsPDF=0;//if it remains zero a new GMM mode will be added
float m_fOneMinAlpha=1-m_fAlphaT; float m_fOneMinAlpha=1-m_fAlphaT;
unsigned char nModes=*pModesUsed;//current number of modes in GMM unsigned char nModes=*pModesUsed;//current number of modes in GMM
float totalWeight=0.0f; float totalWeight=0.0f;
////// //////
//go through all modes //go through all modes
int iMode=0; int iMode=0;
CvPBGMMGaussian* pGauss=pGMM; CvPBGMMGaussian* pGauss=pGMM;
for (;iMode<nModes;iMode++,pGauss++) for (;iMode<nModes;iMode++,pGauss++)
{ {
float weight = pGauss->weight;//need only weight if fit is found float weight = pGauss->weight;//need only weight if fit is found
weight=m_fOneMinAlpha*weight+m_fPrune; weight=m_fOneMinAlpha*weight+m_fPrune;
//// ////
//fit not found yet //fit not found yet
if (!bFitsPDF) if (!bFitsPDF)
{ {
//check if it belongs to some of the remaining modes //check if it belongs to some of the remaining modes
float var=pGauss->variance; float var=pGauss->variance;
//calculate difference and distance //calculate difference and distance
float muR = pGauss->mean[0]; float muR = pGauss->mean[0];
float muG = pGauss->mean[1]; float muG = pGauss->mean[1];
float muB = pGauss->mean[2]; float muB = pGauss->mean[2];
float dR=muR - r; float dR=muR - r;
float dG=muG - g; float dG=muG - g;
float dB=muB - b; float dB=muB - b;
float dist2=(dR*dR+dG*dG+dB*dB); float dist2=(dR*dR+dG*dG+dB*dB);
//background? - m_fTb - usually larger than m_fTg //background? - m_fTb - usually larger than m_fTg
if ((totalWeight<m_fTB)&&(dist2<m_fTb*var)) if ((totalWeight<m_fTB)&&(dist2<m_fTb*var))
bBackground=1; bBackground=1;
//check fit //check fit
if (dist2<m_fTg*var) if (dist2<m_fTg*var)
{ {
///// /////
//belongs to the mode - bFitsPDF becomes 1 //belongs to the mode - bFitsPDF becomes 1
bFitsPDF=1; bFitsPDF=1;
//update distribution //update distribution
//update weight //update weight
weight+=m_fAlphaT; weight+=m_fAlphaT;
float k = m_fAlphaT/weight; float k = m_fAlphaT/weight;
//update mean //update mean
pGauss->mean[0] = muR - k*(dR); pGauss->mean[0] = muR - k*(dR);
pGauss->mean[1] = muG - k*(dG); pGauss->mean[1] = muG - k*(dG);
pGauss->mean[2] = muB - k*(dB); pGauss->mean[2] = muB - k*(dB);
//update variance //update variance
float varnew = var + k*(dist2-var); float varnew = var + k*(dist2-var);
//limit the variance //limit the variance
pGauss->variance = MIN(m_fVarMax,MAX(varnew,m_fVarMin)); pGauss->variance = MIN(m_fVarMax,MAX(varnew,m_fVarMin));
//sort //sort
//all other weights are at the same place and //all other weights are at the same place and
//only the matched (iModes) is higher -> just find the new place for it //only the matched (iModes) is higher -> just find the new place for it
for (int iLocal = iMode;iLocal>0;iLocal--) for (int iLocal = iMode;iLocal>0;iLocal--)
{ {
//check one up //check one up
if (weight < (pGMM[iLocal-1].weight)) if (weight < (pGMM[iLocal-1].weight))
{ {
break; break;
} }
else else
{ {
//swap one up //swap one up
CvPBGMMGaussian temp = pGMM[iLocal]; CvPBGMMGaussian temp = pGMM[iLocal];
pGMM[iLocal] = pGMM[iLocal-1]; pGMM[iLocal] = pGMM[iLocal-1];
pGMM[iLocal-1] = temp; pGMM[iLocal-1] = temp;
pGauss--; pGauss--;
} }
} }
//belongs to the mode - bFitsPDF becomes 1 //belongs to the mode - bFitsPDF becomes 1
///// /////
} }
}//!bFitsPDF) }//!bFitsPDF)
//check prunning //check prunning
if (weight<-m_fPrune) if (weight<-m_fPrune)
{ {
weight=0.0; weight=0.0;
nModes--; nModes--;
} }
pGauss->weight=weight; pGauss->weight=weight;
totalWeight+=weight; totalWeight+=weight;
} }
//go through all modes //go through all modes
////// //////
//renormalize weights //renormalize weights
for (iMode = 0; iMode < nModes; iMode++) for (iMode = 0; iMode < nModes; iMode++)
{ {
pGMM[iMode].weight = pGMM[iMode].weight/totalWeight; pGMM[iMode].weight = pGMM[iMode].weight/totalWeight;
} }
//make new mode if needed and exit //make new mode if needed and exit
if (!bFitsPDF) if (!bFitsPDF)
{ {
if (nModes==m_nM) if (nModes==m_nM)
{ {
//replace the weakest //replace the weakest
pGauss=pGMM+m_nM-1; pGauss=pGMM+m_nM-1;
} }
else else
{ {
//add a new one //add a new one
pGauss=pGMM+nModes; pGauss=pGMM+nModes;
nModes++; nModes++;
} }
if (nModes==1) if (nModes==1)
{ {
pGauss->weight=1; pGauss->weight=1;
} }
else else
{ {
pGauss->weight=m_fAlphaT; pGauss->weight=m_fAlphaT;
//renormalize all weights //renormalize all weights
for (iMode = 0; iMode < nModes-1; iMode++) for (iMode = 0; iMode < nModes-1; iMode++)
{ {
pGMM[iMode].weight *=m_fOneMinAlpha; pGMM[iMode].weight *=m_fOneMinAlpha;
} }
} }
//init //init
pGauss->mean[0]=r; pGauss->mean[0]=r;
pGauss->mean[1]=g; pGauss->mean[1]=g;
pGauss->mean[2]=b; pGauss->mean[2]=b;
pGauss->variance=m_fVarInit; pGauss->variance=m_fVarInit;
//sort //sort
//find the new place for it //find the new place for it
for (int iLocal = nModes-1;iLocal>0;iLocal--) for (int iLocal = nModes-1;iLocal>0;iLocal--)
{ {
//check one up //check one up
if (m_fAlphaT < (pGMM[iLocal-1].weight)) if (m_fAlphaT < (pGMM[iLocal-1].weight))
{ {
break; break;
} }
else else
{ {
//swap one up //swap one up
CvPBGMMGaussian temp = pGMM[iLocal]; CvPBGMMGaussian temp = pGMM[iLocal];
pGMM[iLocal] = pGMM[iLocal-1]; pGMM[iLocal] = pGMM[iLocal-1];
pGMM[iLocal-1] = temp; pGMM[iLocal-1] = temp;
} }
} }
} }
//set the number of modes //set the number of modes
*pModesUsed=nModes; *pModesUsed=nModes;
return bBackground; return bBackground;
} }
//the main function to update the background model //the main function to update the background model
void icvUpdatePixelBackgroundGMM2( const CvArr* srcarr, CvArr* dstarr , void icvUpdatePixelBackgroundGMM2( const CvArr* srcarr, CvArr* dstarr ,
CvPBGMMGaussian *pGMM, CvPBGMMGaussian *pGMM,
unsigned char *pUsedModes, unsigned char *pUsedModes,
//CvGaussBGStatModel2Params* pGMMPar, //CvGaussBGStatModel2Params* pGMMPar,
int nM, int nM,
float fTb, float fTb,
float fTB, float fTB,
float fTg, float fTg,
float fVarInit, float fVarInit,
float fVarMax, float fVarMax,
float fVarMin, float fVarMin,
float fCT, float fCT,
float fTau, float fTau,
bool bShadowDetection, bool bShadowDetection,
unsigned char nShadowDetection, unsigned char nShadowDetection,
float alpha) float alpha)
{ {
CvMat sstub, *src = cvGetMat(srcarr, &sstub); CvMat sstub, *src = cvGetMat(srcarr, &sstub);
CvMat dstub, *dst = cvGetMat(dstarr, &dstub); CvMat dstub, *dst = cvGetMat(dstarr, &dstub);
CvSize size = cvGetMatSize(src); CvSize size = cvGetMatSize(src);
int nD=CV_MAT_CN(src->type); int nD=CV_MAT_CN(src->type);
//reshape if possible //reshape if possible
if( CV_IS_MAT_CONT(src->type & dst->type) ) if( CV_IS_MAT_CONT(src->type & dst->type) )
{ {
size.width *= size.height; size.width *= size.height;
...@@ -687,258 +686,258 @@ void icvUpdatePixelBackgroundGMM2( const CvArr* srcarr, CvArr* dstarr , ...@@ -687,258 +686,258 @@ void icvUpdatePixelBackgroundGMM2( const CvArr* srcarr, CvArr* dstarr ,
} }
int x, y; int x, y;
float data[CV_BGFG_MOG2_NDMAX]; float data[CV_BGFG_MOG2_NDMAX];
float prune=-alpha*fCT; float prune=-alpha*fCT;
//general nD //general nD
if (nD!=3) if (nD!=3)
{ {
switch (CV_MAT_DEPTH(src->type)) switch (CV_MAT_DEPTH(src->type))
{ {
case CV_8U: case CV_8U:
for( y = 0; y < size.height; y++ ) for( y = 0; y < size.height; y++ )
{ {
uchar* sptr = src->data.ptr + src->step*y; uchar* sptr = src->data.ptr + src->step*y;
uchar* pDataOutput = dst->data.ptr + dst->step*y; uchar* pDataOutput = dst->data.ptr + dst->step*y;
for( x = 0; x < size.width; x++, for( x = 0; x < size.width; x++,
pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
{ {
//convert data //convert data
for (int iD=0;iD<nD;iD++) data[iD]=float(sptr[iD]); for (int iD=0;iD<nD;iD++) data[iD]=float(sptr[iD]);
//update GMM model //update GMM model
int result = _icvUpdateGMM(data,nD,pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune); int result = _icvUpdateGMM(data,nD,pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
//detect shadows in the foreground //detect shadows in the foreground
if (bShadowDetection) if (bShadowDetection)
if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau); if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
//generate output //generate output
(* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255;
} }
} }
break; break;
case CV_16S: case CV_16S:
for( y = 0; y < size.height; y++ ) for( y = 0; y < size.height; y++ )
{ {
short* sptr = src->data.s + src->step*y; short* sptr = src->data.s + src->step*y;
uchar* pDataOutput = dst->data.ptr + dst->step*y; uchar* pDataOutput = dst->data.ptr + dst->step*y;
for( x = 0; x < size.width; x++, for( x = 0; x < size.width; x++,
pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
{ {
//convert data //convert data
for (int iD=0;iD<nD;iD++) data[iD]=float(sptr[iD]); for (int iD=0;iD<nD;iD++) data[iD]=float(sptr[iD]);
//update GMM model //update GMM model
int result = _icvUpdateGMM(data,nD,pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune); int result = _icvUpdateGMM(data,nD,pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
//detect shadows in the foreground //detect shadows in the foreground
if (bShadowDetection) if (bShadowDetection)
if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau); if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
//generate output //generate output
(* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255;
} }
} }
break; break;
case CV_16U: case CV_16U:
for( y = 0; y < size.height; y++ ) for( y = 0; y < size.height; y++ )
{ {
unsigned short* sptr = (unsigned short*) (src->data.s + src->step*y); unsigned short* sptr = (unsigned short*) (src->data.s + src->step*y);
uchar* pDataOutput = dst->data.ptr + dst->step*y; uchar* pDataOutput = dst->data.ptr + dst->step*y;
for( x = 0; x < size.width; x++, for( x = 0; x < size.width; x++,
pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
{ {
//convert data //convert data
for (int iD=0;iD<nD;iD++) data[iD]=float(sptr[iD]); for (int iD=0;iD<nD;iD++) data[iD]=float(sptr[iD]);
//update GMM model //update GMM model
int result = _icvUpdateGMM(data,nD,pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune); int result = _icvUpdateGMM(data,nD,pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
//detect shadows in the foreground //detect shadows in the foreground
if (bShadowDetection) if (bShadowDetection)
if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau); if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
//generate output //generate output
(* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255;
} }
} }
break; break;
case CV_32S: case CV_32S:
for( y = 0; y < size.height; y++ ) for( y = 0; y < size.height; y++ )
{ {
int* sptr = src->data.i + src->step*y; int* sptr = src->data.i + src->step*y;
uchar* pDataOutput = dst->data.ptr + dst->step*y; uchar* pDataOutput = dst->data.ptr + dst->step*y;
for( x = 0; x < size.width; x++, for( x = 0; x < size.width; x++,
pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
{ {
//convert data //convert data
for (int iD=0;iD<nD;iD++) data[iD]=float(sptr[iD]); for (int iD=0;iD<nD;iD++) data[iD]=float(sptr[iD]);
//update GMM model //update GMM model
int result = _icvUpdateGMM(data,nD,pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune); int result = _icvUpdateGMM(data,nD,pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
//detect shadows in the foreground //detect shadows in the foreground
if (bShadowDetection) if (bShadowDetection)
if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau); if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
//generate output //generate output
(* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255;
} }
} }
break; break;
case CV_32F: case CV_32F:
for( y = 0; y < size.height; y++ ) for( y = 0; y < size.height; y++ )
{ {
float* sptr = src->data.fl + src->step*y; float* sptr = src->data.fl + src->step*y;
uchar* pDataOutput = dst->data.ptr + dst->step*y; uchar* pDataOutput = dst->data.ptr + dst->step*y;
for( x = 0; x < size.width; x++, for( x = 0; x < size.width; x++,
pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
{ {
//update GMM model //update GMM model
int result = _icvUpdateGMM(sptr,nD,pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune); int result = _icvUpdateGMM(sptr,nD,pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
//detect shadows in the foreground //detect shadows in the foreground
if (bShadowDetection) if (bShadowDetection)
if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau); if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
//generate output //generate output
(* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255;
} }
} }
break; break;
case CV_64F: case CV_64F:
for( y = 0; y < size.height; y++ ) for( y = 0; y < size.height; y++ )
{ {
double* sptr = src->data.db + src->step*y; double* sptr = src->data.db + src->step*y;
uchar* pDataOutput = dst->data.ptr + dst->step*y; uchar* pDataOutput = dst->data.ptr + dst->step*y;
for( x = 0; x < size.width; x++, for( x = 0; x < size.width; x++,
pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
{ {
//convert data //convert data
for (int iD=0;iD<nD;iD++) data[iD]=float(sptr[iD]); for (int iD=0;iD<nD;iD++) data[iD]=float(sptr[iD]);
//update GMM model //update GMM model
int result = _icvUpdateGMM(data,nD,pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune); int result = _icvUpdateGMM(data,nD,pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
//detect shadows in the foreground //detect shadows in the foreground
if (bShadowDetection) if (bShadowDetection)
if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau); if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
//generate output //generate output
(* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255;
} }
} }
break; break;
} }
}else ///if (nD==3) - a bit faster }else ///if (nD==3) - a bit faster
{ {
switch (CV_MAT_DEPTH(src->type)) switch (CV_MAT_DEPTH(src->type))
{ {
case CV_8U: case CV_8U:
for( y = 0; y < size.height; y++ ) for( y = 0; y < size.height; y++ )
{ {
uchar* sptr = src->data.ptr + src->step*y; uchar* sptr = src->data.ptr + src->step*y;
uchar* pDataOutput = dst->data.ptr + dst->step*y; uchar* pDataOutput = dst->data.ptr + dst->step*y;
for( x = 0; x < size.width; x++, for( x = 0; x < size.width; x++,
pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
{ {
//convert data //convert data
data[0]=float(sptr[0]),data[1]=float(sptr[1]),data[2]=float(sptr[2]); data[0]=float(sptr[0]),data[1]=float(sptr[1]),data[2]=float(sptr[2]);
//update GMM model //update GMM model
int result = _icvUpdateGMM_C3(data[0],data[1],data[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune); int result = _icvUpdateGMM_C3(data[0],data[1],data[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
//detect shadows in the foreground //detect shadows in the foreground
if (bShadowDetection) if (bShadowDetection)
if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau); if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
//generate output //generate output
(* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255;
} }
} }
break; break;
case CV_16S: case CV_16S:
for( y = 0; y < size.height; y++ ) for( y = 0; y < size.height; y++ )
{ {
short* sptr = src->data.s + src->step*y; short* sptr = src->data.s + src->step*y;
uchar* pDataOutput = dst->data.ptr + dst->step*y; uchar* pDataOutput = dst->data.ptr + dst->step*y;
for( x = 0; x < size.width; x++, for( x = 0; x < size.width; x++,
pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
{ {
//convert data //convert data
data[0]=float(sptr[0]),data[1]=float(sptr[1]),data[2]=float(sptr[2]); data[0]=float(sptr[0]),data[1]=float(sptr[1]),data[2]=float(sptr[2]);
//update GMM model //update GMM model
int result = _icvUpdateGMM_C3(data[0],data[1],data[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune); int result = _icvUpdateGMM_C3(data[0],data[1],data[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
//detect shadows in the foreground //detect shadows in the foreground
if (bShadowDetection) if (bShadowDetection)
if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau); if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
//generate output //generate output
(* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255;
} }
} }
break; break;
case CV_16U: case CV_16U:
for( y = 0; y < size.height; y++ ) for( y = 0; y < size.height; y++ )
{ {
unsigned short* sptr = (unsigned short*) src->data.s + src->step*y; unsigned short* sptr = (unsigned short*) src->data.s + src->step*y;
uchar* pDataOutput = dst->data.ptr + dst->step*y; uchar* pDataOutput = dst->data.ptr + dst->step*y;
for( x = 0; x < size.width; x++, for( x = 0; x < size.width; x++,
pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
{ {
//convert data //convert data
data[0]=float(sptr[0]),data[1]=float(sptr[1]),data[2]=float(sptr[2]); data[0]=float(sptr[0]),data[1]=float(sptr[1]),data[2]=float(sptr[2]);
//update GMM model //update GMM model
int result = _icvUpdateGMM_C3(data[0],data[1],data[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune); int result = _icvUpdateGMM_C3(data[0],data[1],data[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
//detect shadows in the foreground //detect shadows in the foreground
if (bShadowDetection) if (bShadowDetection)
if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau); if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
//generate output //generate output
(* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255;
} }
} }
break; break;
case CV_32S: case CV_32S:
for( y = 0; y < size.height; y++ ) for( y = 0; y < size.height; y++ )
{ {
int* sptr = src->data.i + src->step*y; int* sptr = src->data.i + src->step*y;
uchar* pDataOutput = dst->data.ptr + dst->step*y; uchar* pDataOutput = dst->data.ptr + dst->step*y;
for( x = 0; x < size.width; x++, for( x = 0; x < size.width; x++,
pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
{ {
//convert data //convert data
data[0]=float(sptr[0]),data[1]=float(sptr[1]),data[2]=float(sptr[2]); data[0]=float(sptr[0]),data[1]=float(sptr[1]),data[2]=float(sptr[2]);
//update GMM model //update GMM model
int result = _icvUpdateGMM_C3(data[0],data[1],data[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune); int result = _icvUpdateGMM_C3(data[0],data[1],data[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
//detect shadows in the foreground //detect shadows in the foreground
if (bShadowDetection) if (bShadowDetection)
if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau); if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
//generate output //generate output
(* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255;
} }
} }
break; break;
case CV_32F: case CV_32F:
for( y = 0; y < size.height; y++ ) for( y = 0; y < size.height; y++ )
{ {
float* sptr = src->data.fl + src->step*y; float* sptr = src->data.fl + src->step*y;
uchar* pDataOutput = dst->data.ptr + dst->step*y; uchar* pDataOutput = dst->data.ptr + dst->step*y;
for( x = 0; x < size.width; x++, for( x = 0; x < size.width; x++,
pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
{ {
//update GMM model //update GMM model
int result = _icvUpdateGMM_C3(sptr[0],sptr[1],sptr[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune); int result = _icvUpdateGMM_C3(sptr[0],sptr[1],sptr[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
//detect shadows in the foreground //detect shadows in the foreground
if (bShadowDetection) if (bShadowDetection)
if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau); if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
//generate output //generate output
(* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255;
} }
} }
break; break;
case CV_64F: case CV_64F:
for( y = 0; y < size.height; y++ ) for( y = 0; y < size.height; y++ )
{ {
double* sptr = src->data.db + src->step*y; double* sptr = src->data.db + src->step*y;
uchar* pDataOutput = dst->data.ptr + dst->step*y; uchar* pDataOutput = dst->data.ptr + dst->step*y;
for( x = 0; x < size.width; x++, for( x = 0; x < size.width; x++,
pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD) pGMM+=nM,pUsedModes++,pDataOutput++,sptr+=nD)
{ {
//convert data //convert data
data[0]=float(sptr[0]),data[1]=float(sptr[1]),data[2]=float(sptr[2]); data[0]=float(sptr[0]),data[1]=float(sptr[1]),data[2]=float(sptr[2]);
//update GMM model //update GMM model
int result = _icvUpdateGMM_C3(data[0],data[1],data[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune); int result = _icvUpdateGMM_C3(data[0],data[1],data[2],pUsedModes,pGMM,nM,alpha, fTb, fTB, fTg, fVarInit, fVarMax, fVarMin,prune);
//detect shadows in the foreground //detect shadows in the foreground
if (bShadowDetection) if (bShadowDetection)
if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau); if (result==0) result= _icvRemoveShadowGMM(data,nD,(*pUsedModes),pGMM,fTb,fTB,fTau);
//generate output //generate output
(* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255; (* pDataOutput)= (result==1) ? 0 : (result==2) ? (nShadowDetection) : 255;
} }
} }
break; break;
} }
}//a bit faster for nD=3; }//a bit faster for nD=3;
} }
...@@ -953,93 +952,95 @@ CV_IMPL CvBGStatModel* ...@@ -953,93 +952,95 @@ CV_IMPL CvBGStatModel*
cvCreateGaussianBGModel2( IplImage* first_frame, CvGaussBGStatModel2Params* parameters ) cvCreateGaussianBGModel2( IplImage* first_frame, CvGaussBGStatModel2Params* parameters )
{ {
CvGaussBGModel2* bg_model = 0; CvGaussBGModel2* bg_model = 0;
int w,h; int w,h;
CV_FUNCNAME( "cvCreateGaussianBGModel2" ); CV_FUNCNAME( "cvCreateGaussianBGModel2" );
__BEGIN__; __BEGIN__;
CvGaussBGStatModel2Params params; CvGaussBGStatModel2Params params;
if( !CV_IS_IMAGE(first_frame) ) if( !CV_IS_IMAGE(first_frame) )
CV_ERROR( CV_StsBadArg, "Invalid or NULL first_frame parameter" ); CV_ERROR( CV_StsBadArg, "Invalid or NULL first_frame parameter" );
if( first_frame->nChannels>CV_BGFG_MOG2_NDMAX ) if( first_frame->nChannels>CV_BGFG_MOG2_NDMAX )
CV_ERROR( CV_StsBadArg, "Maxumum number of channels in the image is excedded (change CV_BGFG_MOG2_MAXBANDS constant)!" ); CV_ERROR( CV_StsBadArg, "Maxumum number of channels in the image is excedded (change CV_BGFG_MOG2_MAXBANDS constant)!" );
CV_CALL( bg_model = (CvGaussBGModel2*)cvAlloc( sizeof(*bg_model) )); CV_CALL( bg_model = (CvGaussBGModel2*)cvAlloc( sizeof(*bg_model) ));
memset( bg_model, 0, sizeof(*bg_model) ); memset( bg_model, 0, sizeof(*bg_model) );
bg_model->type = CV_BG_MODEL_MOG2; bg_model->type = CV_BG_MODEL_MOG2;
bg_model->release = (CvReleaseBGStatModel) icvReleaseGaussianBGModel2; bg_model->release = (CvReleaseBGStatModel) icvReleaseGaussianBGModel2;
bg_model->update = (CvUpdateBGStatModel) icvUpdateGaussianBGModel2; bg_model->update = (CvUpdateBGStatModel) icvUpdateGaussianBGModel2;
//init parameters //init parameters
if( parameters == NULL ) if( parameters == NULL )
{ {
/* These constants are defined in cvaux/include/cvaux.h: */ memset(&params, 0, sizeof(params));
params.bShadowDetection = 1;
params.bPostFiltering=0; /* These constants are defined in cvaux/include/cvaux.h: */
params.minArea=CV_BGFG_MOG2_MINAREA; params.bShadowDetection = 1;
params.bPostFiltering=0;
//set parameters params.minArea=CV_BGFG_MOG2_MINAREA;
// K - max number of Gaussians per pixel
params.nM = CV_BGFG_MOG2_NGAUSSIANS;//4; //set parameters
// Tb - the threshold - n var // K - max number of Gaussians per pixel
//pGMM->fTb = 4*4; params.nM = CV_BGFG_MOG2_NGAUSSIANS;//4;
params.fTb = CV_BGFG_MOG2_STD_THRESHOLD*CV_BGFG_MOG2_STD_THRESHOLD; // Tb - the threshold - n var
// Tbf - the threshold //pGMM->fTb = 4*4;
//pGMM->fTB = 0.9f;//1-cf from the paper params.fTb = CV_BGFG_MOG2_STD_THRESHOLD*CV_BGFG_MOG2_STD_THRESHOLD;
params.fTB = CV_BGFG_MOG2_BACKGROUND_THRESHOLD; // Tbf - the threshold
// Tgenerate - the threshold //pGMM->fTB = 0.9f;//1-cf from the paper
params.fTg = CV_BGFG_MOG2_STD_THRESHOLD_GENERATE*CV_BGFG_MOG2_STD_THRESHOLD_GENERATE;//update the mode or generate new params.fTB = CV_BGFG_MOG2_BACKGROUND_THRESHOLD;
//pGMM->fSigma= 11.0f;//sigma for the new mode // Tgenerate - the threshold
params.fVarInit = CV_BGFG_MOG2_VAR_INIT; params.fTg = CV_BGFG_MOG2_STD_THRESHOLD_GENERATE*CV_BGFG_MOG2_STD_THRESHOLD_GENERATE;//update the mode or generate new
params.fVarMax = CV_BGFG_MOG2_VAR_MAX; //pGMM->fSigma= 11.0f;//sigma for the new mode
params.fVarMin = CV_BGFG_MOG2_VAR_MIN; params.fVarInit = CV_BGFG_MOG2_VAR_INIT;
// alpha - the learning factor params.fVarMax = CV_BGFG_MOG2_VAR_MAX;
params.fAlphaT = 1.0f/CV_BGFG_MOG2_WINDOW_SIZE;//0.003f; params.fVarMin = CV_BGFG_MOG2_VAR_MIN;
// complexity reduction prior constant // alpha - the learning factor
params.fCT = CV_BGFG_MOG2_CT;//0.05f; params.fAlphaT = 1.0f/CV_BGFG_MOG2_WINDOW_SIZE;//0.003f;
// complexity reduction prior constant
//shadow params.fCT = CV_BGFG_MOG2_CT;//0.05f;
// Shadow detection
params.nShadowDetection = (unsigned char)CV_BGFG_MOG2_SHADOW_VALUE;//value 0 to turn off //shadow
params.fTau = CV_BGFG_MOG2_SHADOW_TAU;//0.5f;// Tau - shadow threshold // Shadow detection
params.nShadowDetection = (unsigned char)CV_BGFG_MOG2_SHADOW_VALUE;//value 0 to turn off
params.fTau = CV_BGFG_MOG2_SHADOW_TAU;//0.5f;// Tau - shadow threshold
} }
else else
{ {
params = *parameters; params = *parameters;
} }
bg_model->params = params; bg_model->params = params;
//image data //image data
w = first_frame->width; w = first_frame->width;
h = first_frame->height; h = first_frame->height;
bg_model->params.nWidth = w; bg_model->params.nWidth = w;
bg_model->params.nHeight = h; bg_model->params.nHeight = h;
bg_model->params.nND = first_frame->nChannels; bg_model->params.nND = first_frame->nChannels;
//allocate GMM data //allocate GMM data
//GMM for each pixel //GMM for each pixel
bg_model->data.rGMM = (CvPBGMMGaussian*) malloc(w*h * params.nM * sizeof(CvPBGMMGaussian)); bg_model->data.rGMM = (CvPBGMMGaussian*) malloc(w*h * params.nM * sizeof(CvPBGMMGaussian));
//used modes per pixel //used modes per pixel
bg_model->data.rnUsedModes = (unsigned char* ) malloc(w*h); bg_model->data.rnUsedModes = (unsigned char* ) malloc(w*h);
memset(bg_model->data.rnUsedModes,0,w*h);//no modes used memset(bg_model->data.rnUsedModes,0,w*h);//no modes used
//prepare storages //prepare storages
CV_CALL( bg_model->background = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, first_frame->nChannels)); CV_CALL( bg_model->background = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, first_frame->nChannels));
CV_CALL( bg_model->foreground = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 1)); CV_CALL( bg_model->foreground = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 1));
//for eventual filtering //for eventual filtering
CV_CALL( bg_model->storage = cvCreateMemStorage()); CV_CALL( bg_model->storage = cvCreateMemStorage());
bg_model->countFrames = 0; bg_model->countFrames = 0;
__END__; __END__;
...@@ -1072,8 +1073,8 @@ icvReleaseGaussianBGModel2( CvGaussBGModel2** _bg_model ) ...@@ -1072,8 +1073,8 @@ icvReleaseGaussianBGModel2( CvGaussBGModel2** _bg_model )
{ {
CvGaussBGModel2* bg_model = *_bg_model; CvGaussBGModel2* bg_model = *_bg_model;
free (bg_model->data.rGMM); free (bg_model->data.rGMM);
free (bg_model->data.rnUsedModes); free (bg_model->data.rnUsedModes);
cvReleaseImage( &bg_model->background ); cvReleaseImage( &bg_model->background );
cvReleaseImage( &bg_model->foreground ); cvReleaseImage( &bg_model->foreground );
...@@ -1089,87 +1090,87 @@ icvReleaseGaussianBGModel2( CvGaussBGModel2** _bg_model ) ...@@ -1089,87 +1090,87 @@ icvReleaseGaussianBGModel2( CvGaussBGModel2** _bg_model )
static int CV_CDECL static int CV_CDECL
icvUpdateGaussianBGModel2( IplImage* curr_frame, CvGaussBGModel2* bg_model ) icvUpdateGaussianBGModel2( IplImage* curr_frame, CvGaussBGModel2* bg_model )
{ {
//checks //checks
if ((curr_frame->height!=bg_model->params.nHeight)||(curr_frame->width!=bg_model->params.nWidth)||(curr_frame->nChannels!=bg_model->params.nND)) if ((curr_frame->height!=bg_model->params.nHeight)||(curr_frame->width!=bg_model->params.nWidth)||(curr_frame->nChannels!=bg_model->params.nND))
CV_Error( CV_StsBadSize, "the image not the same size as the reserved GMM background model"); CV_Error( CV_StsBadSize, "the image not the same size as the reserved GMM background model");
float alpha=bg_model->params.fAlphaT; float alpha=bg_model->params.fAlphaT;
bg_model->countFrames++; bg_model->countFrames++;
//faster initial updates - increase value of alpha //faster initial updates - increase value of alpha
if (bg_model->params.bInit){ if (bg_model->params.bInit){
float alphaInit=(1.0f/(2*bg_model->countFrames+1)); float alphaInit=(1.0f/(2*bg_model->countFrames+1));
if (alphaInit>alpha) if (alphaInit>alpha)
{ {
alpha = alphaInit; alpha = alphaInit;
} }
else else
{ {
bg_model->params.bInit = 0; bg_model->params.bInit = 0;
} }
} }
//update background //update background
//icvUpdatePixelBackgroundGMM2( curr_frame, bg_model->foreground, bg_model->data.rGMM,bg_model->data.rnUsedModes,&(bg_model->params),alpha); //icvUpdatePixelBackgroundGMM2( curr_frame, bg_model->foreground, bg_model->data.rGMM,bg_model->data.rnUsedModes,&(bg_model->params),alpha);
icvUpdatePixelBackgroundGMM2( curr_frame, bg_model->foreground, bg_model->data.rGMM,bg_model->data.rnUsedModes, icvUpdatePixelBackgroundGMM2( curr_frame, bg_model->foreground, bg_model->data.rGMM,bg_model->data.rnUsedModes,
bg_model->params.nM, bg_model->params.nM,
bg_model->params.fTb, bg_model->params.fTb,
bg_model->params.fTB, bg_model->params.fTB,
bg_model->params.fTg, bg_model->params.fTg,
bg_model->params.fVarInit, bg_model->params.fVarInit,
bg_model->params.fVarMax, bg_model->params.fVarMax,
bg_model->params.fVarMin, bg_model->params.fVarMin,
bg_model->params.fCT, bg_model->params.fCT,
bg_model->params.fTau, bg_model->params.fTau,
bg_model->params.bShadowDetection, bg_model->params.bShadowDetection,
bg_model->params.nShadowDetection, bg_model->params.nShadowDetection,
alpha); alpha);
//foreground filtering //foreground filtering
if (bg_model->params.bPostFiltering==1) if (bg_model->params.bPostFiltering==1)
{ {
int region_count = 0; int region_count = 0;
CvSeq *first_seq = NULL, *prev_seq = NULL, *seq = NULL; CvSeq *first_seq = NULL, *prev_seq = NULL, *seq = NULL;
//filter small regions //filter small regions
cvClearMemStorage(bg_model->storage); cvClearMemStorage(bg_model->storage);
cvMorphologyEx( bg_model->foreground, bg_model->foreground, 0, 0, CV_MOP_OPEN, 1 ); cvMorphologyEx( bg_model->foreground, bg_model->foreground, 0, 0, CV_MOP_OPEN, 1 );
cvMorphologyEx( bg_model->foreground, bg_model->foreground, 0, 0, CV_MOP_CLOSE, 1 ); cvMorphologyEx( bg_model->foreground, bg_model->foreground, 0, 0, CV_MOP_CLOSE, 1 );
cvFindContours( bg_model->foreground, bg_model->storage, &first_seq, sizeof(CvContour), CV_RETR_LIST ); cvFindContours( bg_model->foreground, bg_model->storage, &first_seq, sizeof(CvContour), CV_RETR_LIST );
for( seq = first_seq; seq; seq = seq->h_next ) for( seq = first_seq; seq; seq = seq->h_next )
{ {
CvContour* cnt = (CvContour*)seq; CvContour* cnt = (CvContour*)seq;
if( cnt->rect.width * cnt->rect.height < bg_model->params.minArea ) if( cnt->rect.width * cnt->rect.height < bg_model->params.minArea )
{ {
//delete small contour //delete small contour
prev_seq = seq->h_prev; prev_seq = seq->h_prev;
if( prev_seq ) if( prev_seq )
{ {
prev_seq->h_next = seq->h_next; prev_seq->h_next = seq->h_next;
if( seq->h_next ) seq->h_next->h_prev = prev_seq; if( seq->h_next ) seq->h_next->h_prev = prev_seq;
} }
else else
{ {
first_seq = seq->h_next; first_seq = seq->h_next;
if( seq->h_next ) seq->h_next->h_prev = NULL; if( seq->h_next ) seq->h_next->h_prev = NULL;
} }
} }
else else
{ {
region_count++; region_count++;
} }
} }
bg_model->foreground_regions = first_seq; bg_model->foreground_regions = first_seq;
cvZero(bg_model->foreground); cvZero(bg_model->foreground);
cvDrawContours(bg_model->foreground, first_seq, CV_RGB(0, 0, 255), CV_RGB(0, 0, 255), 10, -1); cvDrawContours(bg_model->foreground, first_seq, CV_RGB(0, 0, 255), CV_RGB(0, 0, 255), 10, -1);
return region_count; return region_count;
} }
return 1; return 1;
} }
...@@ -1196,19 +1197,19 @@ BackgroundSubtractorMOG2::BackgroundSubtractorMOG2() ...@@ -1196,19 +1197,19 @@ BackgroundSubtractorMOG2::BackgroundSubtractorMOG2()
nframes = 0; nframes = 0;
history = defaultHistory2; history = defaultHistory2;
varThreshold = defaultVarThreshold2; varThreshold = defaultVarThreshold2;
bShadowDetection = 1; bShadowDetection = 1;
nmixtures = defaultNMixtures2; nmixtures = defaultNMixtures2;
backgroundRatio = defaultBackgroundRatio2; backgroundRatio = defaultBackgroundRatio2;
fVarInit = defaultVarInit2; fVarInit = defaultVarInit2;
fVarMax = defaultVarMax2; fVarMax = defaultVarMax2;
fVarMin = defaultVarMin2; fVarMin = defaultVarMin2;
varThresholdGen = defaultVarThresholdGen2; varThresholdGen = defaultVarThresholdGen2;
fCT = defaultfCT2; fCT = defaultfCT2;
nShadowDetection = defaultnShadowDetection2; nShadowDetection = defaultnShadowDetection2;
fTau = defaultfTau; fTau = defaultfTau;
} }
BackgroundSubtractorMOG2::BackgroundSubtractorMOG2(int _history, float _varThreshold, bool _bShadowDetection) BackgroundSubtractorMOG2::BackgroundSubtractorMOG2(int _history, float _varThreshold, bool _bShadowDetection)
...@@ -1218,19 +1219,19 @@ BackgroundSubtractorMOG2::BackgroundSubtractorMOG2(int _history, float _varThre ...@@ -1218,19 +1219,19 @@ BackgroundSubtractorMOG2::BackgroundSubtractorMOG2(int _history, float _varThre
nframes = 0; nframes = 0;
history = _history > 0 ? _history : defaultHistory2; history = _history > 0 ? _history : defaultHistory2;
varThreshold = (_varThreshold>0)? _varThreshold : defaultVarThreshold2; varThreshold = (_varThreshold>0)? _varThreshold : defaultVarThreshold2;
bShadowDetection = _bShadowDetection; bShadowDetection = _bShadowDetection;
nmixtures = defaultNMixtures2; nmixtures = defaultNMixtures2;
backgroundRatio = defaultBackgroundRatio2; backgroundRatio = defaultBackgroundRatio2;
fVarInit = defaultVarInit2; fVarInit = defaultVarInit2;
fVarMax = defaultVarMax2; fVarMax = defaultVarMax2;
fVarMin = defaultVarMin2; fVarMin = defaultVarMin2;
varThresholdGen = defaultVarThresholdGen2; varThresholdGen = defaultVarThresholdGen2;
fCT = defaultfCT2; fCT = defaultfCT2;
nShadowDetection = defaultnShadowDetection2; nShadowDetection = defaultnShadowDetection2;
fTau = defaultfTau; fTau = defaultfTau;
} }
BackgroundSubtractorMOG2::~BackgroundSubtractorMOG2() BackgroundSubtractorMOG2::~BackgroundSubtractorMOG2()
...@@ -1245,15 +1246,15 @@ void BackgroundSubtractorMOG2::initialize(Size _frameSize, int _frameType) ...@@ -1245,15 +1246,15 @@ void BackgroundSubtractorMOG2::initialize(Size _frameSize, int _frameType)
nframes = 0; nframes = 0;
int nchannels = CV_MAT_CN(frameType); int nchannels = CV_MAT_CN(frameType);
CV_Assert( nchannels <= CV_BGFG_MOG2_NDMAX ); CV_Assert( nchannels <= CV_BGFG_MOG2_NDMAX );
// for each gaussian mixture of each pixel bg model we store ... // for each gaussian mixture of each pixel bg model we store ...
// the mixture weight (w), // the mixture weight (w),
// the mean (nchannels values) and // the mean (nchannels values) and
// the covariance // the covariance
bgmodel.create( 1, frameSize.height*frameSize.width*nmixtures*(2 + CV_BGFG_MOG2_NDMAX), CV_32F ); bgmodel.create( 1, frameSize.height*frameSize.width*nmixtures*(2 + CV_BGFG_MOG2_NDMAX), CV_32F );
//make the array for keeping track of the used modes per pixel - all zeros at start //make the array for keeping track of the used modes per pixel - all zeros at start
bgmodelUsedModes.create(frameSize,CV_8U); bgmodelUsedModes.create(frameSize,CV_8U);
bgmodelUsedModes = Scalar::all(0); bgmodelUsedModes = Scalar::all(0);
} }
...@@ -1273,22 +1274,22 @@ void BackgroundSubtractorMOG2::operator()(InputArray _image, OutputArray _fgmask ...@@ -1273,22 +1274,22 @@ void BackgroundSubtractorMOG2::operator()(InputArray _image, OutputArray _fgmask
CV_Assert(learningRate >= 0); CV_Assert(learningRate >= 0);
CvMat _cimage = image, _cfgmask = fgmask; CvMat _cimage = image, _cfgmask = fgmask;
if (learningRate > 0) if (learningRate > 0)
icvUpdatePixelBackgroundGMM2( &_cimage, &_cfgmask, icvUpdatePixelBackgroundGMM2( &_cimage, &_cfgmask,
(CvPBGMMGaussian*) bgmodel.data, (CvPBGMMGaussian*) bgmodel.data,
bgmodelUsedModes.data, bgmodelUsedModes.data,
nmixtures,//nM nmixtures,//nM
varThreshold,//fTb varThreshold,//fTb
backgroundRatio,//fTB backgroundRatio,//fTB
varThresholdGen,//fTg, varThresholdGen,//fTg,
fVarInit, fVarInit,
fVarMax, fVarMax,
fVarMin, fVarMin,
fCT, fCT,
fTau, fTau,
bShadowDetection, bShadowDetection,
nShadowDetection, nShadowDetection,
float(learningRate)); float(learningRate));
} }
void BackgroundSubtractorMOG2::getBackgroundImage(OutputArray backgroundImage) const void BackgroundSubtractorMOG2::getBackgroundImage(OutputArray backgroundImage) const
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment