added support of all types to BackgroundSubtractorGMG

This commit is contained in:
Vladislav Vinogradov 2012-08-13 10:28:42 +04:00
parent 9c75ff43ba
commit 4dbc7600e7
2 changed files with 32 additions and 43 deletions

View File

@ -251,7 +251,7 @@ private:
int frameNum_; int frameNum_;
cv::Mat_<int> nfeatures_; cv::Mat_<int> nfeatures_;
cv::Mat_<int> colors_; cv::Mat_<uint> colors_;
cv::Mat_<float> weights_; cv::Mat_<float> weights_;
cv::Mat buf_; cv::Mat buf_;

View File

@ -91,7 +91,7 @@ void cv::BackgroundSubtractorGMG::initialize(cv::Size frameSize, double min, dou
namespace namespace
{ {
float findFeature(int color, const int* colors, const float* weights, int nfeatures) float findFeature(uint color, const uint* colors, const float* weights, int nfeatures)
{ {
for (int i = 0; i < nfeatures; ++i) for (int i = 0; i < nfeatures; ++i)
{ {
@ -116,7 +116,7 @@ namespace
} }
} }
bool insertFeature(int color, float weight, int* colors, float* weights, int& nfeatures, int maxFeatures) bool insertFeature(uint color, float weight, uint* colors, float* weights, int& nfeatures, int maxFeatures)
{ {
int idx = -1; int idx = -1;
for (int i = 0; i < nfeatures; ++i) for (int i = 0; i < nfeatures; ++i)
@ -134,7 +134,7 @@ namespace
{ {
// move feature to beginning of list // move feature to beginning of list
::memmove(colors + 1, colors, idx * sizeof(int)); ::memmove(colors + 1, colors, idx * sizeof(uint));
::memmove(weights + 1, weights, idx * sizeof(float)); ::memmove(weights + 1, weights, idx * sizeof(float));
colors[0] = color; colors[0] = color;
@ -144,7 +144,7 @@ namespace
{ {
// discard oldest feature // discard oldest feature
::memmove(colors + 1, colors, (nfeatures - 1) * sizeof(int)); ::memmove(colors + 1, colors, (nfeatures - 1) * sizeof(uint));
::memmove(weights + 1, weights, (nfeatures - 1) * sizeof(float)); ::memmove(weights + 1, weights, (nfeatures - 1) * sizeof(float));
colors[0] = color; colors[0] = color;
@ -166,45 +166,31 @@ namespace
namespace namespace
{ {
template <int cn> struct Quantization_
{
template <typename T>
static inline int apply(T val, double minVal, double maxVal, int quantizationLevels)
{
int res = 0;
res |= static_cast<int>((val[0] - minVal) * quantizationLevels / (maxVal - minVal));
res |= static_cast<int>((val[1] - minVal) * quantizationLevels / (maxVal - minVal)) << 8;
res |= static_cast<int>((val[2] - minVal) * quantizationLevels / (maxVal - minVal)) << 16;
return res;
}
};
template <> struct Quantization_<1>
{
template <typename T>
static inline int apply(T val, double minVal, double maxVal, int quantizationLevels)
{
return static_cast<int>((val - minVal) * quantizationLevels / (maxVal - minVal));
}
};
template <typename T> struct Quantization template <typename T> struct Quantization
{ {
static int apply(const void* src_, int x, double minVal, double maxVal, int quantizationLevels) static uint apply(const void* src_, int x, int cn, double minVal, double maxVal, int quantizationLevels)
{ {
const T* src = static_cast<const T*>(src_); const T* src = static_cast<const T*>(src_);
return Quantization_<cv::DataType<T>::channels>::apply(src[x], minVal, maxVal, quantizationLevels); src += x * cn;
uint res = 0;
for (int i = 0, shift = 0; i < cn; ++i, ++src, shift += 8)
res |= static_cast<int>((*src - minVal) * quantizationLevels / (maxVal - minVal)) << shift;
return res;
} }
}; };
class GMG_LoopBody : public cv::ParallelLoopBody class GMG_LoopBody : public cv::ParallelLoopBody
{ {
public: public:
GMG_LoopBody(const cv::Mat& frame, const cv::Mat& fgmask, const cv::Mat_<int>& nfeatures, const cv::Mat_<int>& colors, const cv::Mat_<float>& weights, GMG_LoopBody(const cv::Mat& frame, const cv::Mat& fgmask, const cv::Mat_<int>& nfeatures, const cv::Mat_<uint>& colors, const cv::Mat_<float>& weights,
int maxFeatures, double learningRate, int numInitializationFrames, int quantizationLevels, double backgroundPrior, double decisionThreshold, int maxFeatures, double learningRate, int numInitializationFrames, int quantizationLevels, double backgroundPrior, double decisionThreshold,
double maxVal, double minVal, int frameNum, bool updateBackgroundModel) : double maxVal, double minVal, int frameNum, bool updateBackgroundModel) :
frame_(frame), fgmask_(fgmask), nfeatures_(nfeatures), colors_(colors), weights_(weights), frame_(frame), fgmask_(fgmask), nfeatures_(nfeatures), colors_(colors), weights_(weights),
maxFeatures_(maxFeatures), learningRate_(learningRate), numInitializationFrames_(numInitializationFrames), maxFeatures_(maxFeatures), learningRate_(learningRate), numInitializationFrames_(numInitializationFrames), quantizationLevels_(quantizationLevels),
quantizationLevels_(quantizationLevels), backgroundPrior_(backgroundPrior), decisionThreshold_(decisionThreshold), backgroundPrior_(backgroundPrior), decisionThreshold_(decisionThreshold), updateBackgroundModel_(updateBackgroundModel),
maxVal_(maxVal), minVal_(minVal), frameNum_(frameNum), updateBackgroundModel_(updateBackgroundModel) maxVal_(maxVal), minVal_(minVal), frameNum_(frameNum)
{ {
} }
@ -216,7 +202,7 @@ namespace
mutable cv::Mat_<uchar> fgmask_; mutable cv::Mat_<uchar> fgmask_;
mutable cv::Mat_<int> nfeatures_; mutable cv::Mat_<int> nfeatures_;
mutable cv::Mat_<int> colors_; mutable cv::Mat_<uint> colors_;
mutable cv::Mat_<float> weights_; mutable cv::Mat_<float> weights_;
int maxFeatures_; int maxFeatures_;
@ -234,20 +220,23 @@ namespace
void GMG_LoopBody::operator() (const cv::Range& range) const void GMG_LoopBody::operator() (const cv::Range& range) const
{ {
typedef int (*func_t)(const void* src_, int x, double minVal, double maxVal, int quantizationLevels); typedef uint (*func_t)(const void* src_, int x, int cn, double minVal, double maxVal, int quantizationLevels);
static const func_t funcs[6][4] = static const func_t funcs[] =
{ {
{Quantization<uchar>::apply, 0, Quantization<cv::Vec3b>::apply, Quantization<cv::Vec4b>::apply}, Quantization<uchar>::apply,
{0,0,0,0}, Quantization<schar>::apply,
{Quantization<ushort>::apply, 0, Quantization<cv::Vec3w>::apply, Quantization<cv::Vec4w>::apply}, Quantization<ushort>::apply,
{0,0,0,0}, Quantization<short>::apply,
{0,0,0,0}, Quantization<int>::apply,
{Quantization<float>::apply, 0, Quantization<cv::Vec3f>::apply, Quantization<cv::Vec4f>::apply}, Quantization<float>::apply,
Quantization<double>::apply
}; };
const func_t func = funcs[frame_.depth()][frame_.channels() - 1]; const func_t func = funcs[frame_.depth()];
CV_Assert(func != 0); CV_Assert(func != 0);
const int cn = frame_.channels();
for (int y = range.start, featureIdx = y * frame_.cols; y < range.end; ++y) for (int y = range.start, featureIdx = y * frame_.cols; y < range.end; ++y)
{ {
const uchar* frame_row = frame_.ptr(y); const uchar* frame_row = frame_.ptr(y);
@ -257,10 +246,10 @@ namespace
for (int x = 0; x < frame_.cols; ++x, ++featureIdx) for (int x = 0; x < frame_.cols; ++x, ++featureIdx)
{ {
int nfeatures = nfeatures_row[x]; int nfeatures = nfeatures_row[x];
int* colors = colors_[featureIdx]; uint* colors = colors_[featureIdx];
float* weights = weights_[featureIdx]; float* weights = weights_[featureIdx];
int newFeatureColor = func(frame_row, x, minVal_, maxVal_, quantizationLevels_); uint newFeatureColor = func(frame_row, x, cn, minVal_, maxVal_, quantizationLevels_);
bool isForeground = false; bool isForeground = false;