Commit 311feb21 authored by Maksim Shabunin's avatar Maksim Shabunin

bgsegm: several fixes:

- descriptor Mat access unsigned -> int
- do not use types uint8_t, etc. from C++11
- fixed uninitialized memory access
- minor cosmetic modifications
parent 42b0e13a
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
#include "precomp.hpp" #include "precomp.hpp"
#include <opencv2/calib3d.hpp> #include <opencv2/calib3d.hpp>
#include <iostream> #include <iostream>
#include "opencv2/core/cvdef.h"
namespace cv namespace cv
{ {
...@@ -66,8 +67,7 @@ const float LSBPtau = 0.05f; ...@@ -66,8 +67,7 @@ const float LSBPtau = 0.05f;
#include <intrin.h> #include <intrin.h>
#pragma intrinsic(__popcnt) #pragma intrinsic(__popcnt)
#endif #endif
inline int LSBPDist32(unsigned n) {
inline uint32_t LSBPDist32(uint32_t n) {
#if defined(__GNUC__) || defined(__clang__) #if defined(__GNUC__) || defined(__clang__)
return __builtin_popcount(n); return __builtin_popcount(n);
#elif defined(_MSC_VER) #elif defined(_MSC_VER)
...@@ -138,7 +138,7 @@ inline float localSVD(float a11, float a12, float a13, float a21, float a22, flo ...@@ -138,7 +138,7 @@ inline float localSVD(float a11, float a12, float a13, float a21, float a22, flo
return std::sqrt(e2 / e1) + std::sqrt(e3 / e1); return std::sqrt(e2 / e1) + std::sqrt(e3 / e1);
} }
void removeNoise(Mat& fgMask, const Mat& compMask, const size_t threshold, const uint8_t filler) { void removeNoise(Mat& fgMask, const Mat& compMask, const size_t threshold, const uchar filler) {
const Size sz = fgMask.size(); const Size sz = fgMask.size();
Mat labels; Mat labels;
const int nComponents = connectedComponents(compMask, labels, 8, CV_32S); const int nComponents = connectedComponents(compMask, labels, 8, CV_32S);
...@@ -151,7 +151,7 @@ void removeNoise(Mat& fgMask, const Mat& compMask, const size_t threshold, const ...@@ -151,7 +151,7 @@ void removeNoise(Mat& fgMask, const Mat& compMask, const size_t threshold, const
for (int i = 0; i < sz.height; ++i) for (int i = 0; i < sz.height; ++i)
for (int j = 0; j < sz.width; ++j) for (int j = 0; j < sz.width; ++j)
if (compArea[labels.at<int>(i, j)] < threshold) if (compArea[labels.at<int>(i, j)] < threshold)
fgMask.at<uint8_t>(i, j) = filler; fgMask.at<uchar>(i, j) = filler;
} }
void FindSparseCorrLK(const Mat& src, const Mat& dst, std::vector<Point2f>& srcPoints, std::vector<Point2f>& dstPoints) { void FindSparseCorrLK(const Mat& src, const Mat& dst, std::vector<Point2f>& srcPoints, std::vector<Point2f>& dstPoints) {
...@@ -191,20 +191,20 @@ void FindSparseCorrLK(const Mat& src, const Mat& dst, std::vector<Point2f>& srcP ...@@ -191,20 +191,20 @@ void FindSparseCorrLK(const Mat& src, const Mat& dst, std::vector<Point2f>& srcP
class BackgroundSampleGSOC { class BackgroundSampleGSOC {
public: public:
Point3f color; Point3f color;
uint32_t desc; int desc;
uint64_t time; uint64 time;
uint64_t hits; uint64 hits;
BackgroundSampleGSOC(Point3f c = Point3f(), uint32_t d = 0, uint64_t t = 0, uint64_t h = 0) : color(c), desc(d), time(t), hits(h) {} BackgroundSampleGSOC(Point3f c = Point3f(), int d = 0, uint64 t = 0, uint64 h = 0) : color(c), desc(d), time(t), hits(h) {}
}; };
class BackgroundSampleLSBP { class BackgroundSampleLSBP {
public: public:
Point3f color; Point3f color;
uint32_t desc; int desc;
float minDecisionDist; float minDecisionDist;
BackgroundSampleLSBP(Point3f c = Point3f(), uint32_t d = 0, float mdd = 1e9f) : color(c), desc(d), minDecisionDist(mdd) {} BackgroundSampleLSBP(Point3f c = Point3f(), int d = 0, float mdd = 1e9f) : color(c), desc(d), minDecisionDist(mdd) {}
}; };
template<typename BackgroundSampleType> template<typename BackgroundSampleType>
...@@ -291,7 +291,7 @@ public: ...@@ -291,7 +291,7 @@ public:
samples[minInd] = sample; samples[minInd] = sample;
} }
Point3f getMean(int i, int j, uint64_t threshold) const { Point3f getMean(int i, int j, uint64 threshold) const {
const int end = i * stride + (j + 1) * nSamples; const int end = i * stride + (j + 1) * nSamples;
Point3f acc(0, 0, 0); Point3f acc(0, 0, 0);
int cnt = 0; int cnt = 0;
...@@ -317,13 +317,13 @@ class BackgroundModelLSBP : public BackgroundModel<BackgroundSampleLSBP> { ...@@ -317,13 +317,13 @@ class BackgroundModelLSBP : public BackgroundModel<BackgroundSampleLSBP> {
public: public:
BackgroundModelLSBP(Size sz, int S) : BackgroundModel(sz, S) {}; BackgroundModelLSBP(Size sz, int S) : BackgroundModel(sz, S) {};
int countMatches(int i, int j, const Point3f& color, uint32_t desc, float threshold, uint32_t descThreshold, float& minDist) const { int countMatches(int i, int j, const Point3f& color, int desc, float threshold, int descThreshold, float& minDist) const {
const int end = i * stride + (j + 1) * nSamples; const int end = i * stride + (j + 1) * nSamples;
int count = 0; int count = 0;
minDist = 1e9; minDist = 1e9;
for (int k = i * stride + j * nSamples; k < end; ++k) { for (int k = i * stride + j * nSamples; k < end; ++k) {
const float dist = L1dist(color - samples[k].color); const float dist = L1dist(color - samples[k].color);
if (dist < threshold && LSBPDist32(desc ^ samples[k].desc) < descThreshold) if (dist < threshold && LSBPDist32(static_cast<unsigned>(desc ^ samples[k].desc)) < descThreshold)
++count; ++count;
if (dist < minDist) if (dist < minDist)
minDist = dist; minDist = dist;
...@@ -390,7 +390,7 @@ public: ...@@ -390,7 +390,7 @@ public:
void operator()(const Range &range) const { void operator()(const Range &range) const {
for (int index = range.start; index < range.end; ++index) { for (int index = range.start; index < range.end; ++index) {
const int i = index / sz.width, j = index % sz.width; const int i = index / sz.width, j = index % sz.width;
uint32_t& descVal = desc.at<uint32_t>(i, j); int& descVal = desc.at<int>(i, j);
descVal = 0; descVal = 0;
const float centerVal = localSVDValues.at<float>(i, j); const float centerVal = localSVDValues.at<float>(i, j);
...@@ -398,7 +398,7 @@ public: ...@@ -398,7 +398,7 @@ public:
const int ri = i + LSBPSamplePoints[n].y; const int ri = i + LSBPSamplePoints[n].y;
const int rj = j + LSBPSamplePoints[n].x; const int rj = j + LSBPSamplePoints[n].x;
if (ri >= 0 && rj >= 0 && ri < sz.height && rj < sz.width && std::abs(localSVDValues.at<float>(ri, rj) - centerVal) > LSBPtau) if (ri >= 0 && rj >= 0 && ri < sz.height && rj < sz.width && std::abs(localSVDValues.at<float>(ri, rj) - centerVal) > LSBPtau)
descVal |= uint32_t(1U) << n; descVal |= int(1U) << n;
} }
} }
} }
...@@ -459,12 +459,12 @@ class BackgroundSubtractorGSOCImpl : public BackgroundSubtractorGSOC { ...@@ -459,12 +459,12 @@ class BackgroundSubtractorGSOCImpl : public BackgroundSubtractorGSOC {
private: private:
Ptr<BackgroundModelGSOC> backgroundModel; Ptr<BackgroundModelGSOC> backgroundModel;
Ptr<BackgroundModelGSOC> backgroundModelPrev; Ptr<BackgroundModelGSOC> backgroundModelPrev;
uint64_t currentTime; uint64 currentTime;
const int motionCompensation; const int motionCompensation;
const int nSamples; const int nSamples;
const float replaceRate; const float replaceRate;
const float propagationRate; const float propagationRate;
const uint64_t hitsThreshold; const uint64 hitsThreshold;
const float alpha; const float alpha;
const float beta; const float beta;
const float blinkingSupressionDecay; const float blinkingSupressionDecay;
...@@ -577,7 +577,7 @@ public: ...@@ -577,7 +577,7 @@ public:
BackgroundSampleGSOC& sample = (* backgroundModel)(k); BackgroundSampleGSOC& sample = (* backgroundModel)(k);
if (minDist > threshold) { if (minDist > threshold) {
fgMask.at<uint8_t>(i, j) = 255; fgMask.at<uchar>(i, j) = 255;
if (bgs->rng.uniform(0.0f, 1.0f) < bgs->replaceRate) if (bgs->rng.uniform(0.0f, 1.0f) < bgs->replaceRate)
backgroundModel->replaceOldest(i, j, BackgroundSampleGSOC(frame.at<Point3f>(i, j), 0, bgs->currentTime)); backgroundModel->replaceOldest(i, j, BackgroundSampleGSOC(frame.at<Point3f>(i, j), 0, bgs->currentTime));
...@@ -600,7 +600,7 @@ public: ...@@ -600,7 +600,7 @@ public:
backgroundModel->replaceOldest(i, j - 1, sample); backgroundModel->replaceOldest(i, j - 1, sample);
} }
fgMask.at<uint8_t>(i, j) = 0; fgMask.at<uchar>(i, j) = 0;
} }
} }
} }
...@@ -637,25 +637,25 @@ public: ...@@ -637,25 +637,25 @@ public:
else else
R.at<float>(i, j) *= 1 + bgs->Rincdec; R.at<float>(i, j) *= 1 + bgs->Rincdec;
if (backgroundModel->countMatches(i, j, frame.at<Point3f>(i, j), LSBPDesc.at<uint32_t>(i, j), R.at<float>(i, j), bgs->LSBPthreshold, minDist) < bgs->minCount) { if (backgroundModel->countMatches(i, j, frame.at<Point3f>(i, j), LSBPDesc.at<int>(i, j), R.at<float>(i, j), bgs->LSBPthreshold, minDist) < bgs->minCount) {
fgMask.at<uint8_t>(i, j) = 255; fgMask.at<uchar>(i, j) = 255;
T.at<float>(i, j) += bgs->Tinc / DMean; T.at<float>(i, j) += bgs->Tinc / DMean;
} }
else { else {
fgMask.at<uint8_t>(i, j) = 0; fgMask.at<uchar>(i, j) = 0;
T.at<float>(i, j) -= bgs->Tdec / DMean; T.at<float>(i, j) -= bgs->Tdec / DMean;
if (bgs->rng.uniform(0.0f, 1.0f) < 1 / T.at<float>(i, j)) if (bgs->rng.uniform(0.0f, 1.0f) < 1 / T.at<float>(i, j))
(* backgroundModel)(i, j, bgs->rng.uniform(0, bgs->nSamples)) = BackgroundSampleLSBP(frame.at<Point3f>(i, j), LSBPDesc.at<uint32_t>(i, j), minDist); (* backgroundModel)(i, j, bgs->rng.uniform(0, bgs->nSamples)) = BackgroundSampleLSBP(frame.at<Point3f>(i, j), LSBPDesc.at<int>(i, j), minDist);
if (bgs->rng.uniform(0.0f, 1.0f) < 1 / T.at<float>(i, j)) { if (bgs->rng.uniform(0.0f, 1.0f) < 1 / T.at<float>(i, j)) {
const int oi = i + bgs->rng.uniform(-1, 2); const int oi = i + bgs->rng.uniform(-1, 2);
const int oj = j + bgs->rng.uniform(-1, 2); const int oj = j + bgs->rng.uniform(-1, 2);
if (oi >= 0 && oi < sz.height && oj >= 0 && oj < sz.width) if (oi >= 0 && oi < sz.height && oj >= 0 && oj < sz.width)
(* backgroundModel)(oi, oj, bgs->rng.uniform(0, bgs->nSamples)) = BackgroundSampleLSBP(frame.at<Point3f>(oi, oj), LSBPDesc.at<uint32_t>(oi, oj), minDist); (* backgroundModel)(oi, oj, bgs->rng.uniform(0, bgs->nSamples)) = BackgroundSampleLSBP(frame.at<Point3f>(oi, oj), LSBPDesc.at<int>(oi, oj), minDist);
} }
} }
...@@ -729,9 +729,9 @@ void BackgroundSubtractorGSOCImpl::apply(InputArray _image, OutputArray _fgmask, ...@@ -729,9 +729,9 @@ void BackgroundSubtractorGSOCImpl::apply(InputArray _image, OutputArray _fgmask,
if (backgroundModel.empty()) { if (backgroundModel.empty()) {
backgroundModel = makePtr<BackgroundModelGSOC>(sz, nSamples); backgroundModel = makePtr<BackgroundModelGSOC>(sz, nSamples);
backgroundModelPrev = makePtr<BackgroundModelGSOC>(sz, nSamples); backgroundModelPrev = makePtr<BackgroundModelGSOC>(sz, nSamples);
distMovingAvg = Mat(sz, CV_32F, 0.005f); distMovingAvg = Mat(sz, CV_32F, Scalar::all(0.005f));
prevFgMask = Mat(sz, CV_8U); prevFgMask = Mat(sz, CV_8U, Scalar::all(0));
blinkingSupression = Mat(sz, CV_32F, 0.0f); blinkingSupression = Mat(sz, CV_32F, Scalar::all(0.0f));
for (int i = 0; i < sz.height; ++i) for (int i = 0; i < sz.height; ++i)
for (int j = 0; j < sz.width; ++j) { for (int j = 0; j < sz.width; ++j) {
...@@ -799,7 +799,7 @@ void BackgroundSubtractorGSOCImpl::getBackgroundImage(OutputArray _backgroundIma ...@@ -799,7 +799,7 @@ void BackgroundSubtractorGSOCImpl::getBackgroundImage(OutputArray _backgroundIma
Mat backgroundImage = _backgroundImage.getMat(); Mat backgroundImage = _backgroundImage.getMat();
for (int i = 0; i < sz.height; ++i) for (int i = 0; i < sz.height; ++i)
for (int j = 0; j < sz.width; ++j) for (int j = 0; j < sz.width; ++j)
backgroundImage.at< Point3_<uint8_t> >(i, j) = backgroundModel->getMean(i, j, hitsThreshold) * 255; backgroundImage.at< Point3_<uchar> >(i, j) = backgroundModel->getMean(i, j, hitsThreshold) * 255;
} }
BackgroundSubtractorLSBPImpl::BackgroundSubtractorLSBPImpl(int _mc, BackgroundSubtractorLSBPImpl::BackgroundSubtractorLSBPImpl(int _mc,
...@@ -864,14 +864,11 @@ void BackgroundSubtractorLSBPImpl::apply(InputArray _image, OutputArray _fgmask, ...@@ -864,14 +864,11 @@ void BackgroundSubtractorLSBPImpl::apply(InputArray _image, OutputArray _fgmask,
cvtColor(frame, frame, COLOR_GRAY2BGR); cvtColor(frame, frame, COLOR_GRAY2BGR);
if (frame.depth() != CV_32F) { if (frame.depth() != CV_32F) {
frame.convertTo(frame, CV_32F); frame.convertTo(frame, CV_32F, 1.0/255);
frame /= 255;
} }
Mat LSBPDesc(sz, CV_32S);
LSBPDesc = 0;
CV_Assert(frame.channels() == 3); CV_Assert(frame.channels() == 3);
Mat LSBPDesc(sz, CV_32S, Scalar::all(0));
BackgroundSubtractorLSBPDesc::compute(LSBPDesc, frame, LSBPSamplePoints); BackgroundSubtractorLSBPDesc::compute(LSBPDesc, frame, LSBPSamplePoints);
...@@ -885,7 +882,7 @@ void BackgroundSubtractorLSBPImpl::apply(InputArray _image, OutputArray _fgmask, ...@@ -885,7 +882,7 @@ void BackgroundSubtractorLSBPImpl::apply(InputArray _image, OutputArray _fgmask,
for (int i = 0; i < sz.height; ++i) for (int i = 0; i < sz.height; ++i)
for (int j = 0; j < sz.width; ++j) { for (int j = 0; j < sz.width; ++j) {
BackgroundSampleLSBP sample(frame.at<Point3f>(i, j), LSBPDesc.at<uint32_t>(i, j)); BackgroundSampleLSBP sample(frame.at<Point3f>(i, j), LSBPDesc.at<int>(i, j));
for (int k = 0; k < nSamples; ++k) { for (int k = 0; k < nSamples; ++k) {
(* backgroundModel)(i, j, k) = sample; (* backgroundModel)(i, j, k) = sample;
(* backgroundModelPrev)(i, j, k) = sample; (* backgroundModelPrev)(i, j, k) = sample;
...@@ -937,7 +934,7 @@ void BackgroundSubtractorLSBPImpl::getBackgroundImage(OutputArray _backgroundIma ...@@ -937,7 +934,7 @@ void BackgroundSubtractorLSBPImpl::getBackgroundImage(OutputArray _backgroundIma
Mat backgroundImage = _backgroundImage.getMat(); Mat backgroundImage = _backgroundImage.getMat();
for (int i = 0; i < sz.height; ++i) for (int i = 0; i < sz.height; ++i)
for (int j = 0; j < sz.width; ++j) for (int j = 0; j < sz.width; ++j)
backgroundImage.at< Point3_<uint8_t> >(i, j) = backgroundModel->getMean(i, j) * 255; backgroundImage.at< Point3_<uchar> >(i, j) = backgroundModel->getMean(i, j) * 255;
} }
Ptr<BackgroundSubtractorGSOC> createBackgroundSubtractorGSOC(int mc, Ptr<BackgroundSubtractorGSOC> createBackgroundSubtractorGSOC(int mc,
......
...@@ -64,7 +64,7 @@ inline int within(int a, int b, int c) { ...@@ -64,7 +64,7 @@ inline int within(int a, int b, int c) {
return (((a) <= (b)) && ((b) <= (c))) ? 1 : 0; return (((a) <= (b)) && ((b) <= (c))) ? 1 : 0;
} }
void bilinearInterp(uint8_t* dest, double x, double y, unsigned bpp, const uint8_t** values) { void bilinearInterp(uchar* dest, double x, double y, unsigned bpp, const uchar** values) {
x = std::fmod(x, 1.0); x = std::fmod(x, 1.0);
y = std::fmod(y, 1.0); y = std::fmod(y, 1.0);
...@@ -76,13 +76,13 @@ void bilinearInterp(uint8_t* dest, double x, double y, unsigned bpp, const uint8 ...@@ -76,13 +76,13 @@ void bilinearInterp(uint8_t* dest, double x, double y, unsigned bpp, const uint8
for (unsigned i = 0; i < bpp; i++) { for (unsigned i = 0; i < bpp; i++) {
double m0 = (1.0 - x) * values[0][i] + x * values[1][i]; double m0 = (1.0 - x) * values[0][i] + x * values[1][i];
double m1 = (1.0 - x) * values[2][i] + x * values[3][i]; double m1 = (1.0 - x) * values[2][i] + x * values[3][i];
dest[i] = (uint8_t) ((1.0 - y) * m0 + y * m1); dest[i] = (uchar) ((1.0 - y) * m0 + y * m1);
} }
} }
// Static background is a way too easy test. We will add distortion to it. // Static background is a way too easy test. We will add distortion to it.
void waveDistortion(const uint8_t* src, uint8_t* dst, int width, int height, int bypp, double amplitude, double wavelength, double phase) { void waveDistortion(const uchar* src, uchar* dst, int width, int height, int bypp, double amplitude, double wavelength, double phase) {
const uint8_t zeroes[4] = {0, 0, 0, 0}; const uchar zeroes[4] = {0, 0, 0, 0};
const long rowsiz = width * bypp; const long rowsiz = width * bypp;
const double xhsiz = (double) width / 2.0; const double xhsiz = (double) width / 2.0;
const double yhsiz = (double) height / 2.0; const double yhsiz = (double) height / 2.0;
...@@ -104,7 +104,7 @@ void waveDistortion(const uint8_t* src, uint8_t* dst, int width, int height, int ...@@ -104,7 +104,7 @@ void waveDistortion(const uint8_t* src, uint8_t* dst, int width, int height, int
wavelength *= 2; wavelength *= 2;
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
uint8_t* dest = dst; uchar* dest = dst;
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
const double dx = x * xscale; const double dx = x * xscale;
...@@ -116,13 +116,13 @@ void waveDistortion(const uint8_t* src, uint8_t* dst, int width, int height, int ...@@ -116,13 +116,13 @@ void waveDistortion(const uint8_t* src, uint8_t* dst, int width, int height, int
const int xi = clamp(int(needx), 0, width - 2); const int xi = clamp(int(needx), 0, width - 2);
const int yi = clamp(int(needy), 0, height - 2); const int yi = clamp(int(needy), 0, height - 2);
const uint8_t* p = src + rowsiz * yi + xi * bypp; const uchar* p = src + rowsiz * yi + xi * bypp;
const int x1_in = within(0, xi, width - 1); const int x1_in = within(0, xi, width - 1);
const int y1_in = within(0, yi, height - 1); const int y1_in = within(0, yi, height - 1);
const int x2_in = within(0, xi + 1, width - 1); const int x2_in = within(0, xi + 1, width - 1);
const int y2_in = within(0, yi + 1, height - 1); const int y2_in = within(0, yi + 1, height - 1);
const uint8_t* values[4]; const uchar* values[4];
if (x1_in && y1_in) if (x1_in && y1_in)
values[0] = p; values[0] = p;
......
...@@ -72,16 +72,16 @@ TEST(BackgroundSubtractor_LSBP, Discrimination) ...@@ -72,16 +72,16 @@ TEST(BackgroundSubtractor_LSBP, Discrimination)
Mat desc; Mat desc;
bgsegm::BackgroundSubtractorLSBPDesc::computeFromLocalSVDValues(desc, lsv, LSBPSamplePoints); bgsegm::BackgroundSubtractorLSBPDesc::computeFromLocalSVDValues(desc, lsv, LSBPSamplePoints);
Size sz = desc.size(); Size sz = desc.size();
std::set<uint32_t> distinctive_elements; std::set<int> distinctive_elements;
for (int i = 0; i < sz.height; ++i) for (int i = 0; i < sz.height; ++i)
for (int j = 0; j < sz.width; ++j) for (int j = 0; j < sz.width; ++j)
distinctive_elements.insert(desc.at<uint32_t>(i, j)); distinctive_elements.insert(desc.at<int>(i, j));
EXPECT_GE(distinctive_elements.size(), 35000U); EXPECT_GE(distinctive_elements.size(), 35000U);
} }
static double scoreBitwiseReduce(const Mat& mask, const Mat& gtMask, uint8_t v1, uint8_t v2) { static double scoreBitwiseReduce(const Mat& mask, const Mat& gtMask, uchar v1, uchar v2) {
Mat result; Mat result;
cv::bitwise_and(mask == v1, gtMask == v2, result); cv::bitwise_and(mask == v1, gtMask == v2, result);
return cv::countNonZero(result); return cv::countNonZero(result);
......
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